]> git.saurik.com Git - apple/javascriptcore.git/blobdiff - wtf/ThreadingWin.cpp
JavaScriptCore-903.tar.gz
[apple/javascriptcore.git] / wtf / ThreadingWin.cpp
index ea186564b0009f5259805eadb3f6fff88ea96d0b..c452205c55cc213a6f91e9ab5c6cc6824d19cf26 100644 (file)
@@ -1,6 +1,7 @@
 /*
  * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
  * Copyright (C) 2009 Google Inc. All rights reserved.
+ * Copyright (C) 2009 Torch Mobile, Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
 #include "Threading.h"
 
 #include "MainThread.h"
-#if !USE(PTHREADS) && PLATFORM(WIN_OS)
-#include "ThreadSpecific.h"
-#endif
-#include <process.h>
+#include "ThreadFunctionInvocation.h"
 #include <windows.h>
 #include <wtf/CurrentTime.h>
 #include <wtf/HashMap.h>
 #include <wtf/MathExtras.h>
+#include <wtf/OwnPtr.h>
+#include <wtf/PassOwnPtr.h>
 #include <wtf/RandomNumberSeed.h>
 
+#if !USE(PTHREADS) && OS(WINDOWS)
+#include "ThreadSpecific.h"
+#endif
+
+#if !OS(WINCE)
+#include <process.h>
+#endif
+
+#if HAVE(ERRNO_H)
+#include <errno.h>
+#endif
+
 namespace WTF {
 
 // MS_VC_EXCEPTION, THREADNAME_INFO, and setThreadNameInternal all come from <http://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx>.
@@ -110,7 +122,7 @@ typedef struct tagTHREADNAME_INFO {
 } THREADNAME_INFO;
 #pragma pack(pop)
 
-void setThreadNameInternal(const char* szThreadName)
+void initializeCurrentThreadInternal(const char* szThreadName)
 {
     THREADNAME_INFO info;
     info.dwType = 0x1000;
@@ -137,8 +149,6 @@ void unlockAtomicallyInitializedStaticMutex()
     atomicallyInitializedStaticMutex->unlock();
 }
 
-static ThreadIdentifier mainThreadIdentifier;
-
 static Mutex& threadMapMutex()
 {
     static Mutex mutex;
@@ -147,14 +157,12 @@ static Mutex& threadMapMutex()
 
 void initializeThreading()
 {
-    if (!atomicallyInitializedStaticMutex) {
-        atomicallyInitializedStaticMutex = new Mutex;
-        threadMapMutex();
-        initializeRandomNumberGenerator();
-        initializeMainThread();
-        mainThreadIdentifier = currentThread();
-        setThreadNameInternal("Main Thread");
-    }
+    if (atomicallyInitializedStaticMutex)
+        return;
+
+    atomicallyInitializedStaticMutex = new Mutex;
+    threadMapMutex();
+    initializeRandomNumberGenerator();
 }
 
 static HashMap<DWORD, HANDLE>& threadMap()
@@ -183,21 +191,12 @@ static void clearThreadHandleForIdentifier(ThreadIdentifier id)
     threadMap().remove(id);
 }
 
-struct ThreadFunctionInvocation {
-    ThreadFunctionInvocation(ThreadFunction function, void* data) : function(function), data(data) {}
-
-    ThreadFunction function;
-    void* data;
-};
-
 static unsigned __stdcall wtfThreadEntryPoint(void* param)
 {
-    ThreadFunctionInvocation invocation = *static_cast<ThreadFunctionInvocation*>(param);
-    delete static_cast<ThreadFunctionInvocation*>(param);
-
-    void* result = invocation.function(invocation.data);
+    OwnPtr<ThreadFunctionInvocation> invocation = adoptPtr(static_cast<ThreadFunctionInvocation*>(param));
+    void* result = invocation->function(invocation->data);
 
-#if !USE(PTHREADS) && PLATFORM(WIN_OS)
+#if !USE(PTHREADS) && OS(WINDOWS)
     // Do the TLS cleanup.
     ThreadSpecificThreadExit();
 #endif
@@ -209,13 +208,28 @@ ThreadIdentifier createThreadInternal(ThreadFunction entryPoint, void* data, con
 {
     unsigned threadIdentifier = 0;
     ThreadIdentifier threadID = 0;
-    ThreadFunctionInvocation* invocation = new ThreadFunctionInvocation(entryPoint, data);
-    HANDLE threadHandle = reinterpret_cast<HANDLE>(_beginthreadex(0, 0, wtfThreadEntryPoint, invocation, 0, &threadIdentifier));
+    OwnPtr<ThreadFunctionInvocation> invocation = adoptPtr(new ThreadFunctionInvocation(entryPoint, data));
+#if OS(WINCE)
+    // This is safe on WINCE, since CRT is in the core and innately multithreaded.
+    // On desktop Windows, need to use _beginthreadex (not available on WinCE) if using any CRT functions
+    HANDLE threadHandle = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)wtfThreadEntryPoint, invocation.get(), 0, (LPDWORD)&threadIdentifier);
+#else
+    HANDLE threadHandle = reinterpret_cast<HANDLE>(_beginthreadex(0, 0, wtfThreadEntryPoint, invocation.get(), 0, &threadIdentifier));
+#endif
     if (!threadHandle) {
+#if OS(WINCE)
+        LOG_ERROR("Failed to create thread at entry point %p with data %p: %ld", entryPoint, data, ::GetLastError());
+#elif !HAVE(ERRNO_H)
+        LOG_ERROR("Failed to create thread at entry point %p with data %p.", entryPoint, data);
+#else
         LOG_ERROR("Failed to create thread at entry point %p with data %p: %ld", entryPoint, data, errno);
+#endif
         return 0;
     }
 
+    // The thread will take ownership of invocation.
+    invocation.leakPtr();
+
     threadID = static_cast<ThreadIdentifier>(threadIdentifier);
     storeThreadHandleByIdentifier(threadIdentifier, threadHandle);
 
@@ -250,14 +264,14 @@ void detachThread(ThreadIdentifier threadID)
     clearThreadHandleForIdentifier(threadID);
 }
 
-ThreadIdentifier currentThread()
+void yield()
 {
-    return static_cast<ThreadIdentifier>(GetCurrentThreadId());
+    ::Sleep(1);
 }
 
-bool isMainThread()
+ThreadIdentifier currentThread()
 {
-    return currentThread() == mainThreadIdentifier;
+    return static_cast<ThreadIdentifier>(GetCurrentThreadId());
 }
 
 Mutex::Mutex()
@@ -318,6 +332,7 @@ bool PlatformCondition::timedWait(PlatformMutex& mutex, DWORD durationMillisecon
     res = ReleaseSemaphore(m_blockLock, 1, 0);
     ASSERT(res);
 
+    --mutex.m_recursionCount;
     LeaveCriticalSection(&mutex.m_internalMutex);
 
     // Main wait - use timeout.
@@ -351,6 +366,7 @@ bool PlatformCondition::timedWait(PlatformMutex& mutex, DWORD durationMillisecon
     }
 
     EnterCriticalSection (&mutex.m_internalMutex);
+    ++mutex.m_recursionCount;
 
     return !timedOut;
 }
@@ -444,20 +460,15 @@ void ThreadCondition::wait(Mutex& mutex)
 
 bool ThreadCondition::timedWait(Mutex& mutex, double absoluteTime)
 {
-    double currentTime = WTF::currentTime();
+    DWORD interval = absoluteTimeToWaitTimeoutInterval(absoluteTime);
 
-    // Time is in the past - return immediately.
-    if (absoluteTime < currentTime)
+    if (!interval) {
+        // Consider the wait to have timed out, even if our condition has already been signaled, to
+        // match the pthreads implementation.
         return false;
-
-    // Time is too far in the future (and would overflow unsigned long) - wait forever.
-    if (absoluteTime - currentTime > static_cast<double>(INT_MAX) / 1000.0) {
-        wait(mutex);
-        return true;
     }
 
-    double intervalMilliseconds = (absoluteTime - currentTime) * 1000.0;
-    return m_condition.timedWait(mutex.impl(), static_cast<unsigned long>(intervalMilliseconds));
+    return m_condition.timedWait(mutex.impl(), interval);
 }
 
 void ThreadCondition::signal()
@@ -470,4 +481,19 @@ void ThreadCondition::broadcast()
     m_condition.signal(true); // Unblock all threads.
 }
 
+DWORD absoluteTimeToWaitTimeoutInterval(double absoluteTime)
+{
+    double currentTime = WTF::currentTime();
+
+    // Time is in the past - return immediately.
+    if (absoluteTime < currentTime)
+        return 0;
+
+    // Time is too far in the future (and would overflow unsigned long) - wait forever.
+    if (absoluteTime - currentTime > static_cast<double>(INT_MAX) / 1000.0)
+        return INFINITE;
+
+    return static_cast<DWORD>((absoluteTime - currentTime) * 1000.0);
+}
+
 } // namespace WTF