5d3e6ba1406df1c06e12e64da73b762a01af4878
[ghc-hetmet.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://hackage.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(THREADED_RTS) /* to the end */
19
20 # if defined(HAVE_PTHREAD_H) && !defined(WANT_NATIVE_WIN32_THREADS)
21
22 #if CMINUSMINUS
23
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 */
27
28 #else
29
30 #include <pthread.h>
31 #include <errno.h>
32
33 typedef pthread_cond_t  Condition;
34 typedef pthread_mutex_t Mutex;
35 typedef pthread_t       OSThreadId;
36 typedef pthread_key_t   ThreadLocalKey;
37
38 #define OSThreadProcAttr /* nothing */
39
40 #define INIT_COND_VAR       PTHREAD_COND_INITIALIZER
41
42 #ifdef LOCK_DEBUG
43 #define LOCK_DEBUG_BELCH(what, mutex) \
44   debugBelch("%s(0x%p) %s %d\n", what, mutex, __FILE__, __LINE__)
45 #else
46 #define LOCK_DEBUG_BELCH(what, mutex) /* nothing */
47 #endif
48
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__); \
54   }
55
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__); \
60   }
61
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)
68
69 #endif // CMINUSMINUS
70
71 # elif defined(HAVE_WINDOWS_H)
72
73 #if CMINUSMINUS
74
75 /* We jump through a hoop here to get a CCall EnterCriticalSection
76    and LeaveCriticalSection, as that's what C-- wants. */
77
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 */
81
82 #else
83
84 #include <windows.h>
85
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;
91
92 #define OSThreadProcAttr __stdcall
93
94 #define INIT_COND_VAR  0
95
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
103
104 #if USE_CRITICAL_SECTIONS
105
106 typedef CRITICAL_SECTION Mutex;
107
108 #ifdef LOCK_DEBUG
109
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 */
117
118 #else
119
120 #define ACQUIRE_LOCK(mutex)  EnterCriticalSection(mutex)
121 #define RELEASE_LOCK(mutex)  LeaveCriticalSection(mutex)
122
123 // I don't know how to do this.  TryEnterCriticalSection() doesn't do
124 // the right thing.
125 #define ASSERT_LOCK_HELD(mutex) /* nothing */
126
127 #endif
128
129 #else
130
131 typedef HANDLE Mutex;
132
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());        \
138     }
139
140 #define RELEASE_LOCK(mutex)                             \
141     if (ReleaseMutex(*((Mutex *)mutex)) == 0) {         \
142         barf("ReleaseMutex: %d", GetLastError());       \
143     }
144
145 #define ASSERT_LOCK_HELD(mutex) /* nothing */
146 #endif
147
148 #endif // CMINUSMINUS
149
150 # else
151 #  error "Threads not supported"
152 # endif
153
154
155 #ifndef CMINUSMINUS
156 //
157 // General thread operations
158 //
159 extern OSThreadId osThreadId      ( void );
160 extern void shutdownThread        ( void )   GNUC3_ATTRIBUTE(__noreturn__);
161 extern void yieldThread           ( void );
162
163 typedef void OSThreadProcAttr OSThreadProc(void *);
164
165 extern int  createOSThread        ( OSThreadId* tid, 
166                                     OSThreadProc *startProc, void *param);
167 extern rtsBool osThreadIsAlive    ( OSThreadId id );
168 extern void interruptOSThread (OSThreadId id);
169
170 //
171 // Condition Variables
172 //
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, 
178                                     Mutex* pMut );
179
180 //
181 // Mutexes
182 //
183 extern void initMutex             ( Mutex* pMut );
184 extern void closeMutex            ( Mutex* pMut );
185
186 //
187 // Thread-local storage
188 //
189 void  newThreadLocalKey (ThreadLocalKey *key);
190 void *getThreadLocalVar (ThreadLocalKey *key);
191 void  setThreadLocalVar (ThreadLocalKey *key, void *value);
192 void  freeThreadLocalKey (ThreadLocalKey *key);
193
194 // Processors and affinity
195 nat  getNumberOfProcessors (void);
196 void setThreadAffinity     (nat n, nat m);
197 #endif // !CMINUSMINUS
198
199 #else
200
201 #define ACQUIRE_LOCK(l)
202 #define RELEASE_LOCK(l)
203 #define ASSERT_LOCK_HELD(l)
204
205 #endif /* defined(THREADED_RTS) */
206
207 //
208 // Support for forkOS (defined regardless of THREADED_RTS, but does
209 // nothing when !THREADED_RTS).
210 //
211 #ifndef CMINUSMINUS
212 int forkOS_createThread ( HsStablePtr entry );
213 #endif
214
215 #endif /* RTS_OSTHREADS_H */