Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

remove test #1425

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions API/hermes/hermes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1326,10 +1326,10 @@ void HermesRuntime::registerForProfiling() {
#if HERMESVM_SAMPLING_PROFILER_AVAILABLE
vm::Runtime &runtime = impl(this)->runtime_;
if (runtime.samplingProfiler) {
::hermes::hermes_fatal(
"re-registering HermesVMs for profiling is not allowed");
runtime.samplingProfiler->setRuntimeThread();
} else {
runtime.samplingProfiler = ::hermes::vm::SamplingProfiler::create(runtime);
}
runtime.samplingProfiler = ::hermes::vm::SamplingProfiler::create(runtime);
#else
throwHermesNotCompiledWithSamplingProfilerSupport();
#endif // HERMESVM_SAMPLING_PROFILER_AVAILABLE
Expand Down
5 changes: 4 additions & 1 deletion API/hermes/hermes.h
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,10 @@ class HERMES_EXPORT HermesRuntime : public jsi::Runtime {
const DebugFlags &debugFlags);
#endif

/// Register this runtime for sampling profiler.
/// Register this runtime and thread for sampling profiler. Before using the
/// runtime on another thread, invoke this function again from the new thread
/// to make the sampling profiler target the new thread (and forget the old
/// thread).
void registerForProfiling();
/// Unregister this runtime for sampling profiler.
void unregisterForProfiling();
Expand Down
15 changes: 12 additions & 3 deletions include/hermes/VM/Profiler/SamplingProfiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -109,9 +109,11 @@ class SamplingProfiler {
};

/// \return true if this SamplingProfiler belongs to the current running
/// thread. Does not acquire any locks, and as such should not be used in
/// production.
bool belongsToCurrentThread() const;
/// thread. The current thread can change (e.g. in the time between
/// this function returning and the caller inspecting the value), so the
/// usefulness of this method depends upon knowledge of when the runtime
/// will switch threads.
bool belongsToCurrentThread();

/// \returns the NativeFunctionPtr for \p stackFrame. Caller must hold
/// runtimeDataLock_.
Expand Down Expand Up @@ -153,6 +155,9 @@ class SamplingProfiler {
/// domains.
std::mutex runtimeDataLock_;

/// Protect the current thread id.
std::mutex threadIdLock_;

protected:
/// Sampled stack traces overtime. Protected by runtimeDataLock_.
std::vector<StackTrace> sampledStacks_;
Expand Down Expand Up @@ -274,6 +279,10 @@ class SamplingProfiler {
/// suspend() that hansn't been resume()d yet.
void resume();

/// Inform the sampling profiler that the runtime will now be executing
/// bytecode on the current thread.
void setRuntimeThread();

protected:
explicit SamplingProfiler(Runtime &runtime);
};
Expand Down
25 changes: 17 additions & 8 deletions lib/VM/Profiler/SamplingProfilerPosix.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,10 +70,9 @@ struct SamplingProfilerPosix : SamplingProfiler {
SamplingProfilerPosix(Runtime &rt);
~SamplingProfilerPosix() override;

/// Thread that this profiler instance represents. This can currently only be
/// set from the constructor of SamplingProfiler, so we need to construct a
/// new SamplingProfiler every time the runtime is moved to a different
/// thread.
/// Thread that this profiler instance represents. This can be updated as the
/// runtime is invoked on different threads. Must only be accessed while
/// holding the threadIdLock_.
pthread_t currentThread_;

#if defined(HERMESVM_ENABLE_LOOM) && defined(__ANDROID__)
Expand Down Expand Up @@ -316,7 +315,10 @@ bool Sampler::platformSuspendVMAndWalkStack(SamplingProfiler *profiler) {
// acquired the updates to domains_.
self->profilerForSig_.store(profiler, std::memory_order_release);

// Signal target runtime thread to sample stack.
// Signal target runtime thread to sample stack. The threadIdLock_ is
// held ensuring the runtime won't start to be used on
// another thread before sampling begins.
std::lock_guard<std::mutex> lockGuard(posixProfiler->threadIdLock_);
pthread_kill(posixProfiler->currentThread_, SIGPROF);

// Threading: samplingDoneSem_ will synchronise this thread with the
Expand Down Expand Up @@ -470,9 +472,16 @@ std::unique_ptr<SamplingProfiler> SamplingProfiler::create(Runtime &rt) {
return std::make_unique<sampling_profiler::SamplingProfilerPosix>(rt);
}

bool SamplingProfiler::belongsToCurrentThread() const {
return static_cast<const sampling_profiler::SamplingProfilerPosix *>(this)
->currentThread_ == pthread_self();
bool SamplingProfiler::belongsToCurrentThread() {
auto profiler = static_cast<sampling_profiler::SamplingProfilerPosix *>(this);
std::lock_guard<std::mutex> lock(profiler->threadIdLock_);
return profiler->currentThread_ == pthread_self();
}

void SamplingProfiler::setRuntimeThread() {
auto profiler = static_cast<sampling_profiler::SamplingProfilerPosix *>(this);
std::lock_guard<std::mutex> lock(profiler->threadIdLock_);
profiler->currentThread_ = pthread_self();
}

} // namespace vm
Expand Down
46 changes: 32 additions & 14 deletions lib/VM/Profiler/SamplingProfilerWindows.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,21 @@

namespace hermes {
namespace vm {

/// Open the current thread and \return a handle to it. The handle must later
/// be closed with a call to the Win32 CloseHandle API.
static HANDLE openCurrentThread() {
return OpenThread(
THREAD_GET_CONTEXT | THREAD_SUSPEND_RESUME | THREAD_QUERY_INFORMATION,
false,
GetCurrentThreadId());
}

namespace sampling_profiler {
namespace {
struct SamplingProfilerWindows : SamplingProfiler {
SamplingProfilerWindows(Runtime &rt) : SamplingProfiler(rt) {
currentThread_ = OpenThread(
THREAD_GET_CONTEXT | THREAD_SUSPEND_RESUME | THREAD_QUERY_INFORMATION,
false,
GetCurrentThreadId());
currentThread_ = openCurrentThread();

#if defined(HERMESVM_ENABLE_LOOM)
fbloom_profilo_api()->fbloom_register_enable_for_loom_callback(
Expand All @@ -48,6 +55,8 @@ struct SamplingProfilerWindows : SamplingProfiler {
// TODO(T125910634): re-introduce the requirement for destroying the
// sampling profiler on the same thread in which it was created.
Sampler::get()->unregisterRuntime(this);

CloseHandle(currentThread_);
}

#if defined(HERMESVM_ENABLE_LOOM)
Expand Down Expand Up @@ -121,10 +130,8 @@ struct SamplingProfilerWindows : SamplingProfiler {
bool loomDataPushEnabled_{false};
#endif // defined(HERMESVM_ENABLE_LOOM)

/// Thread that this profiler instance represents. This can currently only
/// be set from the constructor of SamplingProfiler, so we need to construct
/// a new SamplingProfiler every time the runtime is moved to a different
/// thread.
/// Thread that this profiler instance represents. This can be updated
/// by later calls to SetRuntimeThread.
HANDLE currentThread_;
};
} // namespace
Expand Down Expand Up @@ -171,7 +178,10 @@ void Sampler::platformPostSampleStack(SamplingProfiler *localProfiler) {
bool Sampler::platformSuspendVMAndWalkStack(SamplingProfiler *profiler) {
auto *winProfiler = static_cast<SamplingProfilerWindows *>(profiler);

// Suspend the JS thread.
// Suspend the JS thread. The threadIdLock_ is held by the caller, ensuring
// the runtime won't start to be used on another thread before sampling
// begins.
std::lock_guard<std::mutex> lockGuard(winProfiler->threadIdLock_);
DWORD prevSuspendCount = SuspendThread(winProfiler->currentThread_);
if (prevSuspendCount == static_cast<DWORD>(-1)) {
return true;
Expand Down Expand Up @@ -200,11 +210,19 @@ std::unique_ptr<SamplingProfiler> SamplingProfiler::create(Runtime &rt) {
return std::make_unique<sampling_profiler::SamplingProfilerWindows>(rt);
}

bool SamplingProfiler::belongsToCurrentThread() const {
return GetThreadId(
static_cast<const sampling_profiler::SamplingProfilerWindows *>(
this)
->currentThread_) == GetCurrentThreadId();
bool SamplingProfiler::belongsToCurrentThread() {
auto profiler =
static_cast<sampling_profiler::SamplingProfilerWindows *>(this);
std::lock_guard<std::mutex> lock(profiler->threadIdLock_);
return GetThreadId(profiler->currentThread_) == GetCurrentThreadId();
}

void SamplingProfiler::setRuntimeThread() {
auto profiler =
static_cast<sampling_profiler::SamplingProfilerWindows *>(this);
std::lock_guard<std::mutex> lock(profiler->threadIdLock_);
CloseHandle(profiler->currentThread_);
profiler->currentThread_ = openCurrentThread();
}

} // namespace vm
Expand Down
1 change: 1 addition & 0 deletions unittests/VMRuntime/SamplingProfilerTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

#if HERMESVM_SAMPLING_PROFILER_AVAILABLE

#include "TestHelpers1.h"
#include "hermes/VM/Runtime.h"

#include <gtest/gtest.h>
Expand Down
Loading