allow build settings to be overriden by adding mk/validate.mk
[ghc-hetmet.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) pthread_mutex_lock(mutex)
20 #define RELEASE_LOCK(mutex) 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 #define ACQUIRE_LOCK(mutex) EnterCriticalSection(mutex)
86 #define RELEASE_LOCK(mutex) LeaveCriticalSection(mutex)
87 #define ASSERT_LOCK_HELD(mutex) /* nothing */
88
89 #else
90
91 #include <windows.h>
92
93 typedef HANDLE Condition;
94 typedef DWORD OSThreadId;
95 // don't be tempted to use HANDLE as the OSThreadId: there can be 
96 // many HANDLES to a given thread, so comparison would not work.
97 typedef DWORD ThreadLocalKey;
98
99 #define OSThreadProcAttr __stdcall
100
101 #define INIT_COND_VAR  0
102
103 // We have a choice for implementing Mutexes on Windows.  Standard
104 // Mutexes are kernel objects that require kernel calls to
105 // acquire/release, whereas CriticalSections are spin-locks that block
106 // in the kernel after spinning for a configurable number of times.
107 // CriticalSections are *much* faster, so we use those.  The Mutex
108 // implementation is left here for posterity.
109 #define USE_CRITICAL_SECTIONS 1
110
111 #if USE_CRITICAL_SECTIONS
112
113 typedef CRITICAL_SECTION Mutex;
114
115 #ifdef LOCK_DEBUG
116
117 #define ACQUIRE_LOCK(mutex) \
118   debugBelch("ACQUIRE_LOCK(0x%p) %s %d\n", mutex,__FILE__,__LINE__); \
119   EnterCriticalSection(mutex)
120 #define RELEASE_LOCK(mutex) \
121   debugBelch("RELEASE_LOCK(0x%p) %s %d\n", mutex,__FILE__,__LINE__); \
122   LeaveCriticalSection(mutex)
123 #define ASSERT_LOCK_HELD(mutex) /* nothing */
124
125 #else
126
127 #define ACQUIRE_LOCK(mutex)  EnterCriticalSection(mutex)
128 #define 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 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 ACQUIRE_LOCK(mutex)                                     \
143     if (WaitForSingleObject(*((Mutex *)mutex),INFINITE) == WAIT_FAILED) { \
144         barf("WaitForSingleObject: %d", GetLastError());        \
145     }
146
147 #define RELEASE_LOCK(mutex)                             \
148     if (ReleaseMutex(*((Mutex *)mutex)) == 0) {         \
149         barf("ReleaseMutex: %d", GetLastError());       \
150     }
151
152 #define ASSERT_LOCK_HELD(mutex) /* nothing */
153 #endif
154
155 #endif // CMINUSMINUS
156
157 # else
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 );
168 extern void yieldThread           ( void );
169
170 typedef void OSThreadProcAttr OSThreadProc(void *);
171
172 extern int  createOSThread        ( OSThreadId* tid, 
173                                     OSThreadProc *startProc, void *param);
174 extern rtsBool osThreadIsAlive    ( OSThreadId id );
175
176 //
177 // Condition Variables
178 //
179 extern void initCondition         ( Condition* pCond );
180 extern void closeCondition        ( Condition* pCond );
181 extern rtsBool broadcastCondition ( Condition* pCond );
182 extern rtsBool signalCondition    ( Condition* pCond );
183 extern rtsBool waitCondition      ( Condition* pCond, 
184                                     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 #endif // !CMINUSMINUS
201
202 #else
203
204 #define ACQUIRE_LOCK(l)
205 #define RELEASE_LOCK(l)
206 #define ASSERT_LOCK_HELD(l)
207
208 #endif /* defined(THREADED_RTS) */
209
210 #endif /* __OSTHREADS_H__ */