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