Index: src/platform-macos.cc |
diff --git a/src/platform-macos.cc b/src/platform-macos.cc |
index 17e3042882f183047f45078f7dca1929d061a007..bfdf3b21c0ff1ef38c3f663049626f9cfa6ef61b 100644 |
--- a/src/platform-macos.cc |
+++ b/src/platform-macos.cc |
@@ -48,8 +48,10 @@ |
#include <sys/time.h> |
#include <sys/resource.h> |
#include <sys/types.h> |
+#include <sys/sysctl.h> |
#include <stdarg.h> |
#include <stdlib.h> |
+#include <string.h> |
#include <errno.h> |
#undef MAP_TYPE |
@@ -507,12 +509,79 @@ void Thread::Join() { |
} |
+#ifdef V8_FAST_TLS_SUPPORTED |
+ |
+static Atomic32 tls_base_offset_initialized = 0; |
+intptr_t kMacTlsBaseOffset = 0; |
fschneider
2011/04/04 07:39:26
not sure: Can you guarantee that writes to kMacTls
Vitaly Repeshko
2011/04/04 21:15:43
Good question. Technically to prevent the offset f
|
+ |
+// 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 defined(V8_HOST_ARCH_IA32) |
+ kMacTlsBaseOffset = 0x48; |
+#else |
+ kMacTlsBaseOffset = 0x60; |
+#endif |
+ } else { |
+ // 11.x.x (Lion) changed the offset. |
Mark Mentovai
2011/04/01 16:37:16
Perhaps Avi would be satisfied if you had a test h
Avi (use Gerrit)
2011/04/01 16:41:52
Yes, that would make me happy.
Vitaly Repeshko
2011/04/01 16:47:55
Guys, do you want this in addition to CheckFastTls
|
+ kMacTlsBaseOffset = 0; |
+ } |
+ |
+ 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); |
USE(result); |
ASSERT(result == 0); |
- return static_cast<LocalStorageKey>(key); |
+ LocalStorageKey typed_key = static_cast<LocalStorageKey>(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; |
} |