/*
 * Copyright 2020 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <atomic>
#include <string_view>

#include "arch/context.h"
#include "art_method-inl.h"
#include "jni.h"
#include "scoped_thread_state_change.h"
#include "stack.h"
#include "thread.h"

namespace art {
namespace StackWalkConcurrentInstrument {

std::atomic<bool> instrument_waiting = false;
std::atomic<bool> instrumented = false;

// Spin lock.
static void WaitForInstrument() REQUIRES_SHARED(Locks::mutator_lock_) {
  ScopedThreadSuspension sts(Thread::Current(), ThreadState::kWaitingForDeoptimization);
  instrument_waiting = true;
  while (!instrumented) {
  }
}

class SelfStackWalkVisitor : public StackVisitor {
 public:
  explicit SelfStackWalkVisitor(Thread* thread) REQUIRES_SHARED(Locks::mutator_lock_)
      : StackVisitor(thread, Context::Create(), StackWalkKind::kIncludeInlinedFrames) {}

  bool VisitFrame() override REQUIRES_SHARED(Locks::mutator_lock_) {
    if (GetMethod()->GetNameView() == "$noinline$f") {
      CHECK(!found_f_);
      found_f_ = true;
    } else if (GetMethod()->GetNameView() == "$noinline$g") {
      CHECK(!found_g_);
      found_g_ = true;
      WaitForInstrument();
    } else if (GetMethod()->GetNameView() == "$noinline$h") {
      CHECK(!found_h_);
      found_h_ = true;
    }
    return true;
  }

  bool found_f_ = false;
  bool found_g_ = false;
  bool found_h_ = false;
};

extern "C" JNIEXPORT void JNICALL Java_Main_resetTest(JNIEnv*, jobject) {
  instrument_waiting = false;
  instrumented = false;
}

extern "C" JNIEXPORT void JNICALL Java_Main_doSelfStackWalk(JNIEnv*, jobject) {
  ScopedObjectAccess soa(Thread::Current());
  SelfStackWalkVisitor sswv(Thread::Current());
  sswv.WalkStack();
  CHECK(sswv.found_f_);
  CHECK(sswv.found_g_);
  CHECK(sswv.found_h_);
}
extern "C" JNIEXPORT void JNICALL Java_Main_waitAndInstrumentStack(JNIEnv*,
                                                                   jobject,
                                                                   jobject target) {
  while (!instrument_waiting) {
  }
  Thread* other = Runtime::Current()->GetThreadList()->SuspendThreadByPeer(
      target, SuspendReason::kInternal);
  CHECK(other != nullptr);
  ScopedSuspendAll ssa(__FUNCTION__);
  Runtime::Current()->GetInstrumentation()->InstrumentThreadStack(other,
                                                                  /* force_deopt= */ false);
  bool resumed = art::Runtime::Current()->GetThreadList()->Resume(other, SuspendReason::kInternal);
  CHECK(resumed);
  instrumented = true;
  return;
}

}  // namespace StackWalkConcurrentInstrument
}  // namespace art
