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 // don't be tempted to use HANDLE as the OSThreadId: there can be
77 // many HANDLES to a given thread, so comparison would not work.
78 typedef DWORD ThreadLocalKey;
80 #define OSThreadProcAttr __stdcall
82 #define INIT_COND_VAR 0
84 // We have a choice for implementing Mutexes on Windows. Standard
85 // Mutexes are kernel objects that require kernel calls to
86 // acquire/release, whereas CriticalSections are spin-locks that block
87 // in the kernel after spinning for a configurable number of times.
88 // CriticalSections are *much* faster, so we use those. The Mutex
89 // implementation is left here for posterity.
90 #define USE_CRITICAL_SECTIONS 1
92 #if USE_CRITICAL_SECTIONS
94 typedef CRITICAL_SECTION Mutex;
98 #define ACQUIRE_LOCK(mutex) \
99 debugBelch("ACQUIRE_LOCK(0x%p) %s %d\n", mutex,__FILE__,__LINE__); \
100 EnterCriticalSection(mutex)
101 #define RELEASE_LOCK(mutex) \
102 debugBelch("RELEASE_LOCK(0x%p) %s %d\n", mutex,__FILE__,__LINE__); \
103 LeaveCriticalSection(mutex)
104 #define ASSERT_LOCK_HELD(mutex) /* nothing */
108 #define ACQUIRE_LOCK(mutex) EnterCriticalSection(mutex)
109 #define RELEASE_LOCK(mutex) LeaveCriticalSection(mutex)
111 // I don't know how to do this. TryEnterCriticalSection() doesn't do
113 #define ASSERT_LOCK_HELD(mutex) /* nothing */
119 typedef HANDLE Mutex;
121 // casting to (Mutex *) here required due to use in .cmm files where
122 // the argument has (void *) type.
123 #define ACQUIRE_LOCK(mutex) \
124 if (WaitForSingleObject(*((Mutex *)mutex),INFINITE) == WAIT_FAILED) { \
125 barf("WaitForSingleObject: %d", GetLastError()); \
128 #define RELEASE_LOCK(mutex) \
129 if (ReleaseMutex(*((Mutex *)mutex)) == 0) { \
130 barf("ReleaseMutex: %d", GetLastError()); \
133 #define ASSERT_LOCK_HELD(mutex) /* nothing */
137 # error "Threads not supported"
141 // General thread operations
143 extern OSThreadId osThreadId ( void );
144 extern void shutdownThread ( void );
145 extern void yieldThread ( void );
147 typedef void OSThreadProcAttr OSThreadProc(void *);
149 extern int createOSThread ( OSThreadId* tid,
150 OSThreadProc *startProc, void *param);
151 extern rtsBool osThreadIsAlive ( OSThreadId id );
154 // Condition Variables
156 extern void initCondition ( Condition* pCond );
157 extern void closeCondition ( Condition* pCond );
158 extern rtsBool broadcastCondition ( Condition* pCond );
159 extern rtsBool signalCondition ( Condition* pCond );
160 extern rtsBool waitCondition ( Condition* pCond,
166 extern void initMutex ( Mutex* pMut );
167 extern void closeMutex ( Mutex* pMut );
170 // Thread-local storage
172 void newThreadLocalKey (ThreadLocalKey *key);
173 void *getThreadLocalVar (ThreadLocalKey *key);
174 void setThreadLocalVar (ThreadLocalKey *key, void *value);
175 void freeThreadLocalKey (ThreadLocalKey *key);
179 #define ACQUIRE_LOCK(l)
180 #define RELEASE_LOCK(l)
181 #define ASSERT_LOCK_HELD(l)
183 #endif /* defined(THREADED_RTS) */
185 #endif /* __OSTHREADS_H__ */