diff --git a/src/platform-cygwin.cc b/src/platform-cygwin.cc index a9192775b7..c34330b3fb 100644 --- a/src/platform-cygwin.cc +++ b/src/platform-cygwin.cc @@ -51,9 +51,6 @@ namespace v8 { namespace internal { -// 0 is never a valid thread id -static const pthread_t kNoThread = (pthread_t) 0; - double ceiling(double x) { return ceil(x); @@ -418,110 +415,6 @@ bool VirtualMemory::HasLazyCommits() { } -class Thread::PlatformData : public Malloced { - public: - PlatformData() : thread_(kNoThread) {} - pthread_t thread_; // Thread handle for pthread. -}; - - -Thread::Thread(const Options& options) - : data_(new PlatformData()), - stack_size_(options.stack_size()), - start_semaphore_(NULL) { - set_name(options.name()); -} - - -Thread::~Thread() { - delete data_; -} - - -static void* ThreadEntry(void* arg) { - Thread* thread = reinterpret_cast(arg); - // 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->data()->thread_ = pthread_self(); - ASSERT(thread->data()->thread_ != kNoThread); - thread->NotifyStartedAndRun(); - return NULL; -} - - -void Thread::set_name(const char* name) { - strncpy(name_, name, sizeof(name_)); - name_[sizeof(name_) - 1] = '\0'; -} - - -void Thread::Start() { - pthread_attr_t* attr_ptr = NULL; - pthread_attr_t attr; - if (stack_size_ > 0) { - pthread_attr_init(&attr); - pthread_attr_setstacksize(&attr, static_cast(stack_size_)); - attr_ptr = &attr; - } - pthread_create(&data_->thread_, attr_ptr, ThreadEntry, this); - ASSERT(data_->thread_ != kNoThread); -} - - -void Thread::Join() { - pthread_join(data_->thread_, NULL); -} - - -static inline Thread::LocalStorageKey PthreadKeyToLocalKey( - pthread_key_t pthread_key) { - // We need to cast pthread_key_t to Thread::LocalStorageKey in two steps - // because pthread_key_t is a pointer type on Cygwin. This will probably not - // work on 64-bit platforms, but Cygwin doesn't support 64-bit anyway. - STATIC_ASSERT(sizeof(Thread::LocalStorageKey) == sizeof(pthread_key_t)); - intptr_t ptr_key = reinterpret_cast(pthread_key); - return static_cast(ptr_key); -} - - -static inline pthread_key_t LocalKeyToPthreadKey( - Thread::LocalStorageKey local_key) { - STATIC_ASSERT(sizeof(Thread::LocalStorageKey) == sizeof(pthread_key_t)); - intptr_t ptr_key = static_cast(local_key); - return reinterpret_cast(ptr_key); -} - - -Thread::LocalStorageKey Thread::CreateThreadLocalKey() { - pthread_key_t key; - int result = pthread_key_create(&key, NULL); - USE(result); - ASSERT(result == 0); - return PthreadKeyToLocalKey(key); -} - - -void Thread::DeleteThreadLocalKey(LocalStorageKey key) { - pthread_key_t pthread_key = LocalKeyToPthreadKey(key); - int result = pthread_key_delete(pthread_key); - USE(result); - ASSERT(result == 0); -} - - -void* Thread::GetThreadLocal(LocalStorageKey key) { - pthread_key_t pthread_key = LocalKeyToPthreadKey(key); - return pthread_getspecific(pthread_key); -} - - -void Thread::SetThreadLocal(LocalStorageKey key, void* value) { - pthread_key_t pthread_key = LocalKeyToPthreadKey(key); - pthread_setspecific(pthread_key, value); -} - - class CygwinSemaphore : public Semaphore { public: explicit CygwinSemaphore(int count) { sem_init(&sem_, 0, count); } diff --git a/src/platform-freebsd.cc b/src/platform-freebsd.cc index a0e0dbfd05..d7544db1ca 100644 --- a/src/platform-freebsd.cc +++ b/src/platform-freebsd.cc @@ -62,10 +62,6 @@ namespace v8 { namespace internal { -// 0 is never a valid thread id on FreeBSD since tids and pids share a -// name space and pid 0 is used to kill the group (see man 2 kill). -static const pthread_t kNoThread = (pthread_t) 0; - double ceiling(double x) { // Correct as on OS X @@ -397,90 +393,6 @@ bool VirtualMemory::HasLazyCommits() { } -class Thread::PlatformData : public Malloced { - public: - pthread_t thread_; // Thread handle for pthread. -}; - - -Thread::Thread(const Options& options) - : data_(new PlatformData), - stack_size_(options.stack_size()), - start_semaphore_(NULL) { - set_name(options.name()); -} - - -Thread::~Thread() { - delete data_; -} - - -static void* ThreadEntry(void* arg) { - Thread* thread = reinterpret_cast(arg); - // 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->data()->thread_ = pthread_self(); - ASSERT(thread->data()->thread_ != kNoThread); - thread->NotifyStartedAndRun(); - return NULL; -} - - -void Thread::set_name(const char* name) { - strncpy(name_, name, sizeof(name_)); - name_[sizeof(name_) - 1] = '\0'; -} - - -void Thread::Start() { - pthread_attr_t* attr_ptr = NULL; - pthread_attr_t attr; - if (stack_size_ > 0) { - pthread_attr_init(&attr); - pthread_attr_setstacksize(&attr, static_cast(stack_size_)); - attr_ptr = &attr; - } - pthread_create(&data_->thread_, attr_ptr, ThreadEntry, this); - ASSERT(data_->thread_ != kNoThread); -} - - -void Thread::Join() { - pthread_join(data_->thread_, NULL); -} - - -Thread::LocalStorageKey Thread::CreateThreadLocalKey() { - pthread_key_t key; - int result = pthread_key_create(&key, NULL); - USE(result); - ASSERT(result == 0); - return static_cast(key); -} - - -void Thread::DeleteThreadLocalKey(LocalStorageKey key) { - pthread_key_t pthread_key = static_cast(key); - int result = pthread_key_delete(pthread_key); - USE(result); - ASSERT(result == 0); -} - - -void* Thread::GetThreadLocal(LocalStorageKey key) { - pthread_key_t pthread_key = static_cast(key); - return pthread_getspecific(pthread_key); -} - - -void Thread::SetThreadLocal(LocalStorageKey key, void* value) { - pthread_key_t pthread_key = static_cast(key); - pthread_setspecific(pthread_key, value); -} - - class FreeBSDSemaphore : public Semaphore { public: explicit FreeBSDSemaphore(int count) { sem_init(&sem_, 0, count); } diff --git a/src/platform-linux.cc b/src/platform-linux.cc index 438de22629..245dae4ace 100644 --- a/src/platform-linux.cc +++ b/src/platform-linux.cc @@ -75,10 +75,6 @@ namespace v8 { namespace internal { -// 0 is never a valid thread id on Linux since tids and pids share a -// name space and pid 0 is reserved (see man 2 kill). -static const pthread_t kNoThread = (pthread_t) 0; - double ceiling(double x) { return ceil(x); @@ -711,101 +707,6 @@ bool VirtualMemory::HasLazyCommits() { } -class Thread::PlatformData : public Malloced { - public: - PlatformData() : thread_(kNoThread) {} - - pthread_t thread_; // Thread handle for pthread. -}; - -Thread::Thread(const Options& options) - : data_(new PlatformData()), - stack_size_(options.stack_size()), - start_semaphore_(NULL) { - set_name(options.name()); -} - - -Thread::~Thread() { - delete data_; -} - - -static void* ThreadEntry(void* arg) { - Thread* thread = reinterpret_cast(arg); - // 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. -#ifdef PR_SET_NAME - prctl(PR_SET_NAME, - reinterpret_cast(thread->name()), // NOLINT - 0, 0, 0); -#endif - thread->data()->thread_ = pthread_self(); - ASSERT(thread->data()->thread_ != kNoThread); - thread->NotifyStartedAndRun(); - return NULL; -} - - -void Thread::set_name(const char* name) { - strncpy(name_, name, sizeof(name_)); - name_[sizeof(name_) - 1] = '\0'; -} - - -void Thread::Start() { - pthread_attr_t* attr_ptr = NULL; -#if defined(__native_client__) - // use default stack size. -#else - pthread_attr_t attr; - if (stack_size_ > 0) { - pthread_attr_init(&attr); - pthread_attr_setstacksize(&attr, static_cast(stack_size_)); - attr_ptr = &attr; - } -#endif - int result = pthread_create(&data_->thread_, attr_ptr, ThreadEntry, this); - CHECK_EQ(0, result); - ASSERT(data_->thread_ != kNoThread); -} - - -void Thread::Join() { - pthread_join(data_->thread_, NULL); -} - - -Thread::LocalStorageKey Thread::CreateThreadLocalKey() { - pthread_key_t key; - int result = pthread_key_create(&key, NULL); - USE(result); - ASSERT(result == 0); - return static_cast(key); -} - - -void Thread::DeleteThreadLocalKey(LocalStorageKey key) { - pthread_key_t pthread_key = static_cast(key); - int result = pthread_key_delete(pthread_key); - USE(result); - ASSERT(result == 0); -} - - -void* Thread::GetThreadLocal(LocalStorageKey key) { - pthread_key_t pthread_key = static_cast(key); - return pthread_getspecific(pthread_key); -} - - -void Thread::SetThreadLocal(LocalStorageKey key, void* value) { - pthread_key_t pthread_key = static_cast(key); - pthread_setspecific(pthread_key, value); -} - - class LinuxSemaphore : public Semaphore { public: explicit LinuxSemaphore(int count) { sem_init(&sem_, 0, count); } diff --git a/src/platform-macos.cc b/src/platform-macos.cc index 30e90bb614..12a3e663f0 100644 --- a/src/platform-macos.cc +++ b/src/platform-macos.cc @@ -78,10 +78,6 @@ extern "C" { namespace v8 { namespace internal { -// 0 is never a valid thread id on MacOSX since a pthread_t is -// a pointer. -static const pthread_t kNoThread = (pthread_t) 0; - double ceiling(double x) { // Correct Mac OS X Leopard 'ceil' behavior. @@ -421,177 +417,6 @@ bool VirtualMemory::HasLazyCommits() { } -class Thread::PlatformData : public Malloced { - public: - PlatformData() : thread_(kNoThread) {} - pthread_t thread_; // Thread handle for pthread. -}; - - -Thread::Thread(const Options& options) - : data_(new PlatformData), - stack_size_(options.stack_size()), - start_semaphore_(NULL) { - set_name(options.name()); -} - - -Thread::~Thread() { - delete data_; -} - - -static void SetThreadName(const char* name) { - // pthread_setname_np is only available in 10.6 or later, so test - // for it at runtime. - int (*dynamic_pthread_setname_np)(const char*); - *reinterpret_cast(&dynamic_pthread_setname_np) = - dlsym(RTLD_DEFAULT, "pthread_setname_np"); - if (!dynamic_pthread_setname_np) - return; - - // Mac OS X does not expose the length limit of the name, so hardcode it. - static const int kMaxNameLength = 63; - USE(kMaxNameLength); - ASSERT(Thread::kMaxThreadNameLength <= kMaxNameLength); - dynamic_pthread_setname_np(name); -} - - -static void* ThreadEntry(void* arg) { - Thread* thread = reinterpret_cast(arg); - // 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->data()->thread_ = pthread_self(); - SetThreadName(thread->name()); - ASSERT(thread->data()->thread_ != kNoThread); - thread->NotifyStartedAndRun(); - return NULL; -} - - -void Thread::set_name(const char* name) { - strncpy(name_, name, sizeof(name_)); - name_[sizeof(name_) - 1] = '\0'; -} - - -void Thread::Start() { - pthread_attr_t* attr_ptr = NULL; - pthread_attr_t attr; - if (stack_size_ > 0) { - pthread_attr_init(&attr); - pthread_attr_setstacksize(&attr, static_cast(stack_size_)); - attr_ptr = &attr; - } - pthread_create(&data_->thread_, attr_ptr, ThreadEntry, this); - ASSERT(data_->thread_ != kNoThread); -} - - -void Thread::Join() { - pthread_join(data_->thread_, NULL); -} - - -#ifdef V8_FAST_TLS_SUPPORTED - -static Atomic32 tls_base_offset_initialized = 0; -intptr_t kMacTlsBaseOffset = 0; - -// It's safe to do the initialization more that once, but it has to be -// done at least once. -static void InitializeTlsBaseOffset() { - const size_t kBufferSize = 128; - char buffer[kBufferSize]; - size_t buffer_size = kBufferSize; - int ctl_name[] = { CTL_KERN , KERN_OSRELEASE }; - if (sysctl(ctl_name, 2, buffer, &buffer_size, NULL, 0) != 0) { - V8_Fatal(__FILE__, __LINE__, "V8 failed to get kernel version"); - } - // The buffer now contains a string of the form XX.YY.ZZ, where - // XX is the major kernel version component. - // Make sure the buffer is 0-terminated. - buffer[kBufferSize - 1] = '\0'; - char* period_pos = strchr(buffer, '.'); - *period_pos = '\0'; - int kernel_version_major = - static_cast(strtol(buffer, NULL, 10)); // NOLINT - // The constants below are taken from pthreads.s from the XNU kernel - // sources archive at www.opensource.apple.com. - if (kernel_version_major < 11) { - // 8.x.x (Tiger), 9.x.x (Leopard), 10.x.x (Snow Leopard) have the - // same offsets. -#if V8_HOST_ARCH_IA32 - kMacTlsBaseOffset = 0x48; -#else - kMacTlsBaseOffset = 0x60; -#endif - } else { - // 11.x.x (Lion) changed the offset. - kMacTlsBaseOffset = 0; - } - - Release_Store(&tls_base_offset_initialized, 1); -} - - -static void CheckFastTls(Thread::LocalStorageKey key) { - void* expected = reinterpret_cast(0x1234CAFE); - Thread::SetThreadLocal(key, expected); - void* actual = Thread::GetExistingThreadLocal(key); - if (expected != actual) { - V8_Fatal(__FILE__, __LINE__, - "V8 failed to initialize fast TLS on current kernel"); - } - Thread::SetThreadLocal(key, NULL); -} - -#endif // V8_FAST_TLS_SUPPORTED - - -Thread::LocalStorageKey Thread::CreateThreadLocalKey() { -#ifdef V8_FAST_TLS_SUPPORTED - bool check_fast_tls = false; - if (tls_base_offset_initialized == 0) { - check_fast_tls = true; - InitializeTlsBaseOffset(); - } -#endif - pthread_key_t key; - int result = pthread_key_create(&key, NULL); - USE(result); - ASSERT(result == 0); - LocalStorageKey typed_key = static_cast(key); -#ifdef V8_FAST_TLS_SUPPORTED - // If we just initialized fast TLS support, make sure it works. - if (check_fast_tls) CheckFastTls(typed_key); -#endif - return typed_key; -} - - -void Thread::DeleteThreadLocalKey(LocalStorageKey key) { - pthread_key_t pthread_key = static_cast(key); - int result = pthread_key_delete(pthread_key); - USE(result); - ASSERT(result == 0); -} - - -void* Thread::GetThreadLocal(LocalStorageKey key) { - pthread_key_t pthread_key = static_cast(key); - return pthread_getspecific(pthread_key); -} - - -void Thread::SetThreadLocal(LocalStorageKey key, void* value) { - pthread_key_t pthread_key = static_cast(key); - pthread_setspecific(pthread_key, value); -} - - class MacOSSemaphore : public Semaphore { public: explicit MacOSSemaphore(int count) { diff --git a/src/platform-openbsd.cc b/src/platform-openbsd.cc index fbd07c62f8..4340094f12 100644 --- a/src/platform-openbsd.cc +++ b/src/platform-openbsd.cc @@ -477,96 +477,6 @@ bool VirtualMemory::HasLazyCommits() { } -class Thread::PlatformData : public Malloced { - public: - PlatformData() : thread_(kNoThread) {} - - pthread_t thread_; // Thread handle for pthread. -}; - -Thread::Thread(const Options& options) - : data_(new PlatformData()), - stack_size_(options.stack_size()), - start_semaphore_(NULL) { - set_name(options.name()); -} - - -Thread::~Thread() { - delete data_; -} - - -static void* ThreadEntry(void* arg) { - Thread* thread = reinterpret_cast(arg); - // 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. -#ifdef PR_SET_NAME - prctl(PR_SET_NAME, - reinterpret_cast(thread->name()), // NOLINT - 0, 0, 0); -#endif - thread->data()->thread_ = pthread_self(); - ASSERT(thread->data()->thread_ != kNoThread); - thread->NotifyStartedAndRun(); - return NULL; -} - - -void Thread::set_name(const char* name) { - strncpy(name_, name, sizeof(name_)); - name_[sizeof(name_) - 1] = '\0'; -} - - -void Thread::Start() { - pthread_attr_t* attr_ptr = NULL; - pthread_attr_t attr; - if (stack_size_ > 0) { - pthread_attr_init(&attr); - pthread_attr_setstacksize(&attr, static_cast(stack_size_)); - attr_ptr = &attr; - } - pthread_create(&data_->thread_, attr_ptr, ThreadEntry, this); - ASSERT(data_->thread_ != kNoThread); -} - - -void Thread::Join() { - pthread_join(data_->thread_, NULL); -} - - -Thread::LocalStorageKey Thread::CreateThreadLocalKey() { - pthread_key_t key; - int result = pthread_key_create(&key, NULL); - USE(result); - ASSERT(result == 0); - return static_cast(key); -} - - -void Thread::DeleteThreadLocalKey(LocalStorageKey key) { - pthread_key_t pthread_key = static_cast(key); - int result = pthread_key_delete(pthread_key); - USE(result); - ASSERT(result == 0); -} - - -void* Thread::GetThreadLocal(LocalStorageKey key) { - pthread_key_t pthread_key = static_cast(key); - return pthread_getspecific(pthread_key); -} - - -void Thread::SetThreadLocal(LocalStorageKey key, void* value) { - pthread_key_t pthread_key = static_cast(key); - pthread_setspecific(pthread_key, value); -} - - class OpenBSDSemaphore : public Semaphore { public: explicit OpenBSDSemaphore(int count) { sem_init(&sem_, 0, count); } diff --git a/src/platform-posix.cc b/src/platform-posix.cc index 47fa5e55a0..ff5f70addc 100644 --- a/src/platform-posix.cc +++ b/src/platform-posix.cc @@ -31,7 +31,11 @@ #include "platform-posix.h" +#include #include +#if defined(__DragonFly__) || defined(__FreeBSD__) || defined(__OpenBSD__) +#include // for pthread_set_name_np +#endif #include // for sched_yield #include #include @@ -43,6 +47,13 @@ #include #include #include +#if defined(__linux__) +#include // for prctl +#endif +#if defined(__APPLE__) || defined(__DragonFly__) || defined(__FreeBSD__) || \ + defined(__NetBSD__) || defined(__OpenBSD__) +#include // for sysctl +#endif #include #include @@ -63,6 +74,9 @@ namespace v8 { namespace internal { +// 0 is never a valid thread id. +static const pthread_t kNoThread = (pthread_t) 0; + // Maximum size of the virtual memory. 0 means there is no artificial // limit. @@ -217,7 +231,7 @@ UNARY_MATH_FUNCTION(log, CreateTranscendentalFunction(TranscendentalCache::LOG)) UNARY_MATH_FUNCTION(exp, CreateExpFunction()) UNARY_MATH_FUNCTION(sqrt, CreateSqrtFunction()) -#undef MATH_FUNCTION +#undef UNARY_MATH_FUNCTION void lazily_initialize_fast_exp() { @@ -468,8 +482,229 @@ void OS::StrNCpy(Vector dest, const char* src, size_t n) { // POSIX thread support. // +class Thread::PlatformData : public Malloced { + public: + PlatformData() : thread_(kNoThread) {} + pthread_t thread_; // Thread handle for pthread. +}; + +Thread::Thread(const Options& options) + : data_(new PlatformData), + stack_size_(options.stack_size()), + start_semaphore_(NULL) { + set_name(options.name()); +} + + +Thread::~Thread() { + delete data_; +} + + +static void SetThreadName(const char* name) { + int result = 0; +#if defined(__DragonFly__) || defined(__FreeBSD__) || defined(__OpenBSD__) + result = pthread_set_name_np(pthread_self(), name); +#elif defined(__NetBSD__) + STATIC_ASSERT(Thread::kMaxThreadNameLength <= PTHREAD_MAX_NAMELEN_NP); + result = pthread_setname_np(pthread_self(), "%s", name); +#elif defined(__APPLE__) + // pthread_setname_np is only available in 10.6 or later, so test + // for it at runtime. + int (*dynamic_pthread_setname_np)(const char*); + *reinterpret_cast(&dynamic_pthread_setname_np) = + dlsym(RTLD_DEFAULT, "pthread_setname_np"); + if (dynamic_pthread_setname_np == NULL) + return; + + // Mac OS X does not expose the length limit of the name, so hardcode it. + static const int kMaxNameLength = 63; + STATIC_ASSERT(Thread::kMaxThreadNameLength <= kMaxNameLength); + result = dynamic_pthread_setname_np(name); +#elif defined(PR_SET_NAME) + result = prctl(PR_SET_NAME, + reinterpret_cast(name), // NOLINT + 0, 0, 0); +#endif + ASSERT_EQ(0, result); + USE(result); +} + + +static void* ThreadEntry(void* arg) { + Thread* thread = reinterpret_cast(arg); + // 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->data()->thread_ = pthread_self(); + SetThreadName(thread->name()); + ASSERT(thread->data()->thread_ != kNoThread); + thread->NotifyStartedAndRun(); + return NULL; +} + + +void Thread::set_name(const char* name) { + strncpy(name_, name, sizeof(name_)); + name_[sizeof(name_) - 1] = '\0'; +} + + +void Thread::Start() { + int result; + pthread_attr_t attr; + memset(&attr, 0, sizeof(attr)); + result = pthread_attr_init(&attr); + ASSERT_EQ(0, result); + // Native client uses default stack size. +#if !defined(__native_client__) + if (stack_size_ > 0) { + result = pthread_attr_setstacksize(&attr, static_cast(stack_size_)); + ASSERT_EQ(0, result); + } +#endif + result = pthread_create(&data_->thread_, &attr, ThreadEntry, this); + ASSERT_EQ(0, result); + result = pthread_attr_destroy(&attr); + ASSERT_EQ(0, result); + ASSERT(data_->thread_ != kNoThread); + USE(result); +} + + +void Thread::Join() { + pthread_join(data_->thread_, NULL); +} + + void Thread::YieldCPU() { - sched_yield(); + int result = sched_yield(); + ASSERT_EQ(0, result); + USE(result); +} + + +static Thread::LocalStorageKey PthreadKeyToLocalKey(pthread_key_t pthread_key) { +#if defined(__CYGWIN__) + // We need to cast pthread_key_t to Thread::LocalStorageKey in two steps + // because pthread_key_t is a pointer type on Cygwin. This will probably not + // work on 64-bit platforms, but Cygwin doesn't support 64-bit anyway. + STATIC_ASSERT(sizeof(Thread::LocalStorageKey) == sizeof(pthread_key_t)); + intptr_t ptr_key = reinterpret_cast(pthread_key); + return static_cast(ptr_key); +#else + return static_cast(pthread_key); +#endif +} + + +static pthread_key_t LocalKeyToPthreadKey(Thread::LocalStorageKey local_key) { +#if defined(__CYGWIN__) + STATIC_ASSERT(sizeof(Thread::LocalStorageKey) == sizeof(pthread_key_t)); + intptr_t ptr_key = static_cast(local_key); + return reinterpret_cast(ptr_key); +#else + return static_cast(local_key); +#endif +} + + +#ifdef V8_FAST_TLS_SUPPORTED + +static Atomic32 tls_base_offset_initialized = 0; +intptr_t kMacTlsBaseOffset = 0; + +// It's safe to do the initialization more that once, but it has to be +// done at least once. +static void InitializeTlsBaseOffset() { + const size_t kBufferSize = 128; + char buffer[kBufferSize]; + size_t buffer_size = kBufferSize; + int ctl_name[] = { CTL_KERN , KERN_OSRELEASE }; + if (sysctl(ctl_name, 2, buffer, &buffer_size, NULL, 0) != 0) { + V8_Fatal(__FILE__, __LINE__, "V8 failed to get kernel version"); + } + // The buffer now contains a string of the form XX.YY.ZZ, where + // XX is the major kernel version component. + // Make sure the buffer is 0-terminated. + buffer[kBufferSize - 1] = '\0'; + char* period_pos = strchr(buffer, '.'); + *period_pos = '\0'; + int kernel_version_major = + static_cast(strtol(buffer, NULL, 10)); // NOLINT + // The constants below are taken from pthreads.s from the XNU kernel + // sources archive at www.opensource.apple.com. + if (kernel_version_major < 11) { + // 8.x.x (Tiger), 9.x.x (Leopard), 10.x.x (Snow Leopard) have the + // same offsets. +#if V8_HOST_ARCH_IA32 + kMacTlsBaseOffset = 0x48; +#else + kMacTlsBaseOffset = 0x60; +#endif + } else { + // 11.x.x (Lion) changed the offset. + kMacTlsBaseOffset = 0; + } + + Release_Store(&tls_base_offset_initialized, 1); +} + + +static void CheckFastTls(Thread::LocalStorageKey key) { + void* expected = reinterpret_cast(0x1234CAFE); + Thread::SetThreadLocal(key, expected); + void* actual = Thread::GetExistingThreadLocal(key); + if (expected != actual) { + V8_Fatal(__FILE__, __LINE__, + "V8 failed to initialize fast TLS on current kernel"); + } + Thread::SetThreadLocal(key, NULL); +} + +#endif // V8_FAST_TLS_SUPPORTED + + +Thread::LocalStorageKey Thread::CreateThreadLocalKey() { +#ifdef V8_FAST_TLS_SUPPORTED + bool check_fast_tls = false; + if (tls_base_offset_initialized == 0) { + check_fast_tls = true; + InitializeTlsBaseOffset(); + } +#endif + pthread_key_t key; + int result = pthread_key_create(&key, NULL); + ASSERT_EQ(0, result); + USE(result); + LocalStorageKey local_key = PthreadKeyToLocalKey(key); +#ifdef V8_FAST_TLS_SUPPORTED + // If we just initialized fast TLS support, make sure it works. + if (check_fast_tls) CheckFastTls(local_key); +#endif + return local_key; +} + + +void Thread::DeleteThreadLocalKey(LocalStorageKey key) { + pthread_key_t pthread_key = LocalKeyToPthreadKey(key); + int result = pthread_key_delete(pthread_key); + ASSERT_EQ(0, result); + USE(result); +} + + +void* Thread::GetThreadLocal(LocalStorageKey key) { + pthread_key_t pthread_key = LocalKeyToPthreadKey(key); + return pthread_getspecific(pthread_key); +} + + +void Thread::SetThreadLocal(LocalStorageKey key, void* value) { + pthread_key_t pthread_key = LocalKeyToPthreadKey(key); + int result = pthread_setspecific(pthread_key, value); + ASSERT_EQ(0, result); + USE(result); } diff --git a/src/platform-solaris.cc b/src/platform-solaris.cc index 53d8983be4..1ecca16507 100644 --- a/src/platform-solaris.cc +++ b/src/platform-solaris.cc @@ -81,11 +81,6 @@ namespace v8 { namespace internal { -// 0 is never a valid thread id on Solaris since the main thread is 1 and -// subsequent have their ids incremented from there -static const pthread_t kNoThread = (pthread_t) 0; - - double ceiling(double x) { return ceil(x); } @@ -414,90 +409,6 @@ bool VirtualMemory::HasLazyCommits() { } -class Thread::PlatformData : public Malloced { - public: - PlatformData() : thread_(kNoThread) { } - - pthread_t thread_; // Thread handle for pthread. -}; - - -Thread::Thread(const Options& options) - : data_(new PlatformData()), - stack_size_(options.stack_size()), - start_semaphore_(NULL) { - set_name(options.name()); -} - - -Thread::~Thread() { - delete data_; -} - - -static void* ThreadEntry(void* arg) { - Thread* thread = reinterpret_cast(arg); - // 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->data()->thread_ = pthread_self(); - ASSERT(thread->data()->thread_ != kNoThread); - thread->NotifyStartedAndRun(); - return NULL; -} - - -void Thread::set_name(const char* name) { - strncpy(name_, name, sizeof(name_)); - name_[sizeof(name_) - 1] = '\0'; -} - - -void Thread::Start() { - pthread_attr_t attr; - if (stack_size_ > 0) { - pthread_attr_init(&attr); - pthread_attr_setstacksize(&attr, static_cast(stack_size_)); - } - pthread_create(&data_->thread_, NULL, ThreadEntry, this); - ASSERT(data_->thread_ != kNoThread); -} - - -void Thread::Join() { - pthread_join(data_->thread_, NULL); -} - - -Thread::LocalStorageKey Thread::CreateThreadLocalKey() { - pthread_key_t key; - int result = pthread_key_create(&key, NULL); - USE(result); - ASSERT(result == 0); - return static_cast(key); -} - - -void Thread::DeleteThreadLocalKey(LocalStorageKey key) { - pthread_key_t pthread_key = static_cast(key); - int result = pthread_key_delete(pthread_key); - USE(result); - ASSERT(result == 0); -} - - -void* Thread::GetThreadLocal(LocalStorageKey key) { - pthread_key_t pthread_key = static_cast(key); - return pthread_getspecific(pthread_key); -} - - -void Thread::SetThreadLocal(LocalStorageKey key, void* value) { - pthread_key_t pthread_key = static_cast(key); - pthread_setspecific(pthread_key, value); -} - - class SolarisSemaphore : public Semaphore { public: explicit SolarisSemaphore(int count) { sem_init(&sem_, 0, count); }