1 /* ---------------------------------------------------------------------------
3 * (c) The GHC Team, 2001-2009
5 * Accessing OS threads functionality in a (mostly) OS-independent
8 * Do not #include this file directly: #include "Rts.h" instead.
10 * To understand the structure of the RTS headers, see the wiki:
11 * http://hackage.haskell.org/trac/ghc/wiki/Commentary/SourceTree/Includes
13 * --------------------------------------------------------------------------*/
15 #ifndef RTS_OSTHREADS_H
16 #define RTS_OSTHREADS_H
18 #if defined(THREADED_RTS) /* to the end */
20 # if defined(HAVE_PTHREAD_H) && !defined(WANT_NATIVE_WIN32_THREADS)
24 #define ACQUIRE_LOCK(mutex) foreign "C" pthread_mutex_lock(mutex)
25 #define RELEASE_LOCK(mutex) foreign "C" pthread_mutex_unlock(mutex)
26 #define ASSERT_LOCK_HELD(mutex) /* nothing */
33 typedef pthread_cond_t Condition;
34 typedef pthread_mutex_t Mutex;
35 typedef pthread_t OSThreadId;
36 typedef pthread_key_t ThreadLocalKey;
38 #define OSThreadProcAttr /* nothing */
40 #define INIT_COND_VAR PTHREAD_COND_INITIALIZER
43 #define LOCK_DEBUG_BELCH(what, mutex) \
44 debugBelch("%s(0x%p) %s %d\n", what, mutex, __FILE__, __LINE__)
46 #define LOCK_DEBUG_BELCH(what, mutex) /* nothing */
49 /* Always check the result of lock and unlock. */
50 #define ACQUIRE_LOCK(mutex) \
51 LOCK_DEBUG_BELCH("ACQUIRE_LOCK", mutex); \
52 if (pthread_mutex_lock(mutex) == EDEADLK) { \
53 barf("multiple ACQUIRE_LOCK: %s %d", __FILE__,__LINE__); \
56 #define RELEASE_LOCK(mutex) \
57 LOCK_DEBUG_BELCH("RELEASE_LOCK", mutex); \
58 if (pthread_mutex_unlock(mutex) != 0) { \
59 barf("RELEASE_LOCK: I do not own this lock: %s %d", __FILE__,__LINE__); \
62 // Note: this assertion calls pthread_mutex_lock() on a mutex that
63 // is already held by the calling thread. The mutex should therefore
64 // have been created with PTHREAD_MUTEX_ERRORCHECK, otherwise this
65 // assertion will hang. We always initialise mutexes with
66 // PTHREAD_MUTEX_ERRORCHECK when DEBUG is on (see rts/posix/OSThreads.h).
67 #define ASSERT_LOCK_HELD(mutex) ASSERT(pthread_mutex_lock(mutex) == EDEADLK)
71 # elif defined(HAVE_WINDOWS_H)
75 /* We jump through a hoop here to get a CCall EnterCriticalSection
76 and LeaveCriticalSection, as that's what C-- wants. */
78 #define ACQUIRE_LOCK(mutex) foreign "stdcall" EnterCriticalSection(mutex)
79 #define RELEASE_LOCK(mutex) foreign "stdcall" LeaveCriticalSection(mutex)
80 #define ASSERT_LOCK_HELD(mutex) /* nothing */
86 typedef HANDLE Condition;
87 typedef DWORD OSThreadId;
88 // don't be tempted to use HANDLE as the OSThreadId: there can be
89 // many HANDLES to a given thread, so comparison would not work.
90 typedef DWORD ThreadLocalKey;
92 #define OSThreadProcAttr __stdcall
94 #define INIT_COND_VAR 0
96 // We have a choice for implementing Mutexes on Windows. Standard
97 // Mutexes are kernel objects that require kernel calls to
98 // acquire/release, whereas CriticalSections are spin-locks that block
99 // in the kernel after spinning for a configurable number of times.
100 // CriticalSections are *much* faster, so we use those. The Mutex
101 // implementation is left here for posterity.
102 #define USE_CRITICAL_SECTIONS 1
104 #if USE_CRITICAL_SECTIONS
106 typedef CRITICAL_SECTION Mutex;
110 #define ACQUIRE_LOCK(mutex) \
111 debugBelch("ACQUIRE_LOCK(0x%p) %s %d\n", mutex,__FILE__,__LINE__); \
112 EnterCriticalSection(mutex)
113 #define RELEASE_LOCK(mutex) \
114 debugBelch("RELEASE_LOCK(0x%p) %s %d\n", mutex,__FILE__,__LINE__); \
115 LeaveCriticalSection(mutex)
116 #define ASSERT_LOCK_HELD(mutex) /* nothing */
120 #define ACQUIRE_LOCK(mutex) EnterCriticalSection(mutex)
121 #define RELEASE_LOCK(mutex) LeaveCriticalSection(mutex)
123 // I don't know how to do this. TryEnterCriticalSection() doesn't do
125 #define ASSERT_LOCK_HELD(mutex) /* nothing */
131 typedef HANDLE Mutex;
133 // casting to (Mutex *) here required due to use in .cmm files where
134 // the argument has (void *) type.
135 #define ACQUIRE_LOCK(mutex) \
136 if (WaitForSingleObject(*((Mutex *)mutex),INFINITE) == WAIT_FAILED) { \
137 barf("WaitForSingleObject: %d", GetLastError()); \
140 #define RELEASE_LOCK(mutex) \
141 if (ReleaseMutex(*((Mutex *)mutex)) == 0) { \
142 barf("ReleaseMutex: %d", GetLastError()); \
145 #define ASSERT_LOCK_HELD(mutex) /* nothing */
148 #endif // CMINUSMINUS
151 # error "Threads not supported"
157 // General thread operations
159 extern OSThreadId osThreadId ( void );
160 extern void shutdownThread ( void ) GNUC3_ATTRIBUTE(__noreturn__);
161 extern void yieldThread ( void );
163 typedef void OSThreadProcAttr OSThreadProc(void *);
165 extern int createOSThread ( OSThreadId* tid,
166 OSThreadProc *startProc, void *param);
167 extern rtsBool osThreadIsAlive ( OSThreadId id );
168 extern void interruptOSThread (OSThreadId id);
171 // Condition Variables
173 extern void initCondition ( Condition* pCond );
174 extern void closeCondition ( Condition* pCond );
175 extern rtsBool broadcastCondition ( Condition* pCond );
176 extern rtsBool signalCondition ( Condition* pCond );
177 extern rtsBool waitCondition ( Condition* pCond,
183 extern void initMutex ( Mutex* pMut );
184 extern void closeMutex ( Mutex* pMut );
187 // Thread-local storage
189 void newThreadLocalKey (ThreadLocalKey *key);
190 void *getThreadLocalVar (ThreadLocalKey *key);
191 void setThreadLocalVar (ThreadLocalKey *key, void *value);
192 void freeThreadLocalKey (ThreadLocalKey *key);
194 // Processors and affinity
195 nat getNumberOfProcessors (void);
196 void setThreadAffinity (nat n, nat m);
197 #endif // !CMINUSMINUS
201 #define ACQUIRE_LOCK(l)
202 #define RELEASE_LOCK(l)
203 #define ASSERT_LOCK_HELD(l)
205 #endif /* defined(THREADED_RTS) */
208 // Support for forkOS (defined regardless of THREADED_RTS, but does
209 // nothing when !THREADED_RTS).
212 int forkOS_createThread ( HsStablePtr entry );
215 #endif /* RTS_OSTHREADS_H */