2ebbd1e0f19f5e141aa99c6db0c3f7ba839683cf
[ghc.git] / includes / rts / OSThreads.h
1 /* ---------------------------------------------------------------------------
2 *
3 * (c) The GHC Team, 2001-2009
4 *
5 * Accessing OS threads functionality in a (mostly) OS-independent
6 * manner.
7 *
8 * Do not #include this file directly: #include "Rts.h" instead.
9 *
10 * To understand the structure of the RTS headers, see the wiki:
11 * http://ghc.haskell.org/trac/ghc/wiki/Commentary/SourceTree/Includes
12 *
13 * --------------------------------------------------------------------------*/
14
15 #ifndef RTS_OSTHREADS_H
16 #define RTS_OSTHREADS_H
17
18 #if defined(HAVE_PTHREAD_H) && !defined(mingw32_HOST_OS)
19
20 #if CMINUSMINUS
21
22 #define OS_ACQUIRE_LOCK(mutex) foreign "C" pthread_mutex_lock(mutex)
23 #define OS_RELEASE_LOCK(mutex) foreign "C" pthread_mutex_unlock(mutex)
24 #define OS_ASSERT_LOCK_HELD(mutex) /* nothing */
25
26 #else
27
28 #include <pthread.h>
29 #include <errno.h>
30
31 typedef pthread_cond_t Condition;
32 typedef pthread_mutex_t Mutex;
33 typedef pthread_t OSThreadId;
34 typedef pthread_key_t ThreadLocalKey;
35
36 #define OSThreadProcAttr /* nothing */
37
38 #define INIT_COND_VAR PTHREAD_COND_INITIALIZER
39
40 #ifdef LOCK_DEBUG
41 #define LOCK_DEBUG_BELCH(what, mutex) \
42 debugBelch("%s(0x%p) %s %d\n", what, mutex, __FILE__, __LINE__)
43 #else
44 #define LOCK_DEBUG_BELCH(what, mutex) /* nothing */
45 #endif
46
47 /* Always check the result of lock and unlock. */
48 #define OS_ACQUIRE_LOCK(mutex) \
49 LOCK_DEBUG_BELCH("ACQUIRE_LOCK", mutex); \
50 if (pthread_mutex_lock(mutex) == EDEADLK) { \
51 barf("multiple ACQUIRE_LOCK: %s %d", __FILE__,__LINE__); \
52 }
53
54 // Returns zero if the lock was acquired.
55 EXTERN_INLINE int TRY_ACQUIRE_LOCK(pthread_mutex_t *mutex);
56 EXTERN_INLINE int TRY_ACQUIRE_LOCK(pthread_mutex_t *mutex)
57 {
58 LOCK_DEBUG_BELCH("TRY_ACQUIRE_LOCK", mutex);
59 return pthread_mutex_trylock(mutex);
60 }
61
62 #define OS_RELEASE_LOCK(mutex) \
63 LOCK_DEBUG_BELCH("RELEASE_LOCK", mutex); \
64 if (pthread_mutex_unlock(mutex) != 0) { \
65 barf("RELEASE_LOCK: I do not own this lock: %s %d", __FILE__,__LINE__); \
66 }
67
68 // Note: this assertion calls pthread_mutex_lock() on a mutex that
69 // is already held by the calling thread. The mutex should therefore
70 // have been created with PTHREAD_MUTEX_ERRORCHECK, otherwise this
71 // assertion will hang. We always initialise mutexes with
72 // PTHREAD_MUTEX_ERRORCHECK when DEBUG is on (see rts/posix/OSThreads.h).
73 #define OS_ASSERT_LOCK_HELD(mutex) ASSERT(pthread_mutex_lock(mutex) == EDEADLK)
74
75 #endif // CMINUSMINUS
76
77 # elif defined(HAVE_WINDOWS_H)
78
79 #if CMINUSMINUS
80
81 /* We jump through a hoop here to get a CCall EnterCriticalSection
82 and LeaveCriticalSection, as that's what C-- wants. */
83
84 #define OS_ACQUIRE_LOCK(mutex) foreign "stdcall" EnterCriticalSection(mutex)
85 #define OS_RELEASE_LOCK(mutex) foreign "stdcall" LeaveCriticalSection(mutex)
86 #define OS_ASSERT_LOCK_HELD(mutex) /* nothing */
87
88 #else
89
90 #include <windows.h>
91
92 typedef HANDLE Condition;
93 typedef DWORD OSThreadId;
94 // don't be tempted to use HANDLE as the OSThreadId: there can be
95 // many HANDLES to a given thread, so comparison would not work.
96 typedef DWORD ThreadLocalKey;
97
98 #define OSThreadProcAttr __stdcall
99
100 #define INIT_COND_VAR 0
101
102 // We have a choice for implementing Mutexes on Windows. Standard
103 // Mutexes are kernel objects that require kernel calls to
104 // acquire/release, whereas CriticalSections are spin-locks that block
105 // in the kernel after spinning for a configurable number of times.
106 // CriticalSections are *much* faster, so we use those. The Mutex
107 // implementation is left here for posterity.
108 #define USE_CRITICAL_SECTIONS 1
109
110 #if USE_CRITICAL_SECTIONS
111
112 typedef CRITICAL_SECTION Mutex;
113
114 #ifdef LOCK_DEBUG
115
116 #define OS_ACQUIRE_LOCK(mutex) \
117 debugBelch("ACQUIRE_LOCK(0x%p) %s %d\n", mutex,__FILE__,__LINE__); \
118 EnterCriticalSection(mutex)
119 #define OS_RELEASE_LOCK(mutex) \
120 debugBelch("RELEASE_LOCK(0x%p) %s %d\n", mutex,__FILE__,__LINE__); \
121 LeaveCriticalSection(mutex)
122 #define OS_ASSERT_LOCK_HELD(mutex) /* nothing */
123
124 #else
125
126 #define OS_ACQUIRE_LOCK(mutex) EnterCriticalSection(mutex)
127 #define TRY_ACQUIRE_LOCK(mutex) (TryEnterCriticalSection(mutex) == 0)
128 #define OS_RELEASE_LOCK(mutex) LeaveCriticalSection(mutex)
129
130 // I don't know how to do this. TryEnterCriticalSection() doesn't do
131 // the right thing.
132 #define OS_ASSERT_LOCK_HELD(mutex) /* nothing */
133
134 #endif
135
136 #else
137
138 typedef HANDLE Mutex;
139
140 // casting to (Mutex *) here required due to use in .cmm files where
141 // the argument has (void *) type.
142 #define OS_ACQUIRE_LOCK(mutex) \
143 if (WaitForSingleObject(*((Mutex *)mutex),INFINITE) == WAIT_FAILED) { \
144 barf("WaitForSingleObject: %d", GetLastError()); \
145 }
146
147 #define OS_RELEASE_LOCK(mutex) \
148 if (ReleaseMutex(*((Mutex *)mutex)) == 0) { \
149 barf("ReleaseMutex: %d", GetLastError()); \
150 }
151
152 #define OS_ASSERT_LOCK_HELD(mutex) /* nothing */
153 #endif
154
155 #endif // CMINUSMINUS
156
157 # elif defined(THREADED_RTS)
158 # error "Threads not supported"
159 # endif
160
161
162 #ifndef CMINUSMINUS
163 //
164 // General thread operations
165 //
166 extern OSThreadId osThreadId ( void );
167 extern void shutdownThread ( void ) GNUC3_ATTRIBUTE(__noreturn__);
168 extern void yieldThread ( void );
169
170 typedef void OSThreadProcAttr OSThreadProc(void *);
171
172 extern int createOSThread ( OSThreadId* tid, char *name,
173 OSThreadProc *startProc, void *param);
174 extern bool osThreadIsAlive ( OSThreadId id );
175 extern void interruptOSThread (OSThreadId id);
176
177 //
178 // Condition Variables
179 //
180 extern void initCondition ( Condition* pCond );
181 extern void closeCondition ( Condition* pCond );
182 extern bool broadcastCondition ( Condition* pCond );
183 extern bool signalCondition ( Condition* pCond );
184 extern bool waitCondition ( Condition* pCond, Mutex* pMut );
185
186 //
187 // Mutexes
188 //
189 extern void initMutex ( Mutex* pMut );
190 extern void closeMutex ( Mutex* pMut );
191
192 //
193 // Thread-local storage
194 //
195 void newThreadLocalKey (ThreadLocalKey *key);
196 void *getThreadLocalVar (ThreadLocalKey *key);
197 void setThreadLocalVar (ThreadLocalKey *key, void *value);
198 void freeThreadLocalKey (ThreadLocalKey *key);
199
200 // Processors and affinity
201 void setThreadAffinity (uint32_t n, uint32_t m);
202 void setThreadNode (uint32_t node);
203 void releaseThreadNode (void);
204 #endif // !CMINUSMINUS
205
206 #ifdef THREADED_RTS
207
208 #define ACQUIRE_LOCK(l) OS_ACQUIRE_LOCK(l)
209 #define RELEASE_LOCK(l) OS_RELEASE_LOCK(l)
210 #define ASSERT_LOCK_HELD(l) OS_ASSERT_LOCK_HELD(l)
211
212 #else
213
214 #define ACQUIRE_LOCK(l)
215 #define RELEASE_LOCK(l)
216 #define ASSERT_LOCK_HELD(l)
217
218 #endif /* defined(THREADED_RTS) */
219
220 #ifndef CMINUSMINUS
221 //
222 // Support for forkOS (defined regardless of THREADED_RTS, but does
223 // nothing when !THREADED_RTS).
224 //
225 int forkOS_createThread ( HsStablePtr entry );
226
227 //
228 // Free any global resources created in OSThreads.
229 //
230 void freeThreadingResources(void);
231
232 //
233 // Returns the number of processor cores in the machine
234 //
235 uint32_t getNumberOfProcessors (void);
236
237 //
238 // Support for getting at the kernel thread Id for tracing/profiling.
239 //
240 // This stuff is optional and only used for tracing/profiling purposes, to
241 // match up thread ids recorded by other tools. For example, on Linux and OSX
242 // the pthread_t type is not the same as the kernel thread id, and system
243 // profiling tools like Linux perf, and OSX's DTrace use the kernel thread Id.
244 // So if we want to match up RTS tasks with kernel threads recorded by these
245 // tools then we need to know the kernel thread Id, and this must be a separate
246 // type from the OSThreadId.
247 //
248 // If the feature cannot be supported on an OS, it is OK to always return 0.
249 // In particular it would almost certaily be meaningless on systems not using
250 // a 1:1 threading model.
251
252 // We use a common serialisable representation on all OSs
253 // This is ok for Windows, OSX and Linux.
254 typedef StgWord64 KernelThreadId;
255
256 // Get the current kernel thread id
257 KernelThreadId kernelThreadId (void);
258
259 #endif /* CMINUSMINUS */
260
261 #endif /* RTS_OSTHREADS_H */