]> git.saurik.com Git - apple/javascriptcore.git/blobdiff - wtf/ThreadingWin.cpp
JavaScriptCore-903.tar.gz
[apple/javascriptcore.git] / wtf / ThreadingWin.cpp
index 399fb385beed7e986746d1ec3ce1f4f66a003ca8..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 setThreadName all come from <http://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx>.
+// MS_VC_EXCEPTION, THREADNAME_INFO, and setThreadNameInternal all come from <http://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx>.
 static const DWORD MS_VC_EXCEPTION = 0x406D1388;
 
 #pragma pack(push, 8)
@@ -110,16 +122,12 @@ typedef struct tagTHREADNAME_INFO {
 } THREADNAME_INFO;
 #pragma pack(pop)
 
-static void setThreadName(DWORD dwThreadID, LPCSTR szThreadName)
+void initializeCurrentThreadInternal(const char* szThreadName)
 {
-    // Visual Studio has a 31-character limit on thread names. Longer names will
-    // be truncated silently, but we'd like callers to know about the limit.
-    ASSERT_ARG(szThreadName, strlen(szThreadName) <= 31);
-
     THREADNAME_INFO info;
     info.dwType = 0x1000;
     info.szName = szThreadName;
-    info.dwThreadID = dwThreadID;
+    info.dwThreadID = GetCurrentThreadId();
     info.dwFlags = 0;
 
     __try {
@@ -141,8 +149,6 @@ void unlockAtomicallyInitializedStaticMutex()
     atomicallyInitializedStaticMutex->unlock();
 }
 
-static ThreadIdentifier mainThreadIdentifier;
-
 static Mutex& threadMapMutex()
 {
     static Mutex mutex;
@@ -151,14 +157,12 @@ static Mutex& threadMapMutex()
 
 void initializeThreading()
 {
-    if (!atomicallyInitializedStaticMutex) {
-        atomicallyInitializedStaticMutex = new Mutex;
-        threadMapMutex();
-        initializeRandomNumberGenerator();
-        initializeMainThread();
-        mainThreadIdentifier = currentThread();
-        setThreadName(mainThreadIdentifier, "Main Thread");
-    }
+    if (atomicallyInitializedStaticMutex)
+        return;
+
+    atomicallyInitializedStaticMutex = new Mutex;
+    threadMapMutex();
+    initializeRandomNumberGenerator();
 }
 
 static HashMap<DWORD, HANDLE>& threadMap()
@@ -187,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
@@ -213,15 +208,27 @@ 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;
     }
 
-    if (threadName)
-        setThreadName(threadIdentifier, threadName);
+    // The thread will take ownership of invocation.
+    invocation.leakPtr();
 
     threadID = static_cast<ThreadIdentifier>(threadIdentifier);
     storeThreadHandleByIdentifier(threadIdentifier, threadHandle);
@@ -250,21 +257,21 @@ int waitForThreadCompletion(ThreadIdentifier threadID, void** result)
 void detachThread(ThreadIdentifier threadID)
 {
     ASSERT(threadID);
-    
+
     HANDLE threadHandle = threadHandleForIdentifier(threadID);
     if (threadHandle)
         CloseHandle(threadHandle);
     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()
@@ -325,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.
@@ -358,6 +366,7 @@ bool PlatformCondition::timedWait(PlatformMutex& mutex, DWORD durationMillisecon
     }
 
     EnterCriticalSection (&mutex.m_internalMutex);
+    ++mutex.m_recursionCount;
 
     return !timedOut;
 }
@@ -451,17 +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;
+    }
 
-    double intervalMilliseconds = (absoluteTime - currentTime) * 1000.0;
-    if (intervalMilliseconds >= INT_MAX)
-        intervalMilliseconds = INT_MAX;
-
-    return m_condition.timedWait(mutex.impl(), static_cast<unsigned long>(intervalMilliseconds));
+    return m_condition.timedWait(mutex.impl(), interval);
 }
 
 void ThreadCondition::signal()
@@ -474,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