Improve handling of -fdph-* flags
[ghc.git] / includes / OSThreads.h
1 /* ---------------------------------------------------------------------------
2 *
3 * (c) The GHC Team, 2001-2005
4 *
5 * Accessing OS threads functionality in a (mostly) OS-independent
6 * manner.
7 *
8 * --------------------------------------------------------------------------*/
9
10 #ifndef __OSTHREADS_H__
11 #define __OSTHREADS_H__
12
13 #if defined(THREADED_RTS) /* to the end */
14
15 # if defined(HAVE_PTHREAD_H) && !defined(WANT_NATIVE_WIN32_THREADS)
16
17 #if CMINUSMINUS
18
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 */
22
23 #else
24
25 #include <pthread.h>
26
27 typedef pthread_cond_t Condition;
28 typedef pthread_mutex_t Mutex;
29 typedef pthread_t OSThreadId;
30 typedef pthread_key_t ThreadLocalKey;
31
32 #define OSThreadProcAttr /* nothing */
33
34 #define INIT_COND_VAR PTHREAD_COND_INITIALIZER
35
36 #ifdef LOCK_DEBUG
37
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 */
45
46 #elif defined(DEBUG) && defined(linux_HOST_OS)
47 #include <errno.h>
48 /*
49 * On Linux, we can use extensions to determine whether we already
50 * hold a lock or not, which is useful for debugging.
51 */
52 #define ACQUIRE_LOCK(mutex) \
53 if (pthread_mutex_lock(mutex) == EDEADLK) { \
54 barf("multiple ACQUIRE_LOCK: %s %d", __FILE__,__LINE__); \
55 }
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__); \
59 }
60
61 #define ASSERT_LOCK_HELD(mutex) ASSERT(pthread_mutex_lock(mutex) == EDEADLK)
62
63 #define ASSERT_LOCK_NOTHELD(mutex) \
64 if (pthread_mutex_lock(mutex) != EDEADLK) { \
65 pthread_mutex_unlock(mutex); \
66 } else { \
67 ASSERT(0); \
68 }
69
70
71 #else
72
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 */
76
77 #endif
78
79 #endif // CMINUSMINUS
80
81 # elif defined(HAVE_WINDOWS_H)
82
83 #if CMINUSMINUS
84
85 /* We jump through a hoop here to get a CCall EnterCriticalSection
86 and LeaveCriticalSection, as that's what C-- wants. */
87
88 #define ACQUIRE_LOCK(mutex) foreign "stdcall" EnterCriticalSection(mutex)
89 #define RELEASE_LOCK(mutex) foreign "stdcall" LeaveCriticalSection(mutex)
90 #define ASSERT_LOCK_HELD(mutex) /* nothing */
91
92 #else
93
94 #include <windows.h>
95
96 typedef HANDLE Condition;
97 typedef DWORD OSThreadId;
98 // don't be tempted to use HANDLE as the OSThreadId: there can be
99 // many HANDLES to a given thread, so comparison would not work.
100 typedef DWORD ThreadLocalKey;
101
102 #define OSThreadProcAttr __stdcall
103
104 #define INIT_COND_VAR 0
105
106 // We have a choice for implementing Mutexes on Windows. Standard
107 // Mutexes are kernel objects that require kernel calls to
108 // acquire/release, whereas CriticalSections are spin-locks that block
109 // in the kernel after spinning for a configurable number of times.
110 // CriticalSections are *much* faster, so we use those. The Mutex
111 // implementation is left here for posterity.
112 #define USE_CRITICAL_SECTIONS 1
113
114 #if USE_CRITICAL_SECTIONS
115
116 typedef CRITICAL_SECTION Mutex;
117
118 #ifdef LOCK_DEBUG
119
120 #define ACQUIRE_LOCK(mutex) \
121 debugBelch("ACQUIRE_LOCK(0x%p) %s %d\n", mutex,__FILE__,__LINE__); \
122 EnterCriticalSection(mutex)
123 #define RELEASE_LOCK(mutex) \
124 debugBelch("RELEASE_LOCK(0x%p) %s %d\n", mutex,__FILE__,__LINE__); \
125 LeaveCriticalSection(mutex)
126 #define ASSERT_LOCK_HELD(mutex) /* nothing */
127
128 #else
129
130 #define ACQUIRE_LOCK(mutex) EnterCriticalSection(mutex)
131 #define RELEASE_LOCK(mutex) LeaveCriticalSection(mutex)
132
133 // I don't know how to do this. TryEnterCriticalSection() doesn't do
134 // the right thing.
135 #define ASSERT_LOCK_HELD(mutex) /* nothing */
136
137 #endif
138
139 #else
140
141 typedef HANDLE Mutex;
142
143 // casting to (Mutex *) here required due to use in .cmm files where
144 // the argument has (void *) type.
145 #define ACQUIRE_LOCK(mutex) \
146 if (WaitForSingleObject(*((Mutex *)mutex),INFINITE) == WAIT_FAILED) { \
147 barf("WaitForSingleObject: %d", GetLastError()); \
148 }
149
150 #define RELEASE_LOCK(mutex) \
151 if (ReleaseMutex(*((Mutex *)mutex)) == 0) { \
152 barf("ReleaseMutex: %d", GetLastError()); \
153 }
154
155 #define ASSERT_LOCK_HELD(mutex) /* nothing */
156 #endif
157
158 #endif // CMINUSMINUS
159
160 # else
161 # error "Threads not supported"
162 # endif
163
164
165 #ifndef CMINUSMINUS
166 //
167 // General thread operations
168 //
169 extern OSThreadId osThreadId ( void );
170 extern void shutdownThread ( void );
171 extern void yieldThread ( void );
172
173 typedef void OSThreadProcAttr OSThreadProc(void *);
174
175 extern int createOSThread ( OSThreadId* tid,
176 OSThreadProc *startProc, void *param);
177 extern rtsBool osThreadIsAlive ( OSThreadId id );
178
179 //
180 // Condition Variables
181 //
182 extern void initCondition ( Condition* pCond );
183 extern void closeCondition ( Condition* pCond );
184 extern rtsBool broadcastCondition ( Condition* pCond );
185 extern rtsBool signalCondition ( Condition* pCond );
186 extern rtsBool waitCondition ( Condition* pCond,
187 Mutex* pMut );
188
189 //
190 // Mutexes
191 //
192 extern void initMutex ( Mutex* pMut );
193 extern void closeMutex ( Mutex* pMut );
194
195 //
196 // Thread-local storage
197 //
198 void newThreadLocalKey (ThreadLocalKey *key);
199 void *getThreadLocalVar (ThreadLocalKey *key);
200 void setThreadLocalVar (ThreadLocalKey *key, void *value);
201 void freeThreadLocalKey (ThreadLocalKey *key);
202
203 #endif // !CMINUSMINUS
204
205 #else
206
207 #define ACQUIRE_LOCK(l)
208 #define RELEASE_LOCK(l)
209 #define ASSERT_LOCK_HELD(l)
210
211 #endif /* defined(THREADED_RTS) */
212
213 #endif /* __OSTHREADS_H__ */