]> git.saurik.com Git - apple/javascriptcore.git/blobdiff - wtf/ThreadingPthreads.cpp
JavaScriptCore-903.tar.gz
[apple/javascriptcore.git] / wtf / ThreadingPthreads.cpp
index 0c6db2d1ec60c794b4f6a5264a55c9b612d30187..916aa3656dbac7f383f63e743ffeb6e2810ddec5 100644 (file)
 #include "MainThread.h"
 #include "RandomNumberSeed.h"
 #include "StdLibExtras.h"
 #include "MainThread.h"
 #include "RandomNumberSeed.h"
 #include "StdLibExtras.h"
+#include "ThreadIdentifierDataPthreads.h"
+#include "ThreadSpecific.h"
 #include "UnusedParam.h"
 #include <errno.h>
 #include "UnusedParam.h"
 #include <errno.h>
+
+#if !COMPILER(MSVC)
 #include <limits.h>
 #include <limits.h>
+#include <sched.h>
 #include <sys/time.h>
 #include <sys/time.h>
+#endif
+
+#if OS(ANDROID)
+#include "JNIUtility.h"
+#include "ThreadFunctionInvocation.h"
+#include <wtf/OwnPtr.h>
+#include <wtf/PassOwnPtr.h>
+#endif
 
 
-#if PLATFORM(ANDROID)
-#include "jni_utility.h"
+#if OS(MAC_OS_X) && !defined(BUILDING_ON_LEOPARD)
+#include <objc/objc-auto.h>
 #endif
 
 namespace WTF {
 #endif
 
 namespace WTF {
@@ -52,7 +65,7 @@ typedef HashMap<ThreadIdentifier, pthread_t> ThreadMap;
 
 static Mutex* atomicallyInitializedStaticMutex;
 
 
 static Mutex* atomicallyInitializedStaticMutex;
 
-static ThreadIdentifier mainThreadIdentifier; // The thread that was the first to call initializeThreading(), which must be the main thread.
+void clearPthreadHandleForIdentifier(ThreadIdentifier);
 
 static Mutex& threadMapMutex()
 {
 
 static Mutex& threadMapMutex()
 {
@@ -62,13 +75,12 @@ static Mutex& threadMapMutex()
 
 void initializeThreading()
 {
 
 void initializeThreading()
 {
-    if (!atomicallyInitializedStaticMutex) {
-        atomicallyInitializedStaticMutex = new Mutex;
-        threadMapMutex();
-        initializeRandomNumberGenerator();
-        mainThreadIdentifier = currentThread();
-        initializeMainThread();
-    }
+    if (atomicallyInitializedStaticMutex)
+        return;
+
+    atomicallyInitializedStaticMutex = new Mutex;
+    threadMapMutex();
+    initializeRandomNumberGenerator();
 }
 
 void lockAtomicallyInitializedStaticMutex()
 }
 
 void lockAtomicallyInitializedStaticMutex()
@@ -101,7 +113,7 @@ static ThreadIdentifier identifierByPthreadHandle(const pthread_t& pthreadHandle
     return 0;
 }
 
     return 0;
 }
 
-static ThreadIdentifier establishIdentifierForPthreadHandle(pthread_t& pthreadHandle)
+static ThreadIdentifier establishIdentifierForPthreadHandle(const pthread_t& pthreadHandle)
 {
     ASSERT(!identifierByPthreadHandle(pthreadHandle));
 
 {
     ASSERT(!identifierByPthreadHandle(pthreadHandle));
 
@@ -121,7 +133,7 @@ static pthread_t pthreadHandleForIdentifier(ThreadIdentifier id)
     return threadMap().get(id);
 }
 
     return threadMap().get(id);
 }
 
-static void clearPthreadHandleForIdentifier(ThreadIdentifier id)
+void clearPthreadHandleForIdentifier(ThreadIdentifier id)
 {
     MutexLocker locker(threadMapMutex());
 
 {
     MutexLocker locker(threadMapMutex());
 
@@ -130,38 +142,35 @@ static void clearPthreadHandleForIdentifier(ThreadIdentifier id)
     threadMap().remove(id);
 }
 
     threadMap().remove(id);
 }
 
-#if PLATFORM(ANDROID)
-// On the Android platform, threads must be registered with the VM before they run.
-struct ThreadData {
-    ThreadFunction entryPoint;
-    void* arg;
-};
-
+#if OS(ANDROID)
 static void* runThreadWithRegistration(void* arg)
 {
 static void* runThreadWithRegistration(void* arg)
 {
-    ThreadData* data = static_cast<ThreadData*>(arg);
+    OwnPtr<ThreadFunctionInvocation> invocation = adoptPtr(static_cast<ThreadFunctionInvocation*>(arg));
     JavaVM* vm = JSC::Bindings::getJavaVM();
     JNIEnv* env;
     void* ret = 0;
     if (vm->AttachCurrentThread(&env, 0) == JNI_OK) {
     JavaVM* vm = JSC::Bindings::getJavaVM();
     JNIEnv* env;
     void* ret = 0;
     if (vm->AttachCurrentThread(&env, 0) == JNI_OK) {
-        ret = data->entryPoint(data->arg);
+        ret = invocation->function(invocation->data);
         vm->DetachCurrentThread();
     }
         vm->DetachCurrentThread();
     }
-    delete data;
     return ret;
 }
 
 ThreadIdentifier createThreadInternal(ThreadFunction entryPoint, void* data, const char*)
 {
     pthread_t threadHandle;
     return ret;
 }
 
 ThreadIdentifier createThreadInternal(ThreadFunction entryPoint, void* data, const char*)
 {
     pthread_t threadHandle;
-    ThreadData* threadData = new ThreadData();
-    threadData->entryPoint = entryPoint;
-    threadData->arg = data;
 
 
-    if (pthread_create(&threadHandle, 0, runThreadWithRegistration, static_cast<void*>(threadData))) {
+    // On the Android platform, threads must be registered with the VM before they run.
+    OwnPtr<ThreadFunctionInvocation> invocation = adoptPtr(new ThreadFunctionInvocation(entryPoint, data));
+
+    if (pthread_create(&threadHandle, 0, runThreadWithRegistration, invocation.get())) {
         LOG_ERROR("Failed to create pthread at entry point %p with data %p", entryPoint, data);
         return 0;
     }
         LOG_ERROR("Failed to create pthread at entry point %p with data %p", entryPoint, data);
         return 0;
     }
+
+    // The thread will take ownership of invocation.
+    invocation.leakPtr();
+
     return establishIdentifierForPthreadHandle(threadHandle);
 }
 #else
     return establishIdentifierForPthreadHandle(threadHandle);
 }
 #else
@@ -177,13 +186,23 @@ ThreadIdentifier createThreadInternal(ThreadFunction entryPoint, void* data, con
 }
 #endif
 
 }
 #endif
 
-void setThreadNameInternal(const char* threadName)
+void initializeCurrentThreadInternal(const char* threadName)
 {
 #if HAVE(PTHREAD_SETNAME_NP)
     pthread_setname_np(threadName);
 #else
     UNUSED_PARAM(threadName);
 #endif
 {
 #if HAVE(PTHREAD_SETNAME_NP)
     pthread_setname_np(threadName);
 #else
     UNUSED_PARAM(threadName);
 #endif
+
+#if OS(MAC_OS_X) && !defined(BUILDING_ON_LEOPARD)
+    // All threads that potentially use APIs above the BSD layer must be registered with the Objective-C
+    // garbage collector in case API implementations use garbage-collected memory.
+    objc_registerThreadWithCollector();
+#endif
+
+    ThreadIdentifier id = identifierByPthreadHandle(pthread_self());
+    ASSERT(id);
+    ThreadIdentifierData::initialize(id);
 }
 
 int waitForThreadCompletion(ThreadIdentifier threadID, void** result)
 }
 
 int waitForThreadCompletion(ThreadIdentifier threadID, void** result)
@@ -191,12 +210,13 @@ int waitForThreadCompletion(ThreadIdentifier threadID, void** result)
     ASSERT(threadID);
 
     pthread_t pthreadHandle = pthreadHandleForIdentifier(threadID);
     ASSERT(threadID);
 
     pthread_t pthreadHandle = pthreadHandleForIdentifier(threadID);
+    if (!pthreadHandle)
+        return 0;
 
     int joinResult = pthread_join(pthreadHandle, result);
     if (joinResult == EDEADLK)
         LOG_ERROR("ThreadIdentifier %u was found to be deadlocked trying to quit", threadID);
 
 
     int joinResult = pthread_join(pthreadHandle, result);
     if (joinResult == EDEADLK)
         LOG_ERROR("ThreadIdentifier %u was found to be deadlocked trying to quit", threadID);
 
-    clearPthreadHandleForIdentifier(threadID);
     return joinResult;
 }
 
     return joinResult;
 }
 
@@ -205,28 +225,38 @@ void detachThread(ThreadIdentifier threadID)
     ASSERT(threadID);
 
     pthread_t pthreadHandle = pthreadHandleForIdentifier(threadID);
     ASSERT(threadID);
 
     pthread_t pthreadHandle = pthreadHandleForIdentifier(threadID);
+    if (!pthreadHandle)
+        return;
 
     pthread_detach(pthreadHandle);
 
     pthread_detach(pthreadHandle);
+}
 
 
-    clearPthreadHandleForIdentifier(threadID);
+void yield()
+{
+    sched_yield();
 }
 
 ThreadIdentifier currentThread()
 {
 }
 
 ThreadIdentifier currentThread()
 {
-    pthread_t currentThread = pthread_self();
-    if (ThreadIdentifier id = identifierByPthreadHandle(currentThread))
+    ThreadIdentifier id = ThreadIdentifierData::identifier();
+    if (id)
         return id;
         return id;
-    return establishIdentifierForPthreadHandle(currentThread);
-}
 
 
-bool isMainThread()
-{
-    return currentThread() == mainThreadIdentifier;
+    // Not a WTF-created thread, ThreadIdentifier is not established yet.
+    id = establishIdentifierForPthreadHandle(pthread_self());
+    ThreadIdentifierData::initialize(id);
+    return id;
 }
 
 Mutex::Mutex()
 {
 }
 
 Mutex::Mutex()
 {
-    pthread_mutex_init(&m_mutex, NULL);
+    pthread_mutexattr_t attr;
+    pthread_mutexattr_init(&attr);
+    pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL);
+
+    pthread_mutex_init(&m_mutex, &attr);
+
+    pthread_mutexattr_destroy(&attr);
 }
 
 Mutex::~Mutex()
 }
 
 Mutex::~Mutex()
@@ -259,7 +289,7 @@ void Mutex::unlock()
     ASSERT_UNUSED(result, !result);
 }
 
     ASSERT_UNUSED(result, !result);
 }
 
-
+#if HAVE(PTHREAD_RWLOCK)
 ReadWriteLock::ReadWriteLock()
 {
     pthread_rwlock_init(&m_readWriteLock, NULL);
 ReadWriteLock::ReadWriteLock()
 {
     pthread_rwlock_init(&m_readWriteLock, NULL);
@@ -313,6 +343,7 @@ void ReadWriteLock::unlock()
     int result = pthread_rwlock_unlock(&m_readWriteLock);
     ASSERT_UNUSED(result, !result);
 }
     int result = pthread_rwlock_unlock(&m_readWriteLock);
     ASSERT_UNUSED(result, !result);
 }
+#endif  // HAVE(PTHREAD_RWLOCK)
 
 ThreadCondition::ThreadCondition()
 { 
 
 ThreadCondition::ThreadCondition()
 {