[project @ 2005-11-04 12:02:04 by simonmar]
authorsimonmar <unknown>
Fri, 4 Nov 2005 12:02:05 +0000 (12:02 +0000)
committersimonmar <unknown>
Fri, 4 Nov 2005 12:02:05 +0000 (12:02 +0000)
Win32: Use CriticalSections instead of Mutexes, they are *much* faster.

ghc/includes/OSThreads.h
ghc/rts/Schedule.c
ghc/rts/Storage.c
ghc/rts/win32/OSThreads.c

index c136aa5..40c260b 100644 (file)
@@ -1,6 +1,6 @@
 /* ---------------------------------------------------------------------------
  *
- * (c) The GHC Team, 2001
+ * (c) The GHC Team, 2001-2005
  *
  * Accessing OS threads functionality in a (mostly) OS-independent
  * manner. 
@@ -23,7 +23,6 @@ typedef pthread_key_t   ThreadLocalKey;
 
 #define OSThreadProcAttr /* nothing */
 
-#define INIT_MUTEX_VAR      PTHREAD_MUTEX_INITIALIZER
 #define INIT_COND_VAR       PTHREAD_COND_INITIALIZER
 
 #ifdef LOCK_DEBUG
@@ -73,15 +72,35 @@ typedef pthread_key_t   ThreadLocalKey;
 #include <windows.h>
 
 typedef HANDLE Condition;
-typedef HANDLE Mutex;
 typedef DWORD OSThreadId;
 typedef DWORD ThreadLocalKey;
 
 #define OSThreadProcAttr __stdcall
 
-#define INIT_MUTEX_VAR 0
 #define INIT_COND_VAR  0
 
+// We have a choice for implementing Mutexes on Windows.  Standard
+// Mutexes are kernel objects that require kernel calls to
+// acquire/release, whereas CriticalSections are spin-locks that block
+// in the kernel after spinning for a configurable number of times.
+// CriticalSections are *much* faster, so we use those.  The Mutex
+// implementation is left here for posterity.
+#define USE_CRITICAL_SECTIONS 1
+
+#if USE_CRITICAL_SECTIONS
+
+typedef CRITICAL_SECTION Mutex;
+#define ACQUIRE_LOCK(mutex)  EnterCriticalSection(mutex)
+#define RELEASE_LOCK(mutex)  LeaveCriticalSection(mutex)
+
+// I don't know how to do this.  TryEnterCriticalSection() doesn't do
+// the right thing.
+#define ASSERT_LOCK_HELD(mutex) /* nothing */
+
+#else
+
+typedef HANDLE Mutex;
+
 // casting to (Mutex *) here required due to use in .cmm files where
 // the argument has (void *) type.
 #define ACQUIRE_LOCK(mutex)                                    \
@@ -95,6 +114,7 @@ typedef DWORD ThreadLocalKey;
     }
 
 #define ASSERT_LOCK_HELD(mutex) /* nothing */
+#endif
 
 # else
 #  error "Threads not supported"
@@ -140,6 +160,6 @@ void  setThreadLocalVar (ThreadLocalKey *key, void *value);
 #define RELEASE_LOCK(l)
 #define ASSERT_LOCK_HELD(l)
 
-#endif /* defined(RTS_SUPPORTS_THREADS) */
+#endif /* defined(THREADED_RTS) */
 
 #endif /* __OSTHREADS_H__ */
index c2426fa..d3851eb 100644 (file)
@@ -192,7 +192,7 @@ rtsBool shutting_down_scheduler = rtsFalse;
  * the THREADED_RTS and (inc. SMP) runtime.
  */
 #if defined(THREADED_RTS)
-Mutex sched_mutex = INIT_MUTEX_VAR;
+Mutex sched_mutex;
 #endif
 
 #if defined(PARALLEL_HASKELL)
index 57e3d70..e44348f 100644 (file)
@@ -56,7 +56,7 @@ step *nurseries         = NULL; /* array of nurseries, >1 only if SMP */
  * simultaneous access by two STG threads.
  */
 #ifdef SMP
-Mutex sm_mutex = INIT_MUTEX_VAR;
+Mutex sm_mutex;
 #endif
 
 /*
index f48540e..c772be3 100644 (file)
@@ -110,6 +110,13 @@ osThreadId()
   return GetCurrentThreadId();
 }
 
+#ifdef USE_CRITICAL_SECTIONS
+void
+initMutex (Mutex* pMut)
+{
+    InitializeCriticalSectionAndSpinCount(pMut,4000);
+}
+#else
 void
 initMutex (Mutex* pMut)
 {
@@ -120,6 +127,7 @@ initMutex (Mutex* pMut)
   *pMut = h;
   return;
 }
+#endif
 
 void
 newThreadLocalKey (ThreadLocalKey *key)