Index: src/platform-posix.cc |
diff --git a/src/platform-posix.cc b/src/platform-posix.cc |
deleted file mode 100644 |
index bc9d8e2fd419296037a9d7ee809e5225011ef6e4..0000000000000000000000000000000000000000 |
--- a/src/platform-posix.cc |
+++ /dev/null |
@@ -1,726 +0,0 @@ |
-// Copyright 2012 the V8 project authors. All rights reserved. |
-// Use of this source code is governed by a BSD-style license that can be |
-// found in the LICENSE file. |
- |
-// Platform-specific code for POSIX goes here. This is not a platform on its |
-// own, but contains the parts which are the same across the POSIX platforms |
-// Linux, MacOS, FreeBSD, OpenBSD, NetBSD and QNX. |
- |
-#include <dlfcn.h> |
-#include <errno.h> |
-#include <limits.h> |
-#include <pthread.h> |
-#if defined(__DragonFly__) || defined(__FreeBSD__) || defined(__OpenBSD__) |
-#include <pthread_np.h> // for pthread_set_name_np |
-#endif |
-#include <sched.h> // for sched_yield |
-#include <time.h> |
-#include <unistd.h> |
- |
-#include <sys/mman.h> |
-#include <sys/resource.h> |
-#include <sys/stat.h> |
-#include <sys/time.h> |
-#include <sys/types.h> |
- |
-#if defined(__linux__) |
-#include <sys/prctl.h> // NOLINT, for prctl |
-#endif |
-#if defined(__APPLE__) || defined(__DragonFly__) || defined(__FreeBSD__) || \ |
- defined(__NetBSD__) || defined(__OpenBSD__) |
-#include <sys/sysctl.h> // NOLINT, for sysctl |
-#endif |
- |
-#include <arpa/inet.h> |
-#include <netdb.h> |
-#include <netinet/in.h> |
- |
-#undef MAP_TYPE |
- |
-#if defined(ANDROID) && !defined(V8_ANDROID_LOG_STDOUT) |
-#define LOG_TAG "v8" |
-#include <android/log.h> // NOLINT |
-#endif |
- |
-#include <cmath> |
-#include <cstdlib> |
- |
-#include "src/base/lazy-instance.h" |
-#include "src/base/macros.h" |
-#include "src/platform.h" |
-#include "src/platform/time.h" |
-#include "src/utils/random-number-generator.h" |
- |
-#ifdef V8_FAST_TLS_SUPPORTED |
-#include "src/base/atomicops.h" |
-#endif |
- |
-namespace v8 { |
-namespace internal { |
- |
-namespace { |
- |
-// 0 is never a valid thread id. |
-const pthread_t kNoThread = (pthread_t) 0; |
- |
-bool g_hard_abort = false; |
- |
-const char* g_gc_fake_mmap = NULL; |
- |
-} // namespace |
- |
- |
-int OS::NumberOfProcessorsOnline() { |
- return static_cast<int>(sysconf(_SC_NPROCESSORS_ONLN)); |
-} |
- |
- |
-// Maximum size of the virtual memory. 0 means there is no artificial |
-// limit. |
- |
-intptr_t OS::MaxVirtualMemory() { |
- struct rlimit limit; |
- int result = getrlimit(RLIMIT_DATA, &limit); |
- if (result != 0) return 0; |
-#if V8_OS_NACL |
- // The NaCl compiler doesn't like resource.h constants. |
- if (static_cast<int>(limit.rlim_cur) == -1) return 0; |
-#else |
- if (limit.rlim_cur == RLIM_INFINITY) return 0; |
-#endif |
- return limit.rlim_cur; |
-} |
- |
- |
-uint64_t OS::TotalPhysicalMemory() { |
-#if V8_OS_MACOSX |
- int mib[2]; |
- mib[0] = CTL_HW; |
- mib[1] = HW_MEMSIZE; |
- int64_t size = 0; |
- size_t len = sizeof(size); |
- if (sysctl(mib, 2, &size, &len, NULL, 0) != 0) { |
- UNREACHABLE(); |
- return 0; |
- } |
- return static_cast<uint64_t>(size); |
-#elif V8_OS_FREEBSD |
- int pages, page_size; |
- size_t size = sizeof(pages); |
- sysctlbyname("vm.stats.vm.v_page_count", &pages, &size, NULL, 0); |
- sysctlbyname("vm.stats.vm.v_page_size", &page_size, &size, NULL, 0); |
- if (pages == -1 || page_size == -1) { |
- UNREACHABLE(); |
- return 0; |
- } |
- return static_cast<uint64_t>(pages) * page_size; |
-#elif V8_OS_CYGWIN |
- MEMORYSTATUS memory_info; |
- memory_info.dwLength = sizeof(memory_info); |
- if (!GlobalMemoryStatus(&memory_info)) { |
- UNREACHABLE(); |
- return 0; |
- } |
- return static_cast<uint64_t>(memory_info.dwTotalPhys); |
-#elif V8_OS_QNX |
- struct stat stat_buf; |
- if (stat("/proc", &stat_buf) != 0) { |
- UNREACHABLE(); |
- return 0; |
- } |
- return static_cast<uint64_t>(stat_buf.st_size); |
-#else |
- intptr_t pages = sysconf(_SC_PHYS_PAGES); |
- intptr_t page_size = sysconf(_SC_PAGESIZE); |
- if (pages == -1 || page_size == -1) { |
- UNREACHABLE(); |
- return 0; |
- } |
- return static_cast<uint64_t>(pages) * page_size; |
-#endif |
-} |
- |
- |
-int OS::ActivationFrameAlignment() { |
-#if V8_TARGET_ARCH_ARM |
- // On EABI ARM targets this is required for fp correctness in the |
- // runtime system. |
- return 8; |
-#elif V8_TARGET_ARCH_MIPS |
- return 8; |
-#else |
- // Otherwise we just assume 16 byte alignment, i.e.: |
- // - With gcc 4.4 the tree vectorization optimizer can generate code |
- // that requires 16 byte alignment such as movdqa on x86. |
- // - Mac OS X and Solaris (64-bit) activation frames must be 16 byte-aligned; |
- // see "Mac OS X ABI Function Call Guide" |
- return 16; |
-#endif |
-} |
- |
- |
-intptr_t OS::CommitPageSize() { |
- static intptr_t page_size = getpagesize(); |
- return page_size; |
-} |
- |
- |
-void OS::Free(void* address, const size_t size) { |
- // TODO(1240712): munmap has a return value which is ignored here. |
- int result = munmap(address, size); |
- USE(result); |
- ASSERT(result == 0); |
-} |
- |
- |
-// Get rid of writable permission on code allocations. |
-void OS::ProtectCode(void* address, const size_t size) { |
-#if V8_OS_CYGWIN |
- DWORD old_protect; |
- VirtualProtect(address, size, PAGE_EXECUTE_READ, &old_protect); |
-#elif V8_OS_NACL |
- // The Native Client port of V8 uses an interpreter, so |
- // code pages don't need PROT_EXEC. |
- mprotect(address, size, PROT_READ); |
-#else |
- mprotect(address, size, PROT_READ | PROT_EXEC); |
-#endif |
-} |
- |
- |
-// Create guard pages. |
-void OS::Guard(void* address, const size_t size) { |
-#if V8_OS_CYGWIN |
- DWORD oldprotect; |
- VirtualProtect(address, size, PAGE_NOACCESS, &oldprotect); |
-#else |
- mprotect(address, size, PROT_NONE); |
-#endif |
-} |
- |
- |
-static base::LazyInstance<RandomNumberGenerator>::type |
- platform_random_number_generator = LAZY_INSTANCE_INITIALIZER; |
- |
- |
-void OS::Initialize(int64_t random_seed, bool hard_abort, |
- const char* const gc_fake_mmap) { |
- if (random_seed) { |
- platform_random_number_generator.Pointer()->SetSeed(random_seed); |
- } |
- g_hard_abort = hard_abort; |
- g_gc_fake_mmap = gc_fake_mmap; |
-} |
- |
- |
-const char* OS::GetGCFakeMMapFile() { |
- return g_gc_fake_mmap; |
-} |
- |
- |
-void* OS::GetRandomMmapAddr() { |
-#if V8_OS_NACL |
- // TODO(bradchen): restore randomization once Native Client gets |
- // smarter about using mmap address hints. |
- // See http://code.google.com/p/nativeclient/issues/3341 |
- return NULL; |
-#endif |
-#if defined(ADDRESS_SANITIZER) || defined(MEMORY_SANITIZER) || \ |
- defined(THREAD_SANITIZER) |
- // Dynamic tools do not support custom mmap addresses. |
- return NULL; |
-#endif |
- uintptr_t raw_addr; |
- platform_random_number_generator.Pointer()->NextBytes(&raw_addr, |
- sizeof(raw_addr)); |
-#if V8_TARGET_ARCH_X64 |
- // Currently available CPUs have 48 bits of virtual addressing. Truncate |
- // the hint address to 46 bits to give the kernel a fighting chance of |
- // fulfilling our placement request. |
- raw_addr &= V8_UINT64_C(0x3ffffffff000); |
-#else |
- raw_addr &= 0x3ffff000; |
- |
-# ifdef __sun |
- // For our Solaris/illumos mmap hint, we pick a random address in the bottom |
- // half of the top half of the address space (that is, the third quarter). |
- // Because we do not MAP_FIXED, this will be treated only as a hint -- the |
- // system will not fail to mmap() because something else happens to already |
- // be mapped at our random address. We deliberately set the hint high enough |
- // to get well above the system's break (that is, the heap); Solaris and |
- // illumos will try the hint and if that fails allocate as if there were |
- // no hint at all. The high hint prevents the break from getting hemmed in |
- // at low values, ceding half of the address space to the system heap. |
- raw_addr += 0x80000000; |
-# else |
- // The range 0x20000000 - 0x60000000 is relatively unpopulated across a |
- // variety of ASLR modes (PAE kernel, NX compat mode, etc) and on macos |
- // 10.6 and 10.7. |
- raw_addr += 0x20000000; |
-# endif |
-#endif |
- return reinterpret_cast<void*>(raw_addr); |
-} |
- |
- |
-size_t OS::AllocateAlignment() { |
- return static_cast<size_t>(sysconf(_SC_PAGESIZE)); |
-} |
- |
- |
-void OS::Sleep(int milliseconds) { |
- useconds_t ms = static_cast<useconds_t>(milliseconds); |
- usleep(1000 * ms); |
-} |
- |
- |
-void OS::Abort() { |
- if (g_hard_abort) { |
- V8_IMMEDIATE_CRASH(); |
- } |
- // Redirect to std abort to signal abnormal program termination. |
- abort(); |
-} |
- |
- |
-void OS::DebugBreak() { |
-#if V8_HOST_ARCH_ARM |
- asm("bkpt 0"); |
-#elif V8_HOST_ARCH_ARM64 |
- asm("brk 0"); |
-#elif V8_HOST_ARCH_MIPS |
- asm("break"); |
-#elif V8_HOST_ARCH_IA32 |
-#if defined(__native_client__) |
- asm("hlt"); |
-#else |
- asm("int $3"); |
-#endif // __native_client__ |
-#elif V8_HOST_ARCH_X64 |
- asm("int $3"); |
-#else |
-#error Unsupported host architecture. |
-#endif |
-} |
- |
- |
-// ---------------------------------------------------------------------------- |
-// Math functions |
- |
-double OS::nan_value() { |
- // NAN from math.h is defined in C99 and not in POSIX. |
- return NAN; |
-} |
- |
- |
-int OS::GetCurrentProcessId() { |
- return static_cast<int>(getpid()); |
-} |
- |
- |
-// ---------------------------------------------------------------------------- |
-// POSIX date/time support. |
-// |
- |
-int OS::GetUserTime(uint32_t* secs, uint32_t* usecs) { |
- struct rusage usage; |
- |
- if (getrusage(RUSAGE_SELF, &usage) < 0) return -1; |
- *secs = usage.ru_utime.tv_sec; |
- *usecs = usage.ru_utime.tv_usec; |
- return 0; |
-} |
- |
- |
-double OS::TimeCurrentMillis() { |
- return Time::Now().ToJsTime(); |
-} |
- |
- |
-class TimezoneCache {}; |
- |
- |
-TimezoneCache* OS::CreateTimezoneCache() { |
- return NULL; |
-} |
- |
- |
-void OS::DisposeTimezoneCache(TimezoneCache* cache) { |
- ASSERT(cache == NULL); |
-} |
- |
- |
-void OS::ClearTimezoneCache(TimezoneCache* cache) { |
- ASSERT(cache == NULL); |
-} |
- |
- |
-double OS::DaylightSavingsOffset(double time, TimezoneCache*) { |
- if (std::isnan(time)) return nan_value(); |
- time_t tv = static_cast<time_t>(std::floor(time/msPerSecond)); |
- struct tm* t = localtime(&tv); |
- if (NULL == t) return nan_value(); |
- return t->tm_isdst > 0 ? 3600 * msPerSecond : 0; |
-} |
- |
- |
-int OS::GetLastError() { |
- return errno; |
-} |
- |
- |
-// ---------------------------------------------------------------------------- |
-// POSIX stdio support. |
-// |
- |
-FILE* OS::FOpen(const char* path, const char* mode) { |
- FILE* file = fopen(path, mode); |
- if (file == NULL) return NULL; |
- struct stat file_stat; |
- if (fstat(fileno(file), &file_stat) != 0) return NULL; |
- bool is_regular_file = ((file_stat.st_mode & S_IFREG) != 0); |
- if (is_regular_file) return file; |
- fclose(file); |
- return NULL; |
-} |
- |
- |
-bool OS::Remove(const char* path) { |
- return (remove(path) == 0); |
-} |
- |
- |
-FILE* OS::OpenTemporaryFile() { |
- return tmpfile(); |
-} |
- |
- |
-const char* const OS::LogFileOpenMode = "w"; |
- |
- |
-void OS::Print(const char* format, ...) { |
- va_list args; |
- va_start(args, format); |
- VPrint(format, args); |
- va_end(args); |
-} |
- |
- |
-void OS::VPrint(const char* format, va_list args) { |
-#if defined(ANDROID) && !defined(V8_ANDROID_LOG_STDOUT) |
- __android_log_vprint(ANDROID_LOG_INFO, LOG_TAG, format, args); |
-#else |
- vprintf(format, args); |
-#endif |
-} |
- |
- |
-void OS::FPrint(FILE* out, const char* format, ...) { |
- va_list args; |
- va_start(args, format); |
- VFPrint(out, format, args); |
- va_end(args); |
-} |
- |
- |
-void OS::VFPrint(FILE* out, const char* format, va_list args) { |
-#if defined(ANDROID) && !defined(V8_ANDROID_LOG_STDOUT) |
- __android_log_vprint(ANDROID_LOG_INFO, LOG_TAG, format, args); |
-#else |
- vfprintf(out, format, args); |
-#endif |
-} |
- |
- |
-void OS::PrintError(const char* format, ...) { |
- va_list args; |
- va_start(args, format); |
- VPrintError(format, args); |
- va_end(args); |
-} |
- |
- |
-void OS::VPrintError(const char* format, va_list args) { |
-#if defined(ANDROID) && !defined(V8_ANDROID_LOG_STDOUT) |
- __android_log_vprint(ANDROID_LOG_ERROR, LOG_TAG, format, args); |
-#else |
- vfprintf(stderr, format, args); |
-#endif |
-} |
- |
- |
-int OS::SNPrintF(char* str, int length, const char* format, ...) { |
- va_list args; |
- va_start(args, format); |
- int result = VSNPrintF(str, length, format, args); |
- va_end(args); |
- return result; |
-} |
- |
- |
-int OS::VSNPrintF(char* str, |
- int length, |
- const char* format, |
- va_list args) { |
- int n = vsnprintf(str, length, format, args); |
- if (n < 0 || n >= length) { |
- // If the length is zero, the assignment fails. |
- if (length > 0) |
- str[length - 1] = '\0'; |
- return -1; |
- } else { |
- return n; |
- } |
-} |
- |
- |
-// ---------------------------------------------------------------------------- |
-// POSIX string support. |
-// |
- |
-char* OS::StrChr(char* str, int c) { |
- return strchr(str, c); |
-} |
- |
- |
-void OS::StrNCpy(char* dest, int length, const char* src, size_t n) { |
- strncpy(dest, src, n); |
-} |
- |
- |
-// ---------------------------------------------------------------------------- |
-// POSIX thread support. |
-// |
- |
-class Thread::PlatformData { |
- public: |
- PlatformData() : thread_(kNoThread) {} |
- pthread_t thread_; // Thread handle for pthread. |
- // Synchronizes thread creation |
- Mutex thread_creation_mutex_; |
-}; |
- |
-Thread::Thread(const Options& options) |
- : data_(new PlatformData), |
- stack_size_(options.stack_size()), |
- start_semaphore_(NULL) { |
- if (stack_size_ > 0 && stack_size_ < PTHREAD_STACK_MIN) { |
- stack_size_ = PTHREAD_STACK_MIN; |
- } |
- set_name(options.name()); |
-} |
- |
- |
-Thread::~Thread() { |
- delete data_; |
-} |
- |
- |
-static void SetThreadName(const char* name) { |
-#if V8_OS_DRAGONFLYBSD || V8_OS_FREEBSD || V8_OS_OPENBSD |
- pthread_set_name_np(pthread_self(), name); |
-#elif V8_OS_NETBSD |
- STATIC_ASSERT(Thread::kMaxThreadNameLength <= PTHREAD_MAX_NAMELEN_NP); |
- pthread_setname_np(pthread_self(), "%s", name); |
-#elif V8_OS_MACOSX |
- // 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<void**>(&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); |
- dynamic_pthread_setname_np(name); |
-#elif defined(PR_SET_NAME) |
- prctl(PR_SET_NAME, |
- reinterpret_cast<unsigned long>(name), // NOLINT |
- 0, 0, 0); |
-#endif |
-} |
- |
- |
-static void* ThreadEntry(void* arg) { |
- Thread* thread = reinterpret_cast<Thread*>(arg); |
- // We take the lock here to make sure that pthread_create finished first since |
- // we don't know which thread will run first (the original thread or the new |
- // one). |
- { LockGuard<Mutex> lock_guard(&thread->data()->thread_creation_mutex_); } |
- 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 !V8_OS_NACL |
- if (stack_size_ > 0) { |
- result = pthread_attr_setstacksize(&attr, static_cast<size_t>(stack_size_)); |
- ASSERT_EQ(0, result); |
- } |
-#endif |
- { |
- LockGuard<Mutex> lock_guard(&data_->thread_creation_mutex_); |
- 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() { |
- int result = sched_yield(); |
- ASSERT_EQ(0, result); |
- USE(result); |
-} |
- |
- |
-static Thread::LocalStorageKey PthreadKeyToLocalKey(pthread_key_t pthread_key) { |
-#if V8_OS_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<intptr_t>(pthread_key); |
- return static_cast<Thread::LocalStorageKey>(ptr_key); |
-#else |
- return static_cast<Thread::LocalStorageKey>(pthread_key); |
-#endif |
-} |
- |
- |
-static pthread_key_t LocalKeyToPthreadKey(Thread::LocalStorageKey local_key) { |
-#if V8_OS_CYGWIN |
- STATIC_ASSERT(sizeof(Thread::LocalStorageKey) == sizeof(pthread_key_t)); |
- intptr_t ptr_key = static_cast<intptr_t>(local_key); |
- return reinterpret_cast<pthread_key_t>(ptr_key); |
-#else |
- return static_cast<pthread_key_t>(local_key); |
-#endif |
-} |
- |
- |
-#ifdef V8_FAST_TLS_SUPPORTED |
- |
-static base::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<int>(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; |
- } |
- |
- base::Release_Store(&tls_base_offset_initialized, 1); |
-} |
- |
- |
-static void CheckFastTls(Thread::LocalStorageKey key) { |
- void* expected = reinterpret_cast<void*>(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); |
-} |
- |
- |
-} } // namespace v8::internal |