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) foreign "C" pthread_mutex_lock(mutex)
20 #define RELEASE_LOCK(mutex) foreign "C" pthread_mutex_unlock(mutex)
21 #define ASSERT_LOCK_HELD(mutex) /* nothing */
28 typedef pthread_cond_t Condition;
29 typedef pthread_mutex_t Mutex;
30 typedef pthread_t OSThreadId;
31 typedef pthread_key_t ThreadLocalKey;
33 #define OSThreadProcAttr /* nothing */
35 #define INIT_COND_VAR PTHREAD_COND_INITIALIZER
38 #define LOCK_DEBUG_BELCH(what, mutex) \
39 debugBelch("%s(0x%p) %s %d\n", what, mutex, __FILE__, __LINE__)
41 #define LOCK_DEBUG_BELCH(what, mutex) /* nothing */
44 /* Always check the result of lock and unlock. */
45 #define ACQUIRE_LOCK(mutex) \
46 LOCK_DEBUG_BELCH("ACQUIRE_LOCK", mutex); \
47 if (pthread_mutex_lock(mutex) == EDEADLK) { \
48 barf("multiple ACQUIRE_LOCK: %s %d", __FILE__,__LINE__); \
51 #define RELEASE_LOCK(mutex) \
52 LOCK_DEBUG_BELCH("RELEASE_LOCK", mutex); \
53 if (pthread_mutex_unlock(mutex) != 0) { \
54 barf("RELEASE_LOCK: I do not own this lock: %s %d", __FILE__,__LINE__); \
57 // Note: this assertion calls pthread_mutex_lock() on a mutex that
58 // is already held by the calling thread. The mutex should therefore
59 // have been created with PTHREAD_MUTEX_ERRORCHECK, otherwise this
60 // assertion will hang. We always initialise mutexes with
61 // PTHREAD_MUTEX_ERRORCHECK when DEBUG is on (see rts/posix/OSThreads.h).
62 #define ASSERT_LOCK_HELD(mutex) ASSERT(pthread_mutex_lock(mutex) == EDEADLK)
66 # elif defined(HAVE_WINDOWS_H)
70 /* We jump through a hoop here to get a CCall EnterCriticalSection
71 and LeaveCriticalSection, as that's what C-- wants. */
73 #define ACQUIRE_LOCK(mutex) foreign "stdcall" EnterCriticalSection(mutex)
74 #define RELEASE_LOCK(mutex) foreign "stdcall" LeaveCriticalSection(mutex)
75 #define ASSERT_LOCK_HELD(mutex) /* nothing */
81 typedef HANDLE Condition;
82 typedef DWORD OSThreadId;
83 // don't be tempted to use HANDLE as the OSThreadId: there can be
84 // many HANDLES to a given thread, so comparison would not work.
85 typedef DWORD ThreadLocalKey;
87 #define OSThreadProcAttr __stdcall
89 #define INIT_COND_VAR 0
91 // We have a choice for implementing Mutexes on Windows. Standard
92 // Mutexes are kernel objects that require kernel calls to
93 // acquire/release, whereas CriticalSections are spin-locks that block
94 // in the kernel after spinning for a configurable number of times.
95 // CriticalSections are *much* faster, so we use those. The Mutex
96 // implementation is left here for posterity.
97 #define USE_CRITICAL_SECTIONS 1
99 #if USE_CRITICAL_SECTIONS
101 typedef CRITICAL_SECTION Mutex;
105 #define ACQUIRE_LOCK(mutex) \
106 debugBelch("ACQUIRE_LOCK(0x%p) %s %d\n", mutex,__FILE__,__LINE__); \
107 EnterCriticalSection(mutex)
108 #define RELEASE_LOCK(mutex) \
109 debugBelch("RELEASE_LOCK(0x%p) %s %d\n", mutex,__FILE__,__LINE__); \
110 LeaveCriticalSection(mutex)
111 #define ASSERT_LOCK_HELD(mutex) /* nothing */
115 #define ACQUIRE_LOCK(mutex) EnterCriticalSection(mutex)
116 #define RELEASE_LOCK(mutex) LeaveCriticalSection(mutex)
118 // I don't know how to do this. TryEnterCriticalSection() doesn't do
120 #define ASSERT_LOCK_HELD(mutex) /* nothing */
126 typedef HANDLE Mutex;
128 // casting to (Mutex *) here required due to use in .cmm files where
129 // the argument has (void *) type.
130 #define ACQUIRE_LOCK(mutex) \
131 if (WaitForSingleObject(*((Mutex *)mutex),INFINITE) == WAIT_FAILED) { \
132 barf("WaitForSingleObject: %d", GetLastError()); \
135 #define RELEASE_LOCK(mutex) \
136 if (ReleaseMutex(*((Mutex *)mutex)) == 0) { \
137 barf("ReleaseMutex: %d", GetLastError()); \
140 #define ASSERT_LOCK_HELD(mutex) /* nothing */
143 #endif // CMINUSMINUS
146 # error "Threads not supported"
152 // General thread operations
154 extern OSThreadId osThreadId ( void );
155 extern void shutdownThread ( void );
156 extern void yieldThread ( void );
158 typedef void OSThreadProcAttr OSThreadProc(void *);
160 extern int createOSThread ( OSThreadId* tid,
161 OSThreadProc *startProc, void *param);
162 extern rtsBool osThreadIsAlive ( OSThreadId id );
165 // Condition Variables
167 extern void initCondition ( Condition* pCond );
168 extern void closeCondition ( Condition* pCond );
169 extern rtsBool broadcastCondition ( Condition* pCond );
170 extern rtsBool signalCondition ( Condition* pCond );
171 extern rtsBool waitCondition ( Condition* pCond,
177 extern void initMutex ( Mutex* pMut );
178 extern void closeMutex ( Mutex* pMut );
181 // Thread-local storage
183 void newThreadLocalKey (ThreadLocalKey *key);
184 void *getThreadLocalVar (ThreadLocalKey *key);
185 void setThreadLocalVar (ThreadLocalKey *key, void *value);
186 void freeThreadLocalKey (ThreadLocalKey *key);
188 #endif // !CMINUSMINUS
192 #define ACQUIRE_LOCK(l)
193 #define RELEASE_LOCK(l)
194 #define ASSERT_LOCK_HELD(l)
196 #endif /* defined(THREADED_RTS) */
198 #endif /* __OSTHREADS_H__ */