Revision: 7575
Author: [email protected]
Date: Mon Apr 11 16:46:22 2011
Log: Do not rely on uniqueness of pthread_t
Patch by Dmitry Lomov.
pthreads implementations are free to reuse pthread_t (thread id) after
the thread has died. This change gets rid of ThreadHandle class and
replaces it with v8-managed thread identifiers.
http://code.google.com/p/v8/source/detail?r=7575
Modified:
/branches/bleeding_edge/src/api.cc
/branches/bleeding_edge/src/isolate.cc
/branches/bleeding_edge/src/isolate.h
/branches/bleeding_edge/src/objects.cc
/branches/bleeding_edge/src/platform-cygwin.cc
/branches/bleeding_edge/src/platform-freebsd.cc
/branches/bleeding_edge/src/platform-linux.cc
/branches/bleeding_edge/src/platform-macos.cc
/branches/bleeding_edge/src/platform-nullos.cc
/branches/bleeding_edge/src/platform-openbsd.cc
/branches/bleeding_edge/src/platform-solaris.cc
/branches/bleeding_edge/src/platform-win32.cc
/branches/bleeding_edge/src/platform.h
/branches/bleeding_edge/src/runtime.cc
/branches/bleeding_edge/src/top.cc
/branches/bleeding_edge/src/v8.cc
/branches/bleeding_edge/src/v8threads.cc
/branches/bleeding_edge/src/v8threads.h
/branches/bleeding_edge/test/cctest/test-threads.cc
=======================================
--- /branches/bleeding_edge/src/api.cc Thu Apr 7 12:52:24 2011
+++ /branches/bleeding_edge/src/api.cc Mon Apr 11 16:46:22 2011
@@ -4625,7 +4625,7 @@
int V8::GetCurrentThreadId() {
i::Isolate* isolate = i::Isolate::Current();
EnsureInitializedForIsolate(isolate, "V8::GetCurrentThreadId()");
- return isolate->thread_id();
+ return isolate->thread_id().ToInteger();
}
@@ -4636,10 +4636,11 @@
// If the thread_id identifies the current thread just terminate
// execution right away. Otherwise, ask the thread manager to
// terminate the thread with the given id if any.
- if (thread_id == isolate->thread_id()) {
+ i::ThreadId internal_tid = i::ThreadId::FromInteger(thread_id);
+ if (isolate->thread_id().Equals(internal_tid)) {
isolate->stack_guard()->TerminateExecution();
} else {
- isolate->thread_manager()->TerminateExecution(thread_id);
+ isolate->thread_manager()->TerminateExecution(internal_tid);
}
}
=======================================
--- /branches/bleeding_edge/src/isolate.cc Thu Apr 7 12:52:24 2011
+++ /branches/bleeding_edge/src/isolate.cc Mon Apr 11 16:46:22 2011
@@ -54,6 +54,21 @@
namespace v8 {
namespace internal {
+Atomic32 ThreadId::highest_thread_id_ = 0;
+
+int ThreadId::AllocateThreadId() {
+ int new_id = NoBarrier_AtomicIncrement(&highest_thread_id_, 1);
+ return new_id;
+}
+
+int ThreadId::GetCurrentThreadId() {
+ int thread_id = Thread::GetThreadLocalInt(Isolate::thread_id_key_);
+ if (thread_id == 0) {
+ thread_id = AllocateThreadId();
+ Thread::SetThreadLocalInt(Isolate::thread_id_key_, thread_id);
+ }
+ return thread_id;
+}
// Create a dummy thread that will wait forever on a semaphore. The only
// purpose for this thread is to have some stack area to save essential
data
@@ -245,7 +260,6 @@
Thread::LocalStorageKey Isolate::per_isolate_thread_data_key_;
Mutex* Isolate::process_wide_mutex_ = OS::CreateMutex();
Isolate::ThreadDataTable* Isolate::thread_data_table_ = NULL;
-Isolate::ThreadId Isolate::highest_thread_id_ = 0;
class IsolateInitializer {
@@ -265,20 +279,12 @@
static IsolateInitializer* static_initializer =
EnsureDefaultIsolateAllocated();
-Isolate::ThreadId Isolate::AllocateThreadId() {
- ThreadId new_id;
- {
- ScopedLock lock(process_wide_mutex_);
- new_id = ++highest_thread_id_;
- }
- return new_id;
-}
+
Isolate::PerIsolateThreadData* Isolate::AllocatePerIsolateThreadData(
ThreadId thread_id) {
- ASSERT(thread_id != 0);
- ASSERT(Thread::GetThreadLocalInt(thread_id_key_) == thread_id);
+ ASSERT(!thread_id.Equals(ThreadId::Invalid()));
PerIsolateThreadData* per_thread = new PerIsolateThreadData(this,
thread_id);
{
ScopedLock lock(process_wide_mutex_);
@@ -292,11 +298,7 @@
Isolate::PerIsolateThreadData*
Isolate::FindOrAllocatePerThreadDataForThisThread() {
- ThreadId thread_id = Thread::GetThreadLocalInt(thread_id_key_);
- if (thread_id == 0) {
- thread_id = AllocateThreadId();
- Thread::SetThreadLocalInt(thread_id_key_, thread_id);
- }
+ ThreadId thread_id = ThreadId::Current();
PerIsolateThreadData* per_thread = NULL;
{
ScopedLock lock(process_wide_mutex_);
@@ -361,7 +363,8 @@
Isolate::PerIsolateThreadData*
- Isolate::ThreadDataTable::Lookup(Isolate* isolate, ThreadId thread_id)
{
+ Isolate::ThreadDataTable::Lookup(Isolate* isolate,
+ ThreadId thread_id) {
for (PerIsolateThreadData* data = list_; data != NULL; data =
data->next_) {
if (data->Matches(isolate, thread_id)) return data;
}
@@ -383,7 +386,8 @@
}
-void Isolate::ThreadDataTable::Remove(Isolate* isolate, ThreadId
thread_id) {
+void Isolate::ThreadDataTable::Remove(Isolate* isolate,
+ ThreadId thread_id) {
PerIsolateThreadData* data = Lookup(isolate, thread_id);
if (data != NULL) {
Remove(data);
@@ -833,8 +837,8 @@
ASSERT(Current() == this);
ASSERT(entry_stack_ != NULL);
ASSERT(entry_stack_->previous_thread_data == NULL ||
- entry_stack_->previous_thread_data->thread_id() ==
- Thread::GetThreadLocalInt(thread_id_key_));
+ entry_stack_->previous_thread_data->thread_id().Equals(
+ ThreadId::Current()));
// Same thread re-enters the isolate, no need to re-init anything.
entry_stack_->entry_count++;
return;
@@ -872,8 +876,8 @@
void Isolate::Exit() {
ASSERT(entry_stack_ != NULL);
ASSERT(entry_stack_->previous_thread_data == NULL ||
- entry_stack_->previous_thread_data->thread_id() ==
- Thread::GetThreadLocalInt(thread_id_key_));
+ entry_stack_->previous_thread_data->thread_id().Equals(
+ ThreadId::Current()));
if (--entry_stack_->entry_count > 0) return;
=======================================
--- /branches/bleeding_edge/src/isolate.h Mon Apr 11 09:16:52 2011
+++ /branches/bleeding_edge/src/isolate.h Mon Apr 11 16:46:22 2011
@@ -136,6 +136,53 @@
#endif
+// Platform-independent, reliable thread identifier.
+class ThreadId {
+ public:
+ // Creates an invalid ThreadId.
+ ThreadId() : id_(kInvalidId) {}
+
+ // Returns ThreadId for current thread.
+ static ThreadId Current() { return ThreadId(GetCurrentThreadId()); }
+
+ // Returns invalid ThreadId (guaranteed not to be equal to any thread).
+ static ThreadId Invalid() { return ThreadId(kInvalidId); }
+
+ // Compares ThreadIds for equality.
+ INLINE(bool Equals(const ThreadId& other) const) {
+ return id_ == other.id_;
+ }
+
+ // Checks whether this ThreadId refers to any thread.
+ INLINE(bool IsValid() const) {
+ return id_ != kInvalidId;
+ }
+
+ // Converts ThreadId to an integer representation
+ // (required for public API: V8::V8::GetCurrentThreadId).
+ int ToInteger() const { return id_; }
+
+ // Converts ThreadId to an integer representation
+ // (required for public API: V8::V8::TerminateExecution).
+ static ThreadId FromInteger(int id) { return ThreadId(id); }
+
+ private:
+ static const int kInvalidId = -1;
+
+ explicit ThreadId(int id) : id_(id) {}
+
+ static int AllocateThreadId();
+
+ static int GetCurrentThreadId();
+
+ int id_;
+
+ static Atomic32 highest_thread_id_;
+
+ friend class Isolate;
+};
+
+
class ThreadLocalTop BASE_EMBEDDED {
public:
// Initialize the thread data.
@@ -176,7 +223,7 @@
// The context where the current execution method is created and for
variable
// lookups.
Context* context_;
- int thread_id_;
+ ThreadId thread_id_;
MaybeObject* pending_exception_;
bool has_pending_message_;
Object* pending_message_obj_;
@@ -329,8 +376,6 @@
public:
~Isolate();
- typedef int ThreadId;
-
// A thread has a PerIsolateThreadData instance for each isolate that it
has
// entered. That instance is allocated when the isolate is initially
entered
// and reused on subsequent entries.
@@ -363,7 +408,7 @@
#endif
bool Matches(Isolate* isolate, ThreadId thread_id) const {
- return isolate_ == isolate && thread_id_ == thread_id;
+ return isolate_ == isolate && thread_id_.Equals(thread_id);
}
private:
@@ -454,9 +499,6 @@
static Thread::LocalStorageKey thread_id_key() {
return thread_id_key_;
}
-
- // Atomically allocates a new thread ID.
- static ThreadId AllocateThreadId();
// If a client attempts to create a Locker without specifying an isolate,
// we assume that the client is using legacy behavior. Set up the current
@@ -483,8 +525,8 @@
}
// Access to current thread id.
- int thread_id() { return thread_local_top_.thread_id_; }
- void set_thread_id(int id) { thread_local_top_.thread_id_ = id; }
+ ThreadId thread_id() { return thread_local_top_.thread_id_; }
+ void set_thread_id(ThreadId id) { thread_local_top_.thread_id_ = id; }
// Interface to pending exception.
MaybeObject* pending_exception() {
@@ -996,7 +1038,6 @@
static Thread::LocalStorageKey thread_id_key_;
static Isolate* default_isolate_;
static ThreadDataTable* thread_data_table_;
- static ThreadId highest_thread_id_;
bool PreInit();
@@ -1156,6 +1197,7 @@
friend class ExecutionAccess;
friend class IsolateInitializer;
+ friend class ThreadId;
friend class v8::Isolate;
friend class v8::Locker;
=======================================
--- /branches/bleeding_edge/src/objects.cc Mon Apr 11 04:38:34 2011
+++ /branches/bleeding_edge/src/objects.cc Mon Apr 11 16:46:22 2011
@@ -7635,7 +7635,6 @@
Handle<InterceptorInfo> interceptor(GetIndexedInterceptor(), isolate);
Handle<Object> this_handle(receiver, isolate);
Handle<JSObject> holder_handle(this, isolate);
-
if (!interceptor->getter()->IsUndefined()) {
v8::IndexedPropertyGetter getter =
v8::ToCData<v8::IndexedPropertyGetter>(interceptor->getter());
=======================================
--- /branches/bleeding_edge/src/platform-cygwin.cc Wed Mar 30 10:16:36 2011
+++ /branches/bleeding_edge/src/platform-cygwin.cc Mon Apr 11 16:46:22 2011
@@ -362,50 +362,17 @@
}
-class ThreadHandle::PlatformData : public Malloced {
+class Thread::PlatformData : public Malloced {
public:
- explicit PlatformData(ThreadHandle::Kind kind) {
- Initialize(kind);
- }
-
- void Initialize(ThreadHandle::Kind kind) {
- switch (kind) {
- case ThreadHandle::SELF: thread_ = pthread_self(); break;
- case ThreadHandle::INVALID: thread_ = kNoThread; break;
- }
- }
-
+ PlatformData() : thread_(kNoThread) {}
pthread_t thread_; // Thread handle for pthread.
};
-ThreadHandle::ThreadHandle(Kind kind) {
- data_ = new PlatformData(kind);
-}
-
-
-void ThreadHandle::Initialize(ThreadHandle::Kind kind) {
- data_->Initialize(kind);
-}
-
-
-ThreadHandle::~ThreadHandle() {
- delete data_;
-}
-
-
-bool ThreadHandle::IsSelf() const {
- return pthread_equal(data_->thread_, pthread_self());
-}
-
-
-bool ThreadHandle::IsValid() const {
- return data_->thread_ != kNoThread;
-}
Thread::Thread(Isolate* isolate, const Options& options)
- : ThreadHandle(ThreadHandle::INVALID),
+ : data_(new PlatformData),
isolate_(isolate),
stack_size_(options.stack_size) {
set_name(options.name);
@@ -413,7 +380,7 @@
Thread::Thread(Isolate* isolate, const char* name)
- : ThreadHandle(ThreadHandle::INVALID),
+ : data_(new PlatformData),
isolate_(isolate),
stack_size_(0) {
set_name(name);
@@ -421,6 +388,7 @@
Thread::~Thread() {
+ delete data_;
}
@@ -429,8 +397,8 @@
// This is also initialized by the first argument to pthread_create()
but we
// don't know which thread will run first (the original thread or the new
// one) so we initialize it here too.
- thread->thread_handle_data()->thread_ = pthread_self();
- ASSERT(thread->IsValid());
+ thread->data()->thread_ = pthread_self();
+ ASSERT(thread->data()->thread_ != kNoThread);
Thread::SetThreadLocal(Isolate::isolate_key(), thread->isolate());
thread->Run();
return NULL;
@@ -451,13 +419,13 @@
pthread_attr_setstacksize(&attr, static_cast<size_t>(stack_size_));
attr_ptr = &attr;
}
- pthread_create(&thread_handle_data()->thread_, attr_ptr, ThreadEntry,
this);
- ASSERT(IsValid());
+ pthread_create(&data_->thread_, attr_ptr, ThreadEntry, this);
+ ASSERT(data_->thread_ != kNoThread);
}
void Thread::Join() {
- pthread_join(thread_handle_data()->thread_, NULL);
+ pthread_join(data_->thread_, NULL);
}
=======================================
--- /branches/bleeding_edge/src/platform-freebsd.cc Mon Mar 28 23:18:16 2011
+++ /branches/bleeding_edge/src/platform-freebsd.cc Mon Apr 11 16:46:22 2011
@@ -391,18 +391,8 @@
}
-class ThreadHandle::PlatformData : public Malloced {
+class Thread::PlatformData : public Malloced {
public:
- explicit PlatformData(ThreadHandle::Kind kind) {
- Initialize(kind);
- }
-
- void Initialize(ThreadHandle::Kind kind) {
- switch (kind) {
- case ThreadHandle::SELF: thread_ = pthread_self(); break;
- case ThreadHandle::INVALID: thread_ = kNoThread; break;
- }
- }
pthread_t thread_; // Thread handle for pthread.
};
@@ -433,7 +423,7 @@
Thread::Thread(Isolate* isolate, const Options& options)
- : ThreadHandle(ThreadHandle::INVALID),
+ : data_(new PlatformData),
isolate_(isolate),
stack_size_(options.stack_size) {
set_name(options.name);
@@ -441,7 +431,7 @@
Thread::Thread(Isolate* isolate, const char* name)
- : ThreadHandle(ThreadHandle::INVALID),
+ : data_(new PlatformData),
isolate_(isolate),
stack_size_(0) {
set_name(name);
@@ -449,6 +439,7 @@
Thread::~Thread() {
+ delete data_;
}
@@ -457,7 +448,7 @@
// This is also initialized by the first argument to pthread_create()
but we
// don't know which thread will run first (the original thread or the new
// one) so we initialize it here too.
- thread->thread_handle_data()->thread_ = pthread_self();
+ thread_->data_->thread_ = pthread_self();
ASSERT(thread->IsValid());
Thread::SetThreadLocal(Isolate::isolate_key(), thread->isolate());
thread->Run();
=======================================
--- /branches/bleeding_edge/src/platform-linux.cc Mon Mar 28 06:05:36 2011
+++ /branches/bleeding_edge/src/platform-linux.cc Mon Apr 11 16:46:22 2011
@@ -588,50 +588,15 @@
}
-class ThreadHandle::PlatformData : public Malloced {
+class Thread::PlatformData : public Malloced {
public:
- explicit PlatformData(ThreadHandle::Kind kind) {
- Initialize(kind);
- }
-
- void Initialize(ThreadHandle::Kind kind) {
- switch (kind) {
- case ThreadHandle::SELF: thread_ = pthread_self(); break;
- case ThreadHandle::INVALID: thread_ = kNoThread; break;
- }
- }
+ PlatformData() : thread_(kNoThread) {}
pthread_t thread_; // Thread handle for pthread.
};
-
-ThreadHandle::ThreadHandle(Kind kind) {
- data_ = new PlatformData(kind);
-}
-
-
-void ThreadHandle::Initialize(ThreadHandle::Kind kind) {
- data_->Initialize(kind);
-}
-
-
-ThreadHandle::~ThreadHandle() {
- delete data_;
-}
-
-
-bool ThreadHandle::IsSelf() const {
- return pthread_equal(data_->thread_, pthread_self());
-}
-
-
-bool ThreadHandle::IsValid() const {
- return data_->thread_ != kNoThread;
-}
-
-
Thread::Thread(Isolate* isolate, const Options& options)
- : ThreadHandle(ThreadHandle::INVALID),
+ : data_(new PlatformData()),
isolate_(isolate),
stack_size_(options.stack_size) {
set_name(options.name);
@@ -639,7 +604,7 @@
Thread::Thread(Isolate* isolate, const char* name)
- : ThreadHandle(ThreadHandle::INVALID),
+ : data_(new PlatformData()),
isolate_(isolate),
stack_size_(0) {
set_name(name);
@@ -647,6 +612,7 @@
Thread::~Thread() {
+ delete data_;
}
@@ -658,8 +624,8 @@
prctl(PR_SET_NAME,
reinterpret_cast<unsigned long>(thread->name()), // NOLINT
0, 0, 0);
- thread->thread_handle_data()->thread_ = pthread_self();
- ASSERT(thread->IsValid());
+ thread->data()->thread_ = pthread_self();
+ ASSERT(thread->data()->thread_ != kNoThread);
Thread::SetThreadLocal(Isolate::isolate_key(), thread->isolate());
thread->Run();
return NULL;
@@ -680,13 +646,13 @@
pthread_attr_setstacksize(&attr, static_cast<size_t>(stack_size_));
attr_ptr = &attr;
}
- pthread_create(&thread_handle_data()->thread_, attr_ptr, ThreadEntry,
this);
- ASSERT(IsValid());
+ pthread_create(&data_->thread_, attr_ptr, ThreadEntry, this);
+ ASSERT(data_->thread_ != kNoThread);
}
void Thread::Join() {
- pthread_join(thread_handle_data()->thread_, NULL);
+ pthread_join(data_->thread_, NULL);
}
=======================================
--- /branches/bleeding_edge/src/platform-macos.cc Sun Apr 3 22:46:51 2011
+++ /branches/bleeding_edge/src/platform-macos.cc Mon Apr 11 16:46:22 2011
@@ -392,50 +392,14 @@
}
-class ThreadHandle::PlatformData : public Malloced {
+class Thread::PlatformData : public Malloced {
public:
- explicit PlatformData(ThreadHandle::Kind kind) {
- Initialize(kind);
- }
-
- void Initialize(ThreadHandle::Kind kind) {
- switch (kind) {
- case ThreadHandle::SELF: thread_ = pthread_self(); break;
- case ThreadHandle::INVALID: thread_ = kNoThread; break;
- }
- }
+ PlatformData() : thread_(kNoThread) {}
pthread_t thread_; // Thread handle for pthread.
};
-
-
-ThreadHandle::ThreadHandle(Kind kind) {
- data_ = new PlatformData(kind);
-}
-
-
-void ThreadHandle::Initialize(ThreadHandle::Kind kind) {
- data_->Initialize(kind);
-}
-
-
-ThreadHandle::~ThreadHandle() {
- delete data_;
-}
-
-
-bool ThreadHandle::IsSelf() const {
- return pthread_equal(data_->thread_, pthread_self());
-}
-
-
-bool ThreadHandle::IsValid() const {
- return data_->thread_ != kNoThread;
-}
-
-
Thread::Thread(Isolate* isolate, const Options& options)
- : ThreadHandle(ThreadHandle::INVALID),
+ : data_(new PlatformData),
isolate_(isolate),
stack_size_(options.stack_size) {
set_name(options.name);
@@ -443,7 +407,7 @@
Thread::Thread(Isolate* isolate, const char* name)
- : ThreadHandle(ThreadHandle::INVALID),
+ : data_(new PlatformData),
isolate_(isolate),
stack_size_(0) {
set_name(name);
@@ -451,6 +415,7 @@
Thread::~Thread() {
+ delete data_;
}
@@ -476,9 +441,9 @@
// This is also initialized by the first argument to pthread_create()
but we
// don't know which thread will run first (the original thread or the new
// one) so we initialize it here too.
- thread->thread_handle_data()->thread_ = pthread_self();
+ thread->data()->thread_ = pthread_self();
SetThreadName(thread->name());
- ASSERT(thread->IsValid());
+ ASSERT(thread->data()->thread_ != kNoThread);
Thread::SetThreadLocal(Isolate::isolate_key(), thread->isolate());
thread->Run();
return NULL;
@@ -499,13 +464,13 @@
pthread_attr_setstacksize(&attr, static_cast<size_t>(stack_size_));
attr_ptr = &attr;
}
- pthread_create(&thread_handle_data()->thread_, attr_ptr, ThreadEntry,
this);
- ASSERT(IsValid());
+ pthread_create(&data_->thread_, attr_ptr, ThreadEntry, this);
+ ASSERT(data_->thread_ != kNoThread);
}
void Thread::Join() {
- pthread_join(thread_handle_data()->thread_, NULL);
+ pthread_join(data_->thread_, NULL);
}
=======================================
--- /branches/bleeding_edge/src/platform-nullos.cc Mon Mar 21 08:04:17 2011
+++ /branches/bleeding_edge/src/platform-nullos.cc Mon Apr 11 16:46:22 2011
@@ -299,9 +299,9 @@
}
-class ThreadHandle::PlatformData : public Malloced {
+class Thread::PlatformData : public Malloced {
public:
- explicit PlatformData(ThreadHandle::Kind kind) {
+ PlatformData() {
UNIMPLEMENTED();
}
@@ -309,39 +309,8 @@
};
-ThreadHandle::ThreadHandle(Kind kind) {
- UNIMPLEMENTED();
- // Shared setup follows.
- data_ = new PlatformData(kind);
-}
-
-
-void ThreadHandle::Initialize(ThreadHandle::Kind kind) {
- UNIMPLEMENTED();
-}
-
-
-ThreadHandle::~ThreadHandle() {
- UNIMPLEMENTED();
- // Shared tear down follows.
- delete data_;
-}
-
-
-bool ThreadHandle::IsSelf() const {
- UNIMPLEMENTED();
- return false;
-}
-
-
-bool ThreadHandle::IsValid() const {
- UNIMPLEMENTED();
- return false;
-}
-
-
Thread::Thread(Isolate* isolate, const Options& options)
- : ThreadHandle(ThreadHandle::INVALID),
+ : data_(new PlatformData()),
isolate_(isolate),
stack_size_(options.stack_size) {
set_name(options.name);
@@ -350,7 +319,7 @@
Thread::Thread(Isolate* isolate, const char* name)
- : ThreadHandle(ThreadHandle::INVALID),
+ : data_(new PlatformData()),
isolate_(isolate),
stack_size_(0) {
set_name(name);
@@ -359,6 +328,7 @@
Thread::~Thread() {
+ delete data_;
UNIMPLEMENTED();
}
=======================================
--- /branches/bleeding_edge/src/platform-openbsd.cc Mon Mar 21 08:04:17 2011
+++ /branches/bleeding_edge/src/platform-openbsd.cc Mon Apr 11 16:46:22 2011
@@ -359,49 +359,16 @@
}
-class ThreadHandle::PlatformData : public Malloced {
+class Thread::PlatformData : public Malloced {
public:
- explicit PlatformData(ThreadHandle::Kind kind) {
- Initialize(kind);
- }
-
- void Initialize(ThreadHandle::Kind kind) {
- switch (kind) {
- case ThreadHandle::SELF: thread_ = pthread_self(); break;
- case ThreadHandle::INVALID: thread_ = kNoThread; break;
- }
- }
+ PlatformData() : thread_(kNoThread) {}
+
pthread_t thread_; // Thread handle for pthread.
};
-ThreadHandle::ThreadHandle(Kind kind) {
- data_ = new PlatformData(kind);
-}
-
-
-void ThreadHandle::Initialize(ThreadHandle::Kind kind) {
- data_->Initialize(kind);
-}
-
-
-ThreadHandle::~ThreadHandle() {
- delete data_;
-}
-
-
-bool ThreadHandle::IsSelf() const {
- return pthread_equal(data_->thread_, pthread_self());
-}
-
-
-bool ThreadHandle::IsValid() const {
- return data_->thread_ != kNoThread;
-}
-
-
Thread::Thread(Isolate* isolate, const Options& options)
- : ThreadHandle(ThreadHandle::INVALID),
+ : data_(new PlatformData()),
isolate_(isolate),
stack_size_(options.stack_size) {
set_name(options.name);
@@ -409,7 +376,7 @@
Thread::Thread(Isolate* isolate, const char* name)
- : ThreadHandle(ThreadHandle::INVALID),
+ : data_(new PlatfromData()),
isolate_(isolate),
stack_size_(0) {
set_name(name);
@@ -417,6 +384,7 @@
Thread::~Thread() {
+ delete data_;
}
@@ -425,8 +393,8 @@
// This is also initialized by the first argument to pthread_create()
but we
// don't know which thread will run first (the original thread or the new
// one) so we initialize it here too.
- thread->thread_handle_data()->thread_ = pthread_self();
- ASSERT(thread->IsValid());
+ thread->data()->thread_ = pthread_self();
+ ASSERT(thread->data()->thread_ != kNoThread);
Thread::SetThreadLocal(Isolate::isolate_key(), thread->isolate());
thread->Run();
return NULL;
@@ -447,13 +415,13 @@
pthread_attr_setstacksize(&attr, static_cast<size_t>(stack_size_));
attr_ptr = &attr;
}
- pthread_create(&thread_handle_data()->thread_, attr_ptr, ThreadEntry,
this);
+ pthread_create(&data_->thread_, attr_ptr, ThreadEntry, this);
ASSERT(IsValid());
}
void Thread::Join() {
- pthread_join(thread_handle_data()->thread_, NULL);
+ pthread_join(data_->thread_, NULL);
}
=======================================
--- /branches/bleeding_edge/src/platform-solaris.cc Mon Mar 21 08:04:17 2011
+++ /branches/bleeding_edge/src/platform-solaris.cc Mon Apr 11 16:46:22 2011
@@ -373,50 +373,15 @@
}
-class ThreadHandle::PlatformData : public Malloced {
+class Thread::PlatformData : public Malloced {
public:
- explicit PlatformData(ThreadHandle::Kind kind) {
- Initialize(kind);
- }
-
- void Initialize(ThreadHandle::Kind kind) {
- switch (kind) {
- case ThreadHandle::SELF: thread_ = pthread_self(); break;
- case ThreadHandle::INVALID: thread_ = kNoThread; break;
- }
- }
+ PlatformData() : thread_(kNoThread) { }
pthread_t thread_; // Thread handle for pthread.
};
-
-ThreadHandle::ThreadHandle(Kind kind) {
- data_ = new PlatformData(kind);
-}
-
-
-void ThreadHandle::Initialize(ThreadHandle::Kind kind) {
- data_->Initialize(kind);
-}
-
-
-ThreadHandle::~ThreadHandle() {
- delete data_;
-}
-
-
-bool ThreadHandle::IsSelf() const {
- return pthread_equal(data_->thread_, pthread_self());
-}
-
-
-bool ThreadHandle::IsValid() const {
- return data_->thread_ != kNoThread;
-}
-
-
Thread::Thread(Isolate* isolate, const Options& options)
- : ThreadHandle(ThreadHandle::INVALID),
+ : data_(new PlatformData()),
isolate_(isolate),
stack_size_(options.stack_size) {
set_name(options.name);
@@ -424,7 +389,7 @@
Thread::Thread(Isolate* isolate, const char* name)
- : ThreadHandle(ThreadHandle::INVALID),
+ : data_(new PlatformData()),
isolate_(isolate),
stack_size_(0) {
set_name(name);
@@ -432,6 +397,7 @@
Thread::~Thread() {
+ delete data_;
}
@@ -440,8 +406,8 @@
// This is also initialized by the first argument to pthread_create()
but we
// don't know which thread will run first (the original thread or the new
// one) so we initialize it here too.
- thread->thread_handle_data()->thread_ = pthread_self();
- ASSERT(thread->IsValid());
+ thread->data()->thread_ = pthread_self();
+ ASSERT(thread->data()->thread_ != kNoThread);
Thread::SetThreadLocal(Isolate::isolate_key(), thread->isolate());
thread->Run();
return NULL;
@@ -462,13 +428,13 @@
pthread_attr_setstacksize(&attr, static_cast<size_t>(stack_size_));
attr_ptr = &attr;
}
- pthread_create(&thread_handle_data()->thread_, NULL, ThreadEntry, this);
- ASSERT(IsValid());
+ pthread_create(&data_->thread_, NULL, ThreadEntry, this);
+ ASSERT(data_->thread_ != kNoThread);
}
void Thread::Join() {
- pthread_join(thread_handle_data()->thread_, NULL);
+ pthread_join(data_->thread_, NULL);
}
=======================================
--- /branches/bleeding_edge/src/platform-win32.cc Fri Apr 1 07:46:30 2011
+++ /branches/bleeding_edge/src/platform-win32.cc Mon Apr 11 16:46:22 2011
@@ -1496,39 +1496,10 @@
// This is also initialized by the last parameter to _beginthreadex()
but we
// don't know which thread will run first (the original thread or the new
// one) so we initialize it here too.
- thread->thread_handle_data()->tid_ = GetCurrentThreadId();
Thread::SetThreadLocal(Isolate::isolate_key(), thread->isolate());
thread->Run();
return 0;
}
-
-
-// Initialize thread handle to invalid handle.
-ThreadHandle::ThreadHandle(ThreadHandle::Kind kind) {
- data_ = new PlatformData(kind);
-}
-
-
-ThreadHandle::~ThreadHandle() {
- delete data_;
-}
-
-
-// The thread is running if it has the same id as the current thread.
-bool ThreadHandle::IsSelf() const {
- return GetCurrentThreadId() == data_->tid_;
-}
-
-
-// Test for invalid thread handle.
-bool ThreadHandle::IsValid() const {
- return data_->tid_ != kNoThreadId;
-}
-
-
-void ThreadHandle::Initialize(ThreadHandle::Kind kind) {
- data_->Initialize(kind);
-}
class Thread::PlatformData : public Malloced {
@@ -1542,8 +1513,7 @@
// handle until it is started.
Thread::Thread(Isolate* isolate, const Options& options)
- : ThreadHandle(ThreadHandle::INVALID),
- isolate_(isolate),
+ : isolate_(isolate),
stack_size_(options.stack_size) {
data_ = new PlatformData(kNoThread);
set_name(options.name);
@@ -1551,8 +1521,7 @@
Thread::Thread(Isolate* isolate, const char* name)
- : ThreadHandle(ThreadHandle::INVALID),
- isolate_(isolate),
+ : isolate_(isolate),
stack_size_(0) {
data_ = new PlatformData(kNoThread);
set_name(name);
=======================================
--- /branches/bleeding_edge/src/platform.h Thu Mar 31 09:17:37 2011
+++ /branches/bleeding_edge/src/platform.h Mon Apr 11 16:46:22 2011
@@ -354,40 +354,6 @@
size_t size_; // Size of the virtual memory.
};
-
-//
----------------------------------------------------------------------------
-// ThreadHandle
-//
-// A ThreadHandle represents a thread identifier for a thread. The
ThreadHandle
-// does not own the underlying os handle. Thread handles can be used for
-// refering to threads and testing equality.
-
-class ThreadHandle {
- public:
- enum Kind { SELF, INVALID };
- explicit ThreadHandle(Kind kind);
-
- // Destructor.
- ~ThreadHandle();
-
- // Test for thread running.
- bool IsSelf() const;
-
- // Test for valid thread handle.
- bool IsValid() const;
-
- // Get platform-specific data.
- class PlatformData;
- PlatformData* thread_handle_data() { return data_; }
-
- // Initialize the handle to kind
- void Initialize(Kind kind);
-
- private:
- PlatformData* data_; // Captures platform dependent data.
-};
-
-
//
----------------------------------------------------------------------------
// Thread
//
@@ -396,7 +362,7 @@
// thread. The Thread object should not be deallocated before the thread
has
// terminated.
-class Thread: public ThreadHandle {
+class Thread {
public:
// Opaque data type for thread-local storage keys.
// LOCAL_STORAGE_KEY_MIN_VALUE and LOCAL_STORAGE_KEY_MAX_VALUE are
specified
@@ -468,11 +434,15 @@
// The thread name length is limited to 16 based on Linux's
implementation of
// prctl().
static const int kMaxThreadNameLength = 16;
+
+ class PlatformData;
+ PlatformData* data() { return data_; }
+
private:
void set_name(const char *name);
- class PlatformData;
PlatformData* data_;
+
Isolate* isolate_;
char name_[kMaxThreadNameLength];
int stack_size_;
=======================================
--- /branches/bleeding_edge/src/runtime.cc Mon Apr 11 06:24:50 2011
+++ /branches/bleeding_edge/src/runtime.cc Mon Apr 11 16:46:22 2011
@@ -10171,8 +10171,7 @@
details->set(kThreadDetailsCurrentThreadIndex,
isolate->heap()->true_value());
details->set(kThreadDetailsThreadIdIndex,
- Smi::FromInt(
- isolate->thread_manager()->CurrentId()));
+ Smi::FromInt(ThreadId::Current().ToInteger()));
} else {
// Find the thread with the requested index.
int n = 1;
@@ -10189,7 +10188,8 @@
// Fill the details.
details->set(kThreadDetailsCurrentThreadIndex,
isolate->heap()->false_value());
- details->set(kThreadDetailsThreadIdIndex, Smi::FromInt(thread->id()));
+ details->set(kThreadDetailsThreadIdIndex,
+ Smi::FromInt(thread->id().ToInteger()));
}
// Convert to JS array and return.
=======================================
--- /branches/bleeding_edge/src/top.cc Mon Apr 11 09:16:52 2011
+++ /branches/bleeding_edge/src/top.cc Mon Apr 11 16:46:22 2011
@@ -69,8 +69,7 @@
#endif
try_catch_handler_address_ = NULL;
context_ = NULL;
- int id = Isolate::Current()->thread_manager()->CurrentId();
- thread_id_ = (id == 0) ? ThreadManager::kInvalidId : id;
+ thread_id_ = ThreadId::Current();
external_caught_exception_ = false;
failed_access_check_callback_ = NULL;
save_context_ = NULL;
=======================================
--- /branches/bleeding_edge/src/v8.cc Mon Apr 11 02:04:30 2011
+++ /branches/bleeding_edge/src/v8.cc Mon Apr 11 16:46:22 2011
@@ -63,8 +63,8 @@
}
ASSERT(i::Isolate::CurrentPerIsolateThreadData() != NULL);
- ASSERT(i::Isolate::CurrentPerIsolateThreadData()->thread_id() ==
- i::Thread::GetThreadLocalInt(i::Isolate::thread_id_key()));
+ ASSERT(i::Isolate::CurrentPerIsolateThreadData()->thread_id().Equals(
+ i::ThreadId::Current()));
ASSERT(i::Isolate::CurrentPerIsolateThreadData()->isolate() ==
i::Isolate::Current());
=======================================
--- /branches/bleeding_edge/src/v8threads.cc Fri Mar 18 13:35:07 2011
+++ /branches/bleeding_edge/src/v8threads.cc Mon Apr 11 16:46:22 2011
@@ -147,11 +147,11 @@
// First check whether the current thread has been 'lazily archived', ie
// not archived at all. If that is the case we put the state storage we
// had prepared back in the free list, since we didn't need it after all.
- if (lazily_archived_thread_.IsSelf()) {
- lazily_archived_thread_.Initialize(ThreadHandle::INVALID);
+ if (lazily_archived_thread_.Equals(ThreadId::Current())) {
+ lazily_archived_thread_ = ThreadId::Invalid();
ASSERT(Isolate::CurrentPerIsolateThreadData()->thread_state() ==
lazily_archived_thread_state_);
- lazily_archived_thread_state_->set_id(kInvalidId);
+ lazily_archived_thread_state_->set_id(ThreadId::Invalid());
lazily_archived_thread_state_->LinkInto(ThreadState::FREE_LIST);
lazily_archived_thread_state_ = NULL;
Isolate::CurrentPerIsolateThreadData()->set_thread_state(NULL);
@@ -190,7 +190,7 @@
isolate_->stack_guard()->TerminateExecution();
state->set_terminate_on_restore(false);
}
- state->set_id(kInvalidId);
+ state->set_id(ThreadId::Invalid());
state->Unlink();
state->LinkInto(ThreadState::FREE_LIST);
return true;
@@ -199,13 +199,13 @@
void ThreadManager::Lock() {
mutex_->Lock();
- mutex_owner_.Initialize(ThreadHandle::SELF);
+ mutex_owner_ = ThreadId::Current();
ASSERT(IsLockedByCurrentThread());
}
void ThreadManager::Unlock() {
- mutex_owner_.Initialize(ThreadHandle::INVALID);
+ mutex_owner_ = ThreadId::Invalid();
mutex_->Unlock();
}
@@ -224,7 +224,7 @@
ThreadState::ThreadState(ThreadManager* thread_manager)
- : id_(ThreadManager::kInvalidId),
+ : id_(ThreadId::Invalid()),
terminate_on_restore_(false),
next_(this),
previous_(this),
@@ -282,8 +282,8 @@
// defined as 0.)
ThreadManager::ThreadManager()
: mutex_(OS::CreateMutex()),
- mutex_owner_(ThreadHandle::INVALID),
- lazily_archived_thread_(ThreadHandle::INVALID),
+ mutex_owner_(ThreadId::Invalid()),
+ lazily_archived_thread_(ThreadId::Invalid()),
lazily_archived_thread_state_(NULL),
free_anchor_(NULL),
in_use_anchor_(NULL) {
@@ -298,16 +298,16 @@
void ThreadManager::ArchiveThread() {
- ASSERT(!lazily_archived_thread_.IsValid());
+ ASSERT(lazily_archived_thread_.Equals(ThreadId::Invalid()));
ASSERT(!IsArchived());
ThreadState* state = GetFreeThreadState();
state->Unlink();
Isolate::CurrentPerIsolateThreadData()->set_thread_state(state);
- lazily_archived_thread_.Initialize(ThreadHandle::SELF);
+ lazily_archived_thread_ = ThreadId::Current();
lazily_archived_thread_state_ = state;
- ASSERT(state->id() == kInvalidId);
+ ASSERT(state->id().Equals(ThreadId::Invalid()));
state->set_id(CurrentId());
- ASSERT(state->id() != kInvalidId);
+ ASSERT(!state->id().Equals(ThreadId::Invalid()));
}
@@ -326,7 +326,7 @@
to = isolate_->stack_guard()->ArchiveStackGuard(to);
to = isolate_->regexp_stack()->ArchiveStack(to);
to = isolate_->bootstrapper()->ArchiveState(to);
- lazily_archived_thread_.Initialize(ThreadHandle::INVALID);
+ lazily_archived_thread_ = ThreadId::Invalid();
lazily_archived_thread_state_ = NULL;
}
@@ -373,16 +373,16 @@
}
-int ThreadManager::CurrentId() {
- return Thread::GetThreadLocalInt(Isolate::thread_id_key());
+ThreadId ThreadManager::CurrentId() {
+ return ThreadId::Current();
}
-void ThreadManager::TerminateExecution(int thread_id) {
+void ThreadManager::TerminateExecution(ThreadId thread_id) {
for (ThreadState* state = FirstThreadStateInUse();
state != NULL;
state = state->Next()) {
- if (thread_id == state->id()) {
+ if (thread_id.Equals(state->id())) {
state->set_terminate_on_restore(true);
}
}
=======================================
--- /branches/bleeding_edge/src/v8threads.h Tue Apr 5 02:01:47 2011
+++ /branches/bleeding_edge/src/v8threads.h Mon Apr 11 16:46:22 2011
@@ -43,8 +43,8 @@
void Unlink();
// Id of thread.
- void set_id(int id) { id_ = id; }
- int id() { return id_; }
+ void set_id(ThreadId id) { id_ = id; }
+ ThreadId id() { return id_; }
// Should the thread be terminated when it is restored?
bool terminate_on_restore() { return terminate_on_restore_; }
@@ -59,7 +59,7 @@
void AllocateSpace();
- int id_;
+ ThreadId id_;
bool terminate_on_restore_;
char* data_;
ThreadState* next_;
@@ -97,17 +97,18 @@
void Iterate(ObjectVisitor* v);
void IterateArchivedThreads(ThreadVisitor* v);
- bool IsLockedByCurrentThread() { return mutex_owner_.IsSelf(); }
-
- int CurrentId();
-
- void TerminateExecution(int thread_id);
+ bool IsLockedByCurrentThread() {
+ return mutex_owner_.Equals(ThreadId::Current());
+ }
+
+ ThreadId CurrentId();
+
+ void TerminateExecution(ThreadId thread_id);
// Iterate over in-use states.
ThreadState* FirstThreadStateInUse();
ThreadState* GetFreeThreadState();
- static const int kInvalidId = -1;
private:
ThreadManager();
~ThreadManager();
@@ -115,8 +116,8 @@
void EagerlyArchiveThread();
Mutex* mutex_;
- ThreadHandle mutex_owner_;
- ThreadHandle lazily_archived_thread_;
+ ThreadId mutex_owner_;
+ ThreadId lazily_archived_thread_;
ThreadState* lazily_archived_thread_state_;
// In the following two lists there is always at least one object on the
list.
=======================================
--- /branches/bleeding_edge/test/cctest/test-threads.cc Mon Mar 21 08:04:17
2011
+++ /branches/bleeding_edge/test/cctest/test-threads.cc Mon Apr 11 16:46:22
2011
@@ -28,6 +28,7 @@
#include "v8.h"
#include "platform.h"
+#include "isolate.h"
#include "cctest.h"
@@ -136,3 +137,55 @@
CHECK_EQ(DONE, turn);
}
+
+class ThreadIdValidationThread : public v8::internal::Thread {
+ public:
+ ThreadIdValidationThread(i::Thread* thread_to_start,
+ i::List<i::ThreadId>* refs,
+ unsigned int thread_no,
+ i::Semaphore* semaphore)
+ : Thread(NULL, "ThreadRefValidationThread"),
+ refs_(refs), thread_no_(thread_no),
thread_to_start_(thread_to_start),
+ semaphore_(semaphore) {
+ }
+
+ void Run() {
+ i::ThreadId thread_id = i::ThreadId::Current();
+ for (int i = 0; i < thread_no_; i++) {
+ CHECK(!(*refs_)[i].Equals(thread_id));
+ }
+ CHECK(thread_id.IsValid());
+ (*refs_)[thread_no_] = thread_id;
+ if (thread_to_start_ != NULL) {
+ thread_to_start_->Start();
+ }
+ semaphore_->Signal();
+ }
+ private:
+ i::List<i::ThreadId>* refs_;
+ int thread_no_;
+ i::Thread* thread_to_start_;
+ i::Semaphore* semaphore_;
+};
+
+TEST(ThreadIdValidation) {
+ const int kNThreads = 100;
+ i::List<ThreadIdValidationThread*> threads(kNThreads);
+ i::List<i::ThreadId> refs(kNThreads);
+ i::Semaphore* semaphore = i::OS::CreateSemaphore(0);
+ ThreadIdValidationThread* prev = NULL;
+ for (int i = kNThreads - 1; i >= 0; i--) {
+ ThreadIdValidationThread* newThread =
+ new ThreadIdValidationThread(prev, &refs, i, semaphore);
+ threads.Add(newThread);
+ prev = newThread;
+ refs.Add(i::ThreadId::Invalid());
+ }
+ prev->Start();
+ for (int i = 0; i < kNThreads; i++) {
+ semaphore->Wait();
+ }
+ for (int i = 0; i < kNThreads; i++) {
+ delete threads[i];
+ }
+}
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev