]> git.saurik.com Git - apple/javascriptcore.git/blobdiff - wtf/ThreadingPthreads.cpp
JavaScriptCore-721.26.tar.gz
[apple/javascriptcore.git] / wtf / ThreadingPthreads.cpp
index 3cc2f8a73ff2cf52f81016246718fad5c7b55742..f468ce2d72350e6f13483e48f6a7e73105c423e4 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2007, 2009 Apple Inc. All rights reserved.
  * Copyright (C) 2007 Justin Haygood (jhaygood@reaktix.com)
  *
  * Redistribution and use in source and binary forms, with or without
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
+
 #include "config.h"
 #include "Threading.h"
 
-#include "StdLibExtras.h"
-
 #if USE(PTHREADS)
 
 #include "CurrentTime.h"
 #include "HashMap.h"
 #include "MainThread.h"
 #include "RandomNumberSeed.h"
-
+#include "StdLibExtras.h"
+#include "ThreadIdentifierDataPthreads.h"
+#include "ThreadSpecific.h"
+#include "UnusedParam.h"
 #include <errno.h>
+
+#if !COMPILER(MSVC)
 #include <limits.h>
 #include <sys/time.h>
+#endif
+
+#if OS(ANDROID)
+#include "jni_utility.h"
+#endif
 
 namespace WTF {
 
@@ -48,7 +57,7 @@ typedef HashMap<ThreadIdentifier, pthread_t> ThreadMap;
 
 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()
 {
@@ -58,14 +67,12 @@ static Mutex& threadMapMutex()
 
 void initializeThreading()
 {
-    if (!atomicallyInitializedStaticMutex) {
-        atomicallyInitializedStaticMutex = new Mutex;
-        threadMapMutex();
-        initializeRandomNumberGenerator();
-        mainThreadIdentifier = currentThread();
-        initializeMainNSThread();
-        initializeMainThread();
-    }
+    if (atomicallyInitializedStaticMutex)
+        return;
+
+    atomicallyInitializedStaticMutex = new Mutex;
+    threadMapMutex();
+    initializeRandomNumberGenerator();
 }
 
 void lockAtomicallyInitializedStaticMutex()
@@ -98,7 +105,7 @@ static ThreadIdentifier identifierByPthreadHandle(const pthread_t& pthreadHandle
     return 0;
 }
 
-static ThreadIdentifier establishIdentifierForPthreadHandle(pthread_t& pthreadHandle)
+static ThreadIdentifier establishIdentifierForPthreadHandle(const pthread_t& pthreadHandle)
 {
     ASSERT(!identifierByPthreadHandle(pthreadHandle));
 
@@ -107,73 +114,123 @@ static ThreadIdentifier establishIdentifierForPthreadHandle(pthread_t& pthreadHa
     static ThreadIdentifier identifierCount = 1;
 
     threadMap().add(identifierCount, pthreadHandle);
-    
+
     return identifierCount++;
 }
 
 static pthread_t pthreadHandleForIdentifier(ThreadIdentifier id)
 {
     MutexLocker locker(threadMapMutex());
-    
+
     return threadMap().get(id);
 }
 
-static void clearPthreadHandleForIdentifier(ThreadIdentifier id)
+void clearPthreadHandleForIdentifier(ThreadIdentifier id)
 {
     MutexLocker locker(threadMapMutex());
 
     ASSERT(threadMap().contains(id));
-    
+
     threadMap().remove(id);
 }
 
+#if OS(ANDROID)
+// On the Android platform, threads must be registered with the VM before they run.
+struct ThreadData {
+    ThreadFunction entryPoint;
+    void* arg;
+};
+
+static void* runThreadWithRegistration(void* arg)
+{
+    ThreadData* data = static_cast<ThreadData*>(arg);
+    JavaVM* vm = JSC::Bindings::getJavaVM();
+    JNIEnv* env;
+    void* ret = 0;
+    if (vm->AttachCurrentThread(&env, 0) == JNI_OK) {
+        ret = data->entryPoint(data->arg);
+        vm->DetachCurrentThread();
+    }
+    delete data;
+    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))) {
+        LOG_ERROR("Failed to create pthread at entry point %p with data %p", entryPoint, data);
+        delete threadData;
+        return 0;
+    }
+    return establishIdentifierForPthreadHandle(threadHandle);
+}
+#else
 ThreadIdentifier createThreadInternal(ThreadFunction entryPoint, void* data, const char*)
 {
     pthread_t threadHandle;
-    if (pthread_create(&threadHandle, NULL, entryPoint, data)) {
+    if (pthread_create(&threadHandle, 0, entryPoint, data)) {
         LOG_ERROR("Failed to create pthread at entry point %p with data %p", entryPoint, data);
         return 0;
     }
 
     return establishIdentifierForPthreadHandle(threadHandle);
 }
+#endif
+
+void initializeCurrentThreadInternal(const char* threadName)
+{
+#if HAVE(PTHREAD_SETNAME_NP)
+    pthread_setname_np(threadName);
+#else
+    UNUSED_PARAM(threadName);
+#endif
+
+    ThreadIdentifier id = identifierByPthreadHandle(pthread_self());
+    ASSERT(id);
+    ThreadIdentifierData::initialize(id);
+}
 
 int waitForThreadCompletion(ThreadIdentifier threadID, void** result)
 {
     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);
-        
-    clearPthreadHandleForIdentifier(threadID);
+
     return joinResult;
 }
 
 void detachThread(ThreadIdentifier threadID)
 {
     ASSERT(threadID);
-    
+
     pthread_t pthreadHandle = pthreadHandleForIdentifier(threadID);
-    
+    if (!pthreadHandle)
+        return;
+
     pthread_detach(pthreadHandle);
-    
-    clearPthreadHandleForIdentifier(threadID);
 }
 
 ThreadIdentifier currentThread()
 {
-    pthread_t currentThread = pthread_self();
-    if (ThreadIdentifier id = identifierByPthreadHandle(currentThread))
+    ThreadIdentifier id = ThreadIdentifierData::identifier();
+    if (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()
@@ -188,29 +245,85 @@ Mutex::~Mutex()
 
 void Mutex::lock()
 {
-    if (pthread_mutex_lock(&m_mutex) != 0)
-        ASSERT(false);
+    int result = pthread_mutex_lock(&m_mutex);
+    ASSERT_UNUSED(result, !result);
 }
-    
+
 bool Mutex::tryLock()
 {
     int result = pthread_mutex_trylock(&m_mutex);
-    
+
     if (result == 0)
         return true;
-    else if (result == EBUSY)
+    if (result == EBUSY)
         return false;
 
-    ASSERT(false);
+    ASSERT_NOT_REACHED();
     return false;
 }
 
 void Mutex::unlock()
 {
-    if (pthread_mutex_unlock(&m_mutex) != 0)
-        ASSERT(false);
+    int result = pthread_mutex_unlock(&m_mutex);
+    ASSERT_UNUSED(result, !result);
 }
 
+#if HAVE(PTHREAD_RWLOCK)
+ReadWriteLock::ReadWriteLock()
+{
+    pthread_rwlock_init(&m_readWriteLock, NULL);
+}
+
+ReadWriteLock::~ReadWriteLock()
+{
+    pthread_rwlock_destroy(&m_readWriteLock);
+}
+
+void ReadWriteLock::readLock()
+{
+    int result = pthread_rwlock_rdlock(&m_readWriteLock);
+    ASSERT_UNUSED(result, !result);
+}
+
+bool ReadWriteLock::tryReadLock()
+{
+    int result = pthread_rwlock_tryrdlock(&m_readWriteLock);
+
+    if (result == 0)
+        return true;
+    if (result == EBUSY || result == EAGAIN)
+        return false;
+
+    ASSERT_NOT_REACHED();
+    return false;
+}
+
+void ReadWriteLock::writeLock()
+{
+    int result = pthread_rwlock_wrlock(&m_readWriteLock);
+    ASSERT_UNUSED(result, !result);
+}
+
+bool ReadWriteLock::tryWriteLock()
+{
+    int result = pthread_rwlock_trywrlock(&m_readWriteLock);
+
+    if (result == 0)
+        return true;
+    if (result == EBUSY || result == EAGAIN)
+        return false;
+
+    ASSERT_NOT_REACHED();
+    return false;
+}
+
+void ReadWriteLock::unlock()
+{
+    int result = pthread_rwlock_unlock(&m_readWriteLock);
+    ASSERT_UNUSED(result, !result);
+}
+#endif  // HAVE(PTHREAD_RWLOCK)
+
 ThreadCondition::ThreadCondition()
 { 
     pthread_cond_init(&m_condition, NULL);
@@ -223,8 +336,8 @@ ThreadCondition::~ThreadCondition()
     
 void ThreadCondition::wait(Mutex& mutex)
 {
-    if (pthread_cond_wait(&m_condition, &mutex.impl()) != 0)
-        ASSERT(false);
+    int result = pthread_cond_wait(&m_condition, &mutex.impl());
+    ASSERT_UNUSED(result, !result);
 }
 
 bool ThreadCondition::timedWait(Mutex& mutex, double absoluteTime)
@@ -249,16 +362,16 @@ bool ThreadCondition::timedWait(Mutex& mutex, double absoluteTime)
 
 void ThreadCondition::signal()
 {
-    if (pthread_cond_signal(&m_condition) != 0)
-        ASSERT(false);
+    int result = pthread_cond_signal(&m_condition);
+    ASSERT_UNUSED(result, !result);
 }
 
 void ThreadCondition::broadcast()
 {
-    if (pthread_cond_broadcast(&m_condition) != 0)
-        ASSERT(false);
+    int result = pthread_cond_broadcast(&m_condition);
+    ASSERT_UNUSED(result, !result);
 }
-    
+
 } // namespace WTF
 
 #endif // USE(PTHREADS)