Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(581)

Unified Diff: test/cctest/test-log.cc

Issue 171115: Linux profiler: check whether signal handler is called in the VM thread. (Closed)
Patch Set: Now dealing with multiple threads correctly, added test. Created 11 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« src/v8threads.cc ('K') | « src/v8threads.cc ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: test/cctest/test-log.cc
diff --git a/test/cctest/test-log.cc b/test/cctest/test-log.cc
index 5884a419a9baede2ef1ce1a16881898b96ec3bf8..dafd3aaad59afd6b9122f304461f82c300e68920 100644
--- a/test/cctest/test-log.cc
+++ b/test/cctest/test-log.cc
@@ -5,12 +5,15 @@
#ifdef ENABLE_LOGGING_AND_PROFILING
#ifdef __linux__
+#include <math.h>
+#include <pthread.h>
#include <signal.h>
#include <unistd.h>
-#endif
+#endif // __linux__
#include "v8.h"
#include "log.h"
+#include "v8threads.h"
#include "cctest.h"
using v8::internal::Address;
@@ -155,9 +158,10 @@ static bool was_sigprof_received = true;
#ifdef __linux__
struct sigaction old_sigprof_handler;
+pthread_t our_thread;
static void SigProfSignalHandler(int signal, siginfo_t* info, void* context) {
- if (signal != SIGPROF) return;
+ if (signal != SIGPROF || !pthread_equal(pthread_self(), our_thread)) return;
was_sigprof_received = true;
old_sigprof_handler.sa_sigaction(signal, info, context);
}
@@ -185,6 +189,7 @@ static int CheckThatProfilerWorks(int log_pos) {
// Intercept SIGPROF handler to make sure that the test process
// had received it. Under load, system can defer it causing test failure.
// It is important to execute this after 'ResumeProfiler'.
+ our_thread = pthread_self();
was_sigprof_received = false;
struct sigaction sa;
sa.sa_sigaction = SigProfSignalHandler;
@@ -280,6 +285,158 @@ TEST(ProfLazyMode) {
}
+// Profiling multiple threads that use V8 is currently only available on Linux.
+#ifdef __linux__
+
+namespace {
+
+class LoopingThread : public v8::internal::Thread {
+ public:
+ LoopingThread()
+ : v8::internal::Thread(),
+ semaphore_(v8::internal::OS::CreateSemaphore(0)),
+ run_(true) {
+ }
+
+ virtual ~LoopingThread() { delete semaphore_; }
+
+ void Run() {
+ self_ = pthread_self();
+ RunLoop();
+ }
+
+ void SendSigProf() { pthread_kill(self_, SIGPROF); }
+
+ void Stop() { run_ = false; }
+
+ bool WaitForRunning() { return semaphore_->Wait(1000000); }
+
+ protected:
+ bool IsRunning() { return run_; }
+
+ virtual void RunLoop() = 0;
+
+ void SetV8ThreadId() {
+ v8_thread_id_ = v8::V8::GetCurrentThreadId();
+ }
+
+ void SignalRunning() { semaphore_->Signal(); }
+
+ private:
+ v8::internal::Semaphore* semaphore_;
+ bool run_;
+ pthread_t self_;
+ int v8_thread_id_;
+};
+
+
+class LoopingJsThread : public LoopingThread {
+ public:
+ void RunLoop() {
+ {
+ v8::Locker locker;
+ CHECK(v8::internal::ThreadManager::HasId());
+ SetV8ThreadId();
+ }
+ while (IsRunning()) {
+ v8::Locker locker;
+ v8::HandleScope scope;
+ v8::Persistent<v8::Context> context = v8::Context::New();
+ v8::Context::Scope context_scope(context);
+ SignalRunning();
+ CompileAndRunScript(
+ "var j; for (var i=0; i<10000; ++i) { j = Math.sin(i); }");
+ context.Dispose();
+ i::OS::Sleep(1);
+ }
+ }
+};
+
+
+class LoopingNonJsThread : public LoopingThread {
+ public:
+ void RunLoop() {
+ v8::Locker locker;
+ v8::Unlocker unlocker;
+ // Now thread has V8's id, but will not run VM code.
+ CHECK(v8::internal::ThreadManager::HasId());
+ double i = 10;
+ SignalRunning();
+ while (IsRunning()) {
+ i = sin(i);
+ i::OS::Sleep(1);
+ }
+ }
+};
+
+
+class TestSampler : public v8::internal::Sampler {
+ public:
+ TestSampler()
+ : Sampler(0, true),
+ semaphore_(v8::internal::OS::CreateSemaphore(0)),
+ was_sample_stack_called_(false) {
+ }
+
+ ~TestSampler() { delete semaphore_; }
+
+ void SampleStack(v8::internal::TickSample*) {
+ was_sample_stack_called_ = true;
+ }
+
+ void Tick(v8::internal::TickSample*) { semaphore_->Signal(); }
+
+ bool WaitForTick() { return semaphore_->Wait(1000000); }
+
+ void Reset() { was_sample_stack_called_ = false; }
+
+ bool WasSampleStackCalled() { return was_sample_stack_called_; }
+
+ private:
+ v8::internal::Semaphore* semaphore_;
+ bool was_sample_stack_called_;
+};
+
+
+} // namespace
+
+TEST(ProfMultipleThreads) {
+ // V8 needs to be initialized before the first Locker
+ // instantiation. Otherwise, Top::Initialize will reset
+ // thread_id_ in ThreadTopLocal.
+ v8::HandleScope scope;
+ v8::Handle<v8::Context> env = v8::Context::New();
+ env->Enter();
+
+ LoopingJsThread jsThread;
+ jsThread.Start();
+ LoopingNonJsThread nonJsThread;
+ nonJsThread.Start();
+
+ TestSampler sampler;
+ sampler.Start();
+ CHECK(!sampler.WasSampleStackCalled());
+ jsThread.WaitForRunning();
+ jsThread.SendSigProf();
+ CHECK(sampler.WaitForTick());
+ CHECK(sampler.WasSampleStackCalled());
+ sampler.Reset();
+ CHECK(!sampler.WasSampleStackCalled());
+ nonJsThread.WaitForRunning();
+ nonJsThread.SendSigProf();
+ CHECK(sampler.WaitForTick());
+ CHECK(!sampler.WasSampleStackCalled());
+ sampler.Stop();
+
+ jsThread.Stop();
+ nonJsThread.Stop();
+ jsThread.Join();
+ nonJsThread.Join();
+}
+
+#endif // __linux__
+
+
static inline bool IsStringEqualTo(const char* r, const char* s) {
return strncmp(r, s, strlen(r)) == 0;
}
« src/v8threads.cc ('K') | « src/v8threads.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698