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

Side by Side Diff: src/platform-posix.cc

Issue 358363002: Move platform abstraction to base library (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: updates Created 6 years, 5 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 // Platform-specific code for POSIX goes here. This is not a platform on its
6 // own, but contains the parts which are the same across the POSIX platforms
7 // Linux, MacOS, FreeBSD, OpenBSD, NetBSD and QNX.
8
9 #include <dlfcn.h>
10 #include <errno.h>
11 #include <limits.h>
12 #include <pthread.h>
13 #if defined(__DragonFly__) || defined(__FreeBSD__) || defined(__OpenBSD__)
14 #include <pthread_np.h> // for pthread_set_name_np
15 #endif
16 #include <sched.h> // for sched_yield
17 #include <time.h>
18 #include <unistd.h>
19
20 #include <sys/mman.h>
21 #include <sys/resource.h>
22 #include <sys/stat.h>
23 #include <sys/time.h>
24 #include <sys/types.h>
25
26 #if defined(__linux__)
27 #include <sys/prctl.h> // NOLINT, for prctl
28 #endif
29 #if defined(__APPLE__) || defined(__DragonFly__) || defined(__FreeBSD__) || \
30 defined(__NetBSD__) || defined(__OpenBSD__)
31 #include <sys/sysctl.h> // NOLINT, for sysctl
32 #endif
33
34 #include <arpa/inet.h>
35 #include <netdb.h>
36 #include <netinet/in.h>
37
38 #undef MAP_TYPE
39
40 #if defined(ANDROID) && !defined(V8_ANDROID_LOG_STDOUT)
41 #define LOG_TAG "v8"
42 #include <android/log.h> // NOLINT
43 #endif
44
45 #include <cmath>
46 #include <cstdlib>
47
48 #include "src/base/lazy-instance.h"
49 #include "src/base/macros.h"
50 #include "src/platform.h"
51 #include "src/platform/time.h"
52 #include "src/utils/random-number-generator.h"
53
54 #ifdef V8_FAST_TLS_SUPPORTED
55 #include "src/base/atomicops.h"
56 #endif
57
58 namespace v8 {
59 namespace internal {
60
61 namespace {
62
63 // 0 is never a valid thread id.
64 const pthread_t kNoThread = (pthread_t) 0;
65
66 bool g_hard_abort = false;
67
68 const char* g_gc_fake_mmap = NULL;
69
70 } // namespace
71
72
73 int OS::NumberOfProcessorsOnline() {
74 return static_cast<int>(sysconf(_SC_NPROCESSORS_ONLN));
75 }
76
77
78 // Maximum size of the virtual memory. 0 means there is no artificial
79 // limit.
80
81 intptr_t OS::MaxVirtualMemory() {
82 struct rlimit limit;
83 int result = getrlimit(RLIMIT_DATA, &limit);
84 if (result != 0) return 0;
85 #if V8_OS_NACL
86 // The NaCl compiler doesn't like resource.h constants.
87 if (static_cast<int>(limit.rlim_cur) == -1) return 0;
88 #else
89 if (limit.rlim_cur == RLIM_INFINITY) return 0;
90 #endif
91 return limit.rlim_cur;
92 }
93
94
95 uint64_t OS::TotalPhysicalMemory() {
96 #if V8_OS_MACOSX
97 int mib[2];
98 mib[0] = CTL_HW;
99 mib[1] = HW_MEMSIZE;
100 int64_t size = 0;
101 size_t len = sizeof(size);
102 if (sysctl(mib, 2, &size, &len, NULL, 0) != 0) {
103 UNREACHABLE();
104 return 0;
105 }
106 return static_cast<uint64_t>(size);
107 #elif V8_OS_FREEBSD
108 int pages, page_size;
109 size_t size = sizeof(pages);
110 sysctlbyname("vm.stats.vm.v_page_count", &pages, &size, NULL, 0);
111 sysctlbyname("vm.stats.vm.v_page_size", &page_size, &size, NULL, 0);
112 if (pages == -1 || page_size == -1) {
113 UNREACHABLE();
114 return 0;
115 }
116 return static_cast<uint64_t>(pages) * page_size;
117 #elif V8_OS_CYGWIN
118 MEMORYSTATUS memory_info;
119 memory_info.dwLength = sizeof(memory_info);
120 if (!GlobalMemoryStatus(&memory_info)) {
121 UNREACHABLE();
122 return 0;
123 }
124 return static_cast<uint64_t>(memory_info.dwTotalPhys);
125 #elif V8_OS_QNX
126 struct stat stat_buf;
127 if (stat("/proc", &stat_buf) != 0) {
128 UNREACHABLE();
129 return 0;
130 }
131 return static_cast<uint64_t>(stat_buf.st_size);
132 #else
133 intptr_t pages = sysconf(_SC_PHYS_PAGES);
134 intptr_t page_size = sysconf(_SC_PAGESIZE);
135 if (pages == -1 || page_size == -1) {
136 UNREACHABLE();
137 return 0;
138 }
139 return static_cast<uint64_t>(pages) * page_size;
140 #endif
141 }
142
143
144 int OS::ActivationFrameAlignment() {
145 #if V8_TARGET_ARCH_ARM
146 // On EABI ARM targets this is required for fp correctness in the
147 // runtime system.
148 return 8;
149 #elif V8_TARGET_ARCH_MIPS
150 return 8;
151 #else
152 // Otherwise we just assume 16 byte alignment, i.e.:
153 // - With gcc 4.4 the tree vectorization optimizer can generate code
154 // that requires 16 byte alignment such as movdqa on x86.
155 // - Mac OS X and Solaris (64-bit) activation frames must be 16 byte-aligned;
156 // see "Mac OS X ABI Function Call Guide"
157 return 16;
158 #endif
159 }
160
161
162 intptr_t OS::CommitPageSize() {
163 static intptr_t page_size = getpagesize();
164 return page_size;
165 }
166
167
168 void OS::Free(void* address, const size_t size) {
169 // TODO(1240712): munmap has a return value which is ignored here.
170 int result = munmap(address, size);
171 USE(result);
172 ASSERT(result == 0);
173 }
174
175
176 // Get rid of writable permission on code allocations.
177 void OS::ProtectCode(void* address, const size_t size) {
178 #if V8_OS_CYGWIN
179 DWORD old_protect;
180 VirtualProtect(address, size, PAGE_EXECUTE_READ, &old_protect);
181 #elif V8_OS_NACL
182 // The Native Client port of V8 uses an interpreter, so
183 // code pages don't need PROT_EXEC.
184 mprotect(address, size, PROT_READ);
185 #else
186 mprotect(address, size, PROT_READ | PROT_EXEC);
187 #endif
188 }
189
190
191 // Create guard pages.
192 void OS::Guard(void* address, const size_t size) {
193 #if V8_OS_CYGWIN
194 DWORD oldprotect;
195 VirtualProtect(address, size, PAGE_NOACCESS, &oldprotect);
196 #else
197 mprotect(address, size, PROT_NONE);
198 #endif
199 }
200
201
202 static base::LazyInstance<RandomNumberGenerator>::type
203 platform_random_number_generator = LAZY_INSTANCE_INITIALIZER;
204
205
206 void OS::Initialize(int64_t random_seed, bool hard_abort,
207 const char* const gc_fake_mmap) {
208 if (random_seed) {
209 platform_random_number_generator.Pointer()->SetSeed(random_seed);
210 }
211 g_hard_abort = hard_abort;
212 g_gc_fake_mmap = gc_fake_mmap;
213 }
214
215
216 const char* OS::GetGCFakeMMapFile() {
217 return g_gc_fake_mmap;
218 }
219
220
221 void* OS::GetRandomMmapAddr() {
222 #if V8_OS_NACL
223 // TODO(bradchen): restore randomization once Native Client gets
224 // smarter about using mmap address hints.
225 // See http://code.google.com/p/nativeclient/issues/3341
226 return NULL;
227 #endif
228 #if defined(ADDRESS_SANITIZER) || defined(MEMORY_SANITIZER) || \
229 defined(THREAD_SANITIZER)
230 // Dynamic tools do not support custom mmap addresses.
231 return NULL;
232 #endif
233 uintptr_t raw_addr;
234 platform_random_number_generator.Pointer()->NextBytes(&raw_addr,
235 sizeof(raw_addr));
236 #if V8_TARGET_ARCH_X64
237 // Currently available CPUs have 48 bits of virtual addressing. Truncate
238 // the hint address to 46 bits to give the kernel a fighting chance of
239 // fulfilling our placement request.
240 raw_addr &= V8_UINT64_C(0x3ffffffff000);
241 #else
242 raw_addr &= 0x3ffff000;
243
244 # ifdef __sun
245 // For our Solaris/illumos mmap hint, we pick a random address in the bottom
246 // half of the top half of the address space (that is, the third quarter).
247 // Because we do not MAP_FIXED, this will be treated only as a hint -- the
248 // system will not fail to mmap() because something else happens to already
249 // be mapped at our random address. We deliberately set the hint high enough
250 // to get well above the system's break (that is, the heap); Solaris and
251 // illumos will try the hint and if that fails allocate as if there were
252 // no hint at all. The high hint prevents the break from getting hemmed in
253 // at low values, ceding half of the address space to the system heap.
254 raw_addr += 0x80000000;
255 # else
256 // The range 0x20000000 - 0x60000000 is relatively unpopulated across a
257 // variety of ASLR modes (PAE kernel, NX compat mode, etc) and on macos
258 // 10.6 and 10.7.
259 raw_addr += 0x20000000;
260 # endif
261 #endif
262 return reinterpret_cast<void*>(raw_addr);
263 }
264
265
266 size_t OS::AllocateAlignment() {
267 return static_cast<size_t>(sysconf(_SC_PAGESIZE));
268 }
269
270
271 void OS::Sleep(int milliseconds) {
272 useconds_t ms = static_cast<useconds_t>(milliseconds);
273 usleep(1000 * ms);
274 }
275
276
277 void OS::Abort() {
278 if (g_hard_abort) {
279 V8_IMMEDIATE_CRASH();
280 }
281 // Redirect to std abort to signal abnormal program termination.
282 abort();
283 }
284
285
286 void OS::DebugBreak() {
287 #if V8_HOST_ARCH_ARM
288 asm("bkpt 0");
289 #elif V8_HOST_ARCH_ARM64
290 asm("brk 0");
291 #elif V8_HOST_ARCH_MIPS
292 asm("break");
293 #elif V8_HOST_ARCH_IA32
294 #if defined(__native_client__)
295 asm("hlt");
296 #else
297 asm("int $3");
298 #endif // __native_client__
299 #elif V8_HOST_ARCH_X64
300 asm("int $3");
301 #else
302 #error Unsupported host architecture.
303 #endif
304 }
305
306
307 // ----------------------------------------------------------------------------
308 // Math functions
309
310 double OS::nan_value() {
311 // NAN from math.h is defined in C99 and not in POSIX.
312 return NAN;
313 }
314
315
316 int OS::GetCurrentProcessId() {
317 return static_cast<int>(getpid());
318 }
319
320
321 // ----------------------------------------------------------------------------
322 // POSIX date/time support.
323 //
324
325 int OS::GetUserTime(uint32_t* secs, uint32_t* usecs) {
326 struct rusage usage;
327
328 if (getrusage(RUSAGE_SELF, &usage) < 0) return -1;
329 *secs = usage.ru_utime.tv_sec;
330 *usecs = usage.ru_utime.tv_usec;
331 return 0;
332 }
333
334
335 double OS::TimeCurrentMillis() {
336 return Time::Now().ToJsTime();
337 }
338
339
340 class TimezoneCache {};
341
342
343 TimezoneCache* OS::CreateTimezoneCache() {
344 return NULL;
345 }
346
347
348 void OS::DisposeTimezoneCache(TimezoneCache* cache) {
349 ASSERT(cache == NULL);
350 }
351
352
353 void OS::ClearTimezoneCache(TimezoneCache* cache) {
354 ASSERT(cache == NULL);
355 }
356
357
358 double OS::DaylightSavingsOffset(double time, TimezoneCache*) {
359 if (std::isnan(time)) return nan_value();
360 time_t tv = static_cast<time_t>(std::floor(time/msPerSecond));
361 struct tm* t = localtime(&tv);
362 if (NULL == t) return nan_value();
363 return t->tm_isdst > 0 ? 3600 * msPerSecond : 0;
364 }
365
366
367 int OS::GetLastError() {
368 return errno;
369 }
370
371
372 // ----------------------------------------------------------------------------
373 // POSIX stdio support.
374 //
375
376 FILE* OS::FOpen(const char* path, const char* mode) {
377 FILE* file = fopen(path, mode);
378 if (file == NULL) return NULL;
379 struct stat file_stat;
380 if (fstat(fileno(file), &file_stat) != 0) return NULL;
381 bool is_regular_file = ((file_stat.st_mode & S_IFREG) != 0);
382 if (is_regular_file) return file;
383 fclose(file);
384 return NULL;
385 }
386
387
388 bool OS::Remove(const char* path) {
389 return (remove(path) == 0);
390 }
391
392
393 FILE* OS::OpenTemporaryFile() {
394 return tmpfile();
395 }
396
397
398 const char* const OS::LogFileOpenMode = "w";
399
400
401 void OS::Print(const char* format, ...) {
402 va_list args;
403 va_start(args, format);
404 VPrint(format, args);
405 va_end(args);
406 }
407
408
409 void OS::VPrint(const char* format, va_list args) {
410 #if defined(ANDROID) && !defined(V8_ANDROID_LOG_STDOUT)
411 __android_log_vprint(ANDROID_LOG_INFO, LOG_TAG, format, args);
412 #else
413 vprintf(format, args);
414 #endif
415 }
416
417
418 void OS::FPrint(FILE* out, const char* format, ...) {
419 va_list args;
420 va_start(args, format);
421 VFPrint(out, format, args);
422 va_end(args);
423 }
424
425
426 void OS::VFPrint(FILE* out, const char* format, va_list args) {
427 #if defined(ANDROID) && !defined(V8_ANDROID_LOG_STDOUT)
428 __android_log_vprint(ANDROID_LOG_INFO, LOG_TAG, format, args);
429 #else
430 vfprintf(out, format, args);
431 #endif
432 }
433
434
435 void OS::PrintError(const char* format, ...) {
436 va_list args;
437 va_start(args, format);
438 VPrintError(format, args);
439 va_end(args);
440 }
441
442
443 void OS::VPrintError(const char* format, va_list args) {
444 #if defined(ANDROID) && !defined(V8_ANDROID_LOG_STDOUT)
445 __android_log_vprint(ANDROID_LOG_ERROR, LOG_TAG, format, args);
446 #else
447 vfprintf(stderr, format, args);
448 #endif
449 }
450
451
452 int OS::SNPrintF(char* str, int length, const char* format, ...) {
453 va_list args;
454 va_start(args, format);
455 int result = VSNPrintF(str, length, format, args);
456 va_end(args);
457 return result;
458 }
459
460
461 int OS::VSNPrintF(char* str,
462 int length,
463 const char* format,
464 va_list args) {
465 int n = vsnprintf(str, length, format, args);
466 if (n < 0 || n >= length) {
467 // If the length is zero, the assignment fails.
468 if (length > 0)
469 str[length - 1] = '\0';
470 return -1;
471 } else {
472 return n;
473 }
474 }
475
476
477 // ----------------------------------------------------------------------------
478 // POSIX string support.
479 //
480
481 char* OS::StrChr(char* str, int c) {
482 return strchr(str, c);
483 }
484
485
486 void OS::StrNCpy(char* dest, int length, const char* src, size_t n) {
487 strncpy(dest, src, n);
488 }
489
490
491 // ----------------------------------------------------------------------------
492 // POSIX thread support.
493 //
494
495 class Thread::PlatformData {
496 public:
497 PlatformData() : thread_(kNoThread) {}
498 pthread_t thread_; // Thread handle for pthread.
499 // Synchronizes thread creation
500 Mutex thread_creation_mutex_;
501 };
502
503 Thread::Thread(const Options& options)
504 : data_(new PlatformData),
505 stack_size_(options.stack_size()),
506 start_semaphore_(NULL) {
507 if (stack_size_ > 0 && stack_size_ < PTHREAD_STACK_MIN) {
508 stack_size_ = PTHREAD_STACK_MIN;
509 }
510 set_name(options.name());
511 }
512
513
514 Thread::~Thread() {
515 delete data_;
516 }
517
518
519 static void SetThreadName(const char* name) {
520 #if V8_OS_DRAGONFLYBSD || V8_OS_FREEBSD || V8_OS_OPENBSD
521 pthread_set_name_np(pthread_self(), name);
522 #elif V8_OS_NETBSD
523 STATIC_ASSERT(Thread::kMaxThreadNameLength <= PTHREAD_MAX_NAMELEN_NP);
524 pthread_setname_np(pthread_self(), "%s", name);
525 #elif V8_OS_MACOSX
526 // pthread_setname_np is only available in 10.6 or later, so test
527 // for it at runtime.
528 int (*dynamic_pthread_setname_np)(const char*);
529 *reinterpret_cast<void**>(&dynamic_pthread_setname_np) =
530 dlsym(RTLD_DEFAULT, "pthread_setname_np");
531 if (dynamic_pthread_setname_np == NULL)
532 return;
533
534 // Mac OS X does not expose the length limit of the name, so hardcode it.
535 static const int kMaxNameLength = 63;
536 STATIC_ASSERT(Thread::kMaxThreadNameLength <= kMaxNameLength);
537 dynamic_pthread_setname_np(name);
538 #elif defined(PR_SET_NAME)
539 prctl(PR_SET_NAME,
540 reinterpret_cast<unsigned long>(name), // NOLINT
541 0, 0, 0);
542 #endif
543 }
544
545
546 static void* ThreadEntry(void* arg) {
547 Thread* thread = reinterpret_cast<Thread*>(arg);
548 // We take the lock here to make sure that pthread_create finished first since
549 // we don't know which thread will run first (the original thread or the new
550 // one).
551 { LockGuard<Mutex> lock_guard(&thread->data()->thread_creation_mutex_); }
552 SetThreadName(thread->name());
553 ASSERT(thread->data()->thread_ != kNoThread);
554 thread->NotifyStartedAndRun();
555 return NULL;
556 }
557
558
559 void Thread::set_name(const char* name) {
560 strncpy(name_, name, sizeof(name_));
561 name_[sizeof(name_) - 1] = '\0';
562 }
563
564
565 void Thread::Start() {
566 int result;
567 pthread_attr_t attr;
568 memset(&attr, 0, sizeof(attr));
569 result = pthread_attr_init(&attr);
570 ASSERT_EQ(0, result);
571 // Native client uses default stack size.
572 #if !V8_OS_NACL
573 if (stack_size_ > 0) {
574 result = pthread_attr_setstacksize(&attr, static_cast<size_t>(stack_size_));
575 ASSERT_EQ(0, result);
576 }
577 #endif
578 {
579 LockGuard<Mutex> lock_guard(&data_->thread_creation_mutex_);
580 result = pthread_create(&data_->thread_, &attr, ThreadEntry, this);
581 }
582 ASSERT_EQ(0, result);
583 result = pthread_attr_destroy(&attr);
584 ASSERT_EQ(0, result);
585 ASSERT(data_->thread_ != kNoThread);
586 USE(result);
587 }
588
589
590 void Thread::Join() {
591 pthread_join(data_->thread_, NULL);
592 }
593
594
595 void Thread::YieldCPU() {
596 int result = sched_yield();
597 ASSERT_EQ(0, result);
598 USE(result);
599 }
600
601
602 static Thread::LocalStorageKey PthreadKeyToLocalKey(pthread_key_t pthread_key) {
603 #if V8_OS_CYGWIN
604 // We need to cast pthread_key_t to Thread::LocalStorageKey in two steps
605 // because pthread_key_t is a pointer type on Cygwin. This will probably not
606 // work on 64-bit platforms, but Cygwin doesn't support 64-bit anyway.
607 STATIC_ASSERT(sizeof(Thread::LocalStorageKey) == sizeof(pthread_key_t));
608 intptr_t ptr_key = reinterpret_cast<intptr_t>(pthread_key);
609 return static_cast<Thread::LocalStorageKey>(ptr_key);
610 #else
611 return static_cast<Thread::LocalStorageKey>(pthread_key);
612 #endif
613 }
614
615
616 static pthread_key_t LocalKeyToPthreadKey(Thread::LocalStorageKey local_key) {
617 #if V8_OS_CYGWIN
618 STATIC_ASSERT(sizeof(Thread::LocalStorageKey) == sizeof(pthread_key_t));
619 intptr_t ptr_key = static_cast<intptr_t>(local_key);
620 return reinterpret_cast<pthread_key_t>(ptr_key);
621 #else
622 return static_cast<pthread_key_t>(local_key);
623 #endif
624 }
625
626
627 #ifdef V8_FAST_TLS_SUPPORTED
628
629 static base::Atomic32 tls_base_offset_initialized = 0;
630 intptr_t kMacTlsBaseOffset = 0;
631
632 // It's safe to do the initialization more that once, but it has to be
633 // done at least once.
634 static void InitializeTlsBaseOffset() {
635 const size_t kBufferSize = 128;
636 char buffer[kBufferSize];
637 size_t buffer_size = kBufferSize;
638 int ctl_name[] = { CTL_KERN , KERN_OSRELEASE };
639 if (sysctl(ctl_name, 2, buffer, &buffer_size, NULL, 0) != 0) {
640 V8_Fatal(__FILE__, __LINE__, "V8 failed to get kernel version");
641 }
642 // The buffer now contains a string of the form XX.YY.ZZ, where
643 // XX is the major kernel version component.
644 // Make sure the buffer is 0-terminated.
645 buffer[kBufferSize - 1] = '\0';
646 char* period_pos = strchr(buffer, '.');
647 *period_pos = '\0';
648 int kernel_version_major =
649 static_cast<int>(strtol(buffer, NULL, 10)); // NOLINT
650 // The constants below are taken from pthreads.s from the XNU kernel
651 // sources archive at www.opensource.apple.com.
652 if (kernel_version_major < 11) {
653 // 8.x.x (Tiger), 9.x.x (Leopard), 10.x.x (Snow Leopard) have the
654 // same offsets.
655 #if V8_HOST_ARCH_IA32
656 kMacTlsBaseOffset = 0x48;
657 #else
658 kMacTlsBaseOffset = 0x60;
659 #endif
660 } else {
661 // 11.x.x (Lion) changed the offset.
662 kMacTlsBaseOffset = 0;
663 }
664
665 base::Release_Store(&tls_base_offset_initialized, 1);
666 }
667
668
669 static void CheckFastTls(Thread::LocalStorageKey key) {
670 void* expected = reinterpret_cast<void*>(0x1234CAFE);
671 Thread::SetThreadLocal(key, expected);
672 void* actual = Thread::GetExistingThreadLocal(key);
673 if (expected != actual) {
674 V8_Fatal(__FILE__, __LINE__,
675 "V8 failed to initialize fast TLS on current kernel");
676 }
677 Thread::SetThreadLocal(key, NULL);
678 }
679
680 #endif // V8_FAST_TLS_SUPPORTED
681
682
683 Thread::LocalStorageKey Thread::CreateThreadLocalKey() {
684 #ifdef V8_FAST_TLS_SUPPORTED
685 bool check_fast_tls = false;
686 if (tls_base_offset_initialized == 0) {
687 check_fast_tls = true;
688 InitializeTlsBaseOffset();
689 }
690 #endif
691 pthread_key_t key;
692 int result = pthread_key_create(&key, NULL);
693 ASSERT_EQ(0, result);
694 USE(result);
695 LocalStorageKey local_key = PthreadKeyToLocalKey(key);
696 #ifdef V8_FAST_TLS_SUPPORTED
697 // If we just initialized fast TLS support, make sure it works.
698 if (check_fast_tls) CheckFastTls(local_key);
699 #endif
700 return local_key;
701 }
702
703
704 void Thread::DeleteThreadLocalKey(LocalStorageKey key) {
705 pthread_key_t pthread_key = LocalKeyToPthreadKey(key);
706 int result = pthread_key_delete(pthread_key);
707 ASSERT_EQ(0, result);
708 USE(result);
709 }
710
711
712 void* Thread::GetThreadLocal(LocalStorageKey key) {
713 pthread_key_t pthread_key = LocalKeyToPthreadKey(key);
714 return pthread_getspecific(pthread_key);
715 }
716
717
718 void Thread::SetThreadLocal(LocalStorageKey key, void* value) {
719 pthread_key_t pthread_key = LocalKeyToPthreadKey(key);
720 int result = pthread_setspecific(pthread_key, value);
721 ASSERT_EQ(0, result);
722 USE(result);
723 }
724
725
726 } } // namespace v8::internal
OLDNEW
« src/base/macros.h ('K') | « src/platform-openbsd.cc ('k') | src/platform-qnx.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698