#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 <sched.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 {
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()
{
void initializeThreading()
{
- if (!atomicallyInitializedStaticMutex) {
- atomicallyInitializedStaticMutex = new Mutex;
- threadMapMutex();
- initializeRandomNumberGenerator();
- mainThreadIdentifier = currentThread();
- initializeMainThread();
- }
+ if (atomicallyInitializedStaticMutex)
+ return;
+
+ atomicallyInitializedStaticMutex = new Mutex;
+ threadMapMutex();
+ initializeRandomNumberGenerator();
}
void lockAtomicallyInitializedStaticMutex()
return 0;
}
-static ThreadIdentifier establishIdentifierForPthreadHandle(pthread_t& pthreadHandle)
+static ThreadIdentifier establishIdentifierForPthreadHandle(const pthread_t& pthreadHandle)
{
ASSERT(!identifierByPthreadHandle(pthreadHandle));
return threadMap().get(id);
}
-static void clearPthreadHandleForIdentifier(ThreadIdentifier id)
+void clearPthreadHandleForIdentifier(ThreadIdentifier id)
{
MutexLocker locker(threadMapMutex());
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)
{
- 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) {
- ret = data->entryPoint(data->arg);
+ ret = invocation->function(invocation->data);
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))) {
+ // 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;
}
+
+ // The thread will take ownership of invocation.
+ invocation.leakPtr();
+
return establishIdentifierForPthreadHandle(threadHandle);
}
#else
}
#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 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;
}
ASSERT(threadID);
pthread_t pthreadHandle = pthreadHandleForIdentifier(threadID);
+ if (!pthreadHandle)
+ return;
pthread_detach(pthreadHandle);
+}
- clearPthreadHandleForIdentifier(threadID);
+void yield()
+{
+ sched_yield();
}
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()
{
- 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()
ASSERT_UNUSED(result, !result);
}
-
+#if HAVE(PTHREAD_RWLOCK)
ReadWriteLock::ReadWriteLock()
{
pthread_rwlock_init(&m_readWriteLock, NULL);
int result = pthread_rwlock_unlock(&m_readWriteLock);
ASSERT_UNUSED(result, !result);
}
+#endif // HAVE(PTHREAD_RWLOCK)
ThreadCondition::ThreadCondition()
{