X-Git-Url: https://git.saurik.com/apple/javascriptcore.git/blobdiff_plain/9dae56ea45a0f5f8136a5c93d6f3a7f99399ca73..14957cd040308e3eeec43d26bae5d76da13fcd85:/wtf/ThreadingPthreads.cpp?ds=inline diff --git a/wtf/ThreadingPthreads.cpp b/wtf/ThreadingPthreads.cpp index 3cc2f8a..916aa36 100644 --- a/wtf/ThreadingPthreads.cpp +++ b/wtf/ThreadingPthreads.cpp @@ -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 @@ -26,21 +26,38 @@ * (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 + +#if !COMPILER(MSVC) #include +#include #include +#endif + +#if OS(ANDROID) +#include "JNIUtility.h" +#include "ThreadFunctionInvocation.h" +#include +#include +#endif + +#if OS(MAC_OS_X) && !defined(BUILDING_ON_LEOPARD) +#include +#endif namespace WTF { @@ -48,7 +65,7 @@ typedef HashMap 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 +75,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 +113,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,78 +122,141 @@ 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) +static void* runThreadWithRegistration(void* arg) +{ + OwnPtr invocation = adoptPtr(static_cast(arg)); + JavaVM* vm = JSC::Bindings::getJavaVM(); + JNIEnv* env; + void* ret = 0; + if (vm->AttachCurrentThread(&env, 0) == JNI_OK) { + ret = invocation->function(invocation->data); + vm->DetachCurrentThread(); + } + return ret; +} + +ThreadIdentifier createThreadInternal(ThreadFunction entryPoint, void* data, const char*) +{ + pthread_t threadHandle; + + // On the Android platform, threads must be registered with the VM before they run. + OwnPtr 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; + } + + // The thread will take ownership of invocation. + invocation.leakPtr(); + + 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 + +#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) { 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() +void yield() { - pthread_t currentThread = pthread_self(); - if (ThreadIdentifier id = identifierByPthreadHandle(currentThread)) - return id; - return establishIdentifierForPthreadHandle(currentThread); + sched_yield(); } -bool isMainThread() +ThreadIdentifier currentThread() { - return currentThread() == mainThreadIdentifier; + ThreadIdentifier id = ThreadIdentifierData::identifier(); + if (id) + return id; + + // Not a WTF-created thread, ThreadIdentifier is not established yet. + id = establishIdentifierForPthreadHandle(pthread_self()); + ThreadIdentifierData::initialize(id); + return id; } 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() @@ -188,29 +266,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 +357,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 +383,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)