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 #define ACQUIRE_LOCK(mutex) pthread_mutex_lock(mutex)
20 #define RELEASE_LOCK(mutex) pthread_mutex_unlock(mutex)
21 #define ASSERT_LOCK_HELD(mutex) /* nothing */
27 typedef pthread_cond_t Condition;
28 typedef pthread_mutex_t Mutex;
29 typedef pthread_t OSThreadId;
30 typedef pthread_key_t ThreadLocalKey;
32 #define OSThreadProcAttr /* nothing */
34 #define INIT_COND_VAR PTHREAD_COND_INITIALIZER
38 #define ACQUIRE_LOCK(mutex) \
39 debugBelch("ACQUIRE_LOCK(0x%p) %s %d\n", mutex,__FILE__,__LINE__); \
40 pthread_mutex_lock(mutex)
41 #define RELEASE_LOCK(mutex) \
42 debugBelch("RELEASE_LOCK(0x%p) %s %d\n", mutex,__FILE__,__LINE__); \
43 pthread_mutex_unlock(mutex)
44 #define ASSERT_LOCK_HELD(mutex) /* nothing */
46 #elif defined(DEBUG) && defined(linux_HOST_OS)
49 * On Linux, we can use extensions to determine whether we already
50 * hold a lock or not, which is useful for debugging.
52 #define ACQUIRE_LOCK(mutex) \
53 if (pthread_mutex_lock(mutex) == EDEADLK) { \
54 barf("multiple ACQUIRE_LOCK: %s %d", __FILE__,__LINE__); \
56 #define RELEASE_LOCK(mutex) \
57 if (pthread_mutex_unlock(mutex) != 0) { \
58 barf("RELEASE_LOCK: I do not own this lock: %s %d", __FILE__,__LINE__); \
61 #define ASSERT_LOCK_HELD(mutex) ASSERT(pthread_mutex_lock(mutex) == EDEADLK)
63 #define ASSERT_LOCK_NOTHELD(mutex) \
64 if (pthread_mutex_lock(mutex) != EDEADLK) { \
65 pthread_mutex_unlock(mutex); \
73 #define ACQUIRE_LOCK(mutex) pthread_mutex_lock(mutex)
74 #define RELEASE_LOCK(mutex) pthread_mutex_unlock(mutex)
75 #define ASSERT_LOCK_HELD(mutex) /* nothing */
81 # elif defined(HAVE_WINDOWS_H)
85 #define ACQUIRE_LOCK(mutex) EnterCriticalSection(mutex)
86 #define RELEASE_LOCK(mutex) LeaveCriticalSection(mutex)
87 #define ASSERT_LOCK_HELD(mutex) /* nothing */
93 typedef HANDLE Condition;
94 typedef DWORD OSThreadId;
95 // don't be tempted to use HANDLE as the OSThreadId: there can be
96 // many HANDLES to a given thread, so comparison would not work.
97 typedef DWORD ThreadLocalKey;
99 #define OSThreadProcAttr __stdcall
101 #define INIT_COND_VAR 0
103 // We have a choice for implementing Mutexes on Windows. Standard
104 // Mutexes are kernel objects that require kernel calls to
105 // acquire/release, whereas CriticalSections are spin-locks that block
106 // in the kernel after spinning for a configurable number of times.
107 // CriticalSections are *much* faster, so we use those. The Mutex
108 // implementation is left here for posterity.
109 #define USE_CRITICAL_SECTIONS 1
111 #if USE_CRITICAL_SECTIONS
113 typedef CRITICAL_SECTION Mutex;
117 #define ACQUIRE_LOCK(mutex) \
118 debugBelch("ACQUIRE_LOCK(0x%p) %s %d\n", mutex,__FILE__,__LINE__); \
119 EnterCriticalSection(mutex)
120 #define RELEASE_LOCK(mutex) \
121 debugBelch("RELEASE_LOCK(0x%p) %s %d\n", mutex,__FILE__,__LINE__); \
122 LeaveCriticalSection(mutex)
123 #define ASSERT_LOCK_HELD(mutex) /* nothing */
127 #define ACQUIRE_LOCK(mutex) EnterCriticalSection(mutex)
128 #define RELEASE_LOCK(mutex) LeaveCriticalSection(mutex)
130 // I don't know how to do this. TryEnterCriticalSection() doesn't do
132 #define ASSERT_LOCK_HELD(mutex) /* nothing */
138 typedef HANDLE Mutex;
140 // casting to (Mutex *) here required due to use in .cmm files where
141 // the argument has (void *) type.
142 #define ACQUIRE_LOCK(mutex) \
143 if (WaitForSingleObject(*((Mutex *)mutex),INFINITE) == WAIT_FAILED) { \
144 barf("WaitForSingleObject: %d", GetLastError()); \
147 #define RELEASE_LOCK(mutex) \
148 if (ReleaseMutex(*((Mutex *)mutex)) == 0) { \
149 barf("ReleaseMutex: %d", GetLastError()); \
152 #define ASSERT_LOCK_HELD(mutex) /* nothing */
155 #endif // CMINUSMINUS
158 # error "Threads not supported"
164 // General thread operations
166 extern OSThreadId osThreadId ( void );
167 extern void shutdownThread ( void );
168 extern void yieldThread ( void );
170 typedef void OSThreadProcAttr OSThreadProc(void *);
172 extern int createOSThread ( OSThreadId* tid,
173 OSThreadProc *startProc, void *param);
174 extern rtsBool osThreadIsAlive ( OSThreadId id );
177 // Condition Variables
179 extern void initCondition ( Condition* pCond );
180 extern void closeCondition ( Condition* pCond );
181 extern rtsBool broadcastCondition ( Condition* pCond );
182 extern rtsBool signalCondition ( Condition* pCond );
183 extern rtsBool waitCondition ( Condition* pCond,
189 extern void initMutex ( Mutex* pMut );
190 extern void closeMutex ( Mutex* pMut );
193 // Thread-local storage
195 void newThreadLocalKey (ThreadLocalKey *key);
196 void *getThreadLocalVar (ThreadLocalKey *key);
197 void setThreadLocalVar (ThreadLocalKey *key, void *value);
198 void freeThreadLocalKey (ThreadLocalKey *key);
200 #endif // !CMINUSMINUS
204 #define ACQUIRE_LOCK(l)
205 #define RELEASE_LOCK(l)
206 #define ASSERT_LOCK_HELD(l)
208 #endif /* defined(THREADED_RTS) */
210 #endif /* __OSTHREADS_H__ */