1 /* ---------------------------------------------------------------------------
3 * (c) The GHC Team, 2001-2005
5 * Accessing OS threads functionality in a (mostly) OS-independent
8 * --------------------------------------------------------------------------*/
10 #ifndef __OSTHREADS_H__
11 #define __OSTHREADS_H__
13 #if defined(THREADED_RTS) /* to the end */
15 # if defined(HAVE_PTHREAD_H) && !defined(WANT_NATIVE_WIN32_THREADS)
19 typedef pthread_cond_t Condition;
20 typedef pthread_mutex_t Mutex;
21 typedef pthread_t OSThreadId;
22 typedef pthread_key_t ThreadLocalKey;
24 #define OSThreadProcAttr /* nothing */
26 #define INIT_COND_VAR PTHREAD_COND_INITIALIZER
30 #define ACQUIRE_LOCK(mutex) \
31 debugBelch("ACQUIRE_LOCK(0x%p) %s %d\n", mutex,__FILE__,__LINE__); \
32 pthread_mutex_lock(mutex)
33 #define RELEASE_LOCK(mutex) \
34 debugBelch("RELEASE_LOCK(0x%p) %s %d\n", mutex,__FILE__,__LINE__); \
35 pthread_mutex_unlock(mutex)
36 #define ASSERT_LOCK_HELD(mutex) /* nothing */
38 #elif defined(DEBUG) && defined(linux_HOST_OS)
41 * On Linux, we can use extensions to determine whether we already
42 * hold a lock or not, which is useful for debugging.
44 #define ACQUIRE_LOCK(mutex) \
45 if (pthread_mutex_lock(mutex) == EDEADLK) { \
46 barf("multiple ACQUIRE_LOCK: %s %d", __FILE__,__LINE__); \
48 #define RELEASE_LOCK(mutex) \
49 if (pthread_mutex_unlock(mutex) != 0) { \
50 barf("RELEASE_LOCK: I do not own this lock: %s %d", __FILE__,__LINE__); \
53 #define ASSERT_LOCK_HELD(mutex) ASSERT(pthread_mutex_lock(mutex) == EDEADLK)
55 #define ASSERT_LOCK_NOTHELD(mutex) \
56 if (pthread_mutex_lock(mutex) != EDEADLK) { \
57 pthread_mutex_unlock(mutex); \
65 #define ACQUIRE_LOCK(mutex) pthread_mutex_lock(mutex)
66 #define RELEASE_LOCK(mutex) pthread_mutex_unlock(mutex)
67 #define ASSERT_LOCK_HELD(mutex) /* nothing */
71 # elif defined(HAVE_WINDOWS_H)
74 typedef HANDLE Condition;
75 typedef DWORD OSThreadId;
76 typedef DWORD ThreadLocalKey;
78 #define OSThreadProcAttr __stdcall
80 #define INIT_COND_VAR 0
82 // We have a choice for implementing Mutexes on Windows. Standard
83 // Mutexes are kernel objects that require kernel calls to
84 // acquire/release, whereas CriticalSections are spin-locks that block
85 // in the kernel after spinning for a configurable number of times.
86 // CriticalSections are *much* faster, so we use those. The Mutex
87 // implementation is left here for posterity.
88 #define USE_CRITICAL_SECTIONS 1
90 #if USE_CRITICAL_SECTIONS
92 typedef CRITICAL_SECTION Mutex;
93 #define ACQUIRE_LOCK(mutex) EnterCriticalSection(mutex)
94 #define RELEASE_LOCK(mutex) LeaveCriticalSection(mutex)
96 // I don't know how to do this. TryEnterCriticalSection() doesn't do
98 #define ASSERT_LOCK_HELD(mutex) /* nothing */
102 typedef HANDLE Mutex;
104 // casting to (Mutex *) here required due to use in .cmm files where
105 // the argument has (void *) type.
106 #define ACQUIRE_LOCK(mutex) \
107 if (WaitForSingleObject(*((Mutex *)mutex),INFINITE) == WAIT_FAILED) { \
108 barf("WaitForSingleObject: %d", GetLastError()); \
111 #define RELEASE_LOCK(mutex) \
112 if (ReleaseMutex(*((Mutex *)mutex)) == 0) { \
113 barf("ReleaseMutex: %d", GetLastError()); \
116 #define ASSERT_LOCK_HELD(mutex) /* nothing */
120 # error "Threads not supported"
124 // General thread operations
126 extern OSThreadId osThreadId ( void );
127 extern void shutdownThread ( void );
128 extern void yieldThread ( void );
130 typedef void OSThreadProcAttr OSThreadProc(void *);
132 extern int createOSThread ( OSThreadId* tid,
133 OSThreadProc *startProc, void *param);
136 // Condition Variables
138 extern void initCondition ( Condition* pCond );
139 extern void closeCondition ( Condition* pCond );
140 extern rtsBool broadcastCondition ( Condition* pCond );
141 extern rtsBool signalCondition ( Condition* pCond );
142 extern rtsBool waitCondition ( Condition* pCond,
148 extern void initMutex ( Mutex* pMut );
151 // Thread-local storage
153 void newThreadLocalKey (ThreadLocalKey *key);
154 void *getThreadLocalVar (ThreadLocalKey *key);
155 void setThreadLocalVar (ThreadLocalKey *key, void *value);
159 #define ACQUIRE_LOCK(l)
160 #define RELEASE_LOCK(l)
161 #define ASSERT_LOCK_HELD(l)
163 #endif /* defined(THREADED_RTS) */
165 #endif /* __OSTHREADS_H__ */