replace sparc-specific Int64 code with calls to platform-independent macros
[ghc-hetmet.git] / includes / rts / 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 RTS_OSTHREADS_H
11 #define RTS_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 #include <errno.h>
27
28 typedef pthread_cond_t  Condition;
29 typedef pthread_mutex_t Mutex;
30 typedef pthread_t       OSThreadId;
31 typedef pthread_key_t   ThreadLocalKey;
32
33 #define OSThreadProcAttr /* nothing */
34
35 #define INIT_COND_VAR       PTHREAD_COND_INITIALIZER
36
37 #ifdef LOCK_DEBUG
38 #define LOCK_DEBUG_BELCH(what, mutex) \
39   debugBelch("%s(0x%p) %s %d\n", what, mutex, __FILE__, __LINE__)
40 #else
41 #define LOCK_DEBUG_BELCH(what, mutex) /* nothing */
42 #endif
43
44 /* Always check the result of lock and unlock. */
45 #define ACQUIRE_LOCK(mutex) \
46   LOCK_DEBUG_BELCH("ACQUIRE_LOCK", mutex); \
47   if (pthread_mutex_lock(mutex) == EDEADLK) { \
48     barf("multiple ACQUIRE_LOCK: %s %d", __FILE__,__LINE__); \
49   }
50
51 #define RELEASE_LOCK(mutex) \
52   LOCK_DEBUG_BELCH("RELEASE_LOCK", mutex); \
53   if (pthread_mutex_unlock(mutex) != 0) { \
54     barf("RELEASE_LOCK: I do not own this lock: %s %d", __FILE__,__LINE__); \
55   }
56
57 // Note: this assertion calls pthread_mutex_lock() on a mutex that
58 // is already held by the calling thread.  The mutex should therefore
59 // have been created with PTHREAD_MUTEX_ERRORCHECK, otherwise this
60 // assertion will hang.  We always initialise mutexes with
61 // PTHREAD_MUTEX_ERRORCHECK when DEBUG is on (see rts/posix/OSThreads.h).
62 #define ASSERT_LOCK_HELD(mutex) ASSERT(pthread_mutex_lock(mutex) == EDEADLK)
63
64 #endif // CMINUSMINUS
65
66 # elif defined(HAVE_WINDOWS_H)
67
68 #if CMINUSMINUS
69
70 /* We jump through a hoop here to get a CCall EnterCriticalSection
71    and LeaveCriticalSection, as that's what C-- wants. */
72
73 #define ACQUIRE_LOCK(mutex) foreign "stdcall" EnterCriticalSection(mutex)
74 #define RELEASE_LOCK(mutex) foreign "stdcall" LeaveCriticalSection(mutex)
75 #define ASSERT_LOCK_HELD(mutex) /* nothing */
76
77 #else
78
79 #include <windows.h>
80
81 typedef HANDLE Condition;
82 typedef DWORD OSThreadId;
83 // don't be tempted to use HANDLE as the OSThreadId: there can be 
84 // many HANDLES to a given thread, so comparison would not work.
85 typedef DWORD ThreadLocalKey;
86
87 #define OSThreadProcAttr __stdcall
88
89 #define INIT_COND_VAR  0
90
91 // We have a choice for implementing Mutexes on Windows.  Standard
92 // Mutexes are kernel objects that require kernel calls to
93 // acquire/release, whereas CriticalSections are spin-locks that block
94 // in the kernel after spinning for a configurable number of times.
95 // CriticalSections are *much* faster, so we use those.  The Mutex
96 // implementation is left here for posterity.
97 #define USE_CRITICAL_SECTIONS 1
98
99 #if USE_CRITICAL_SECTIONS
100
101 typedef CRITICAL_SECTION Mutex;
102
103 #ifdef LOCK_DEBUG
104
105 #define ACQUIRE_LOCK(mutex) \
106   debugBelch("ACQUIRE_LOCK(0x%p) %s %d\n", mutex,__FILE__,__LINE__); \
107   EnterCriticalSection(mutex)
108 #define RELEASE_LOCK(mutex) \
109   debugBelch("RELEASE_LOCK(0x%p) %s %d\n", mutex,__FILE__,__LINE__); \
110   LeaveCriticalSection(mutex)
111 #define ASSERT_LOCK_HELD(mutex) /* nothing */
112
113 #else
114
115 #define ACQUIRE_LOCK(mutex)  EnterCriticalSection(mutex)
116 #define RELEASE_LOCK(mutex)  LeaveCriticalSection(mutex)
117
118 // I don't know how to do this.  TryEnterCriticalSection() doesn't do
119 // the right thing.
120 #define ASSERT_LOCK_HELD(mutex) /* nothing */
121
122 #endif
123
124 #else
125
126 typedef HANDLE Mutex;
127
128 // casting to (Mutex *) here required due to use in .cmm files where
129 // the argument has (void *) type.
130 #define ACQUIRE_LOCK(mutex)                                     \
131     if (WaitForSingleObject(*((Mutex *)mutex),INFINITE) == WAIT_FAILED) { \
132         barf("WaitForSingleObject: %d", GetLastError());        \
133     }
134
135 #define RELEASE_LOCK(mutex)                             \
136     if (ReleaseMutex(*((Mutex *)mutex)) == 0) {         \
137         barf("ReleaseMutex: %d", GetLastError());       \
138     }
139
140 #define ASSERT_LOCK_HELD(mutex) /* nothing */
141 #endif
142
143 #endif // CMINUSMINUS
144
145 # else
146 #  error "Threads not supported"
147 # endif
148
149
150 #ifndef CMINUSMINUS
151 //
152 // General thread operations
153 //
154 extern OSThreadId osThreadId      ( void );
155 extern void shutdownThread        ( void )   GNUC3_ATTRIBUTE(__noreturn__);
156 extern void yieldThread           ( void );
157
158 typedef void OSThreadProcAttr OSThreadProc(void *);
159
160 extern int  createOSThread        ( OSThreadId* tid, 
161                                     OSThreadProc *startProc, void *param);
162 extern rtsBool osThreadIsAlive    ( OSThreadId id );
163
164 //
165 // Condition Variables
166 //
167 extern void initCondition         ( Condition* pCond );
168 extern void closeCondition        ( Condition* pCond );
169 extern rtsBool broadcastCondition ( Condition* pCond );
170 extern rtsBool signalCondition    ( Condition* pCond );
171 extern rtsBool waitCondition      ( Condition* pCond, 
172                                     Mutex* pMut );
173
174 //
175 // Mutexes
176 //
177 extern void initMutex             ( Mutex* pMut );
178 extern void closeMutex            ( Mutex* pMut );
179
180 //
181 // Thread-local storage
182 //
183 void  newThreadLocalKey (ThreadLocalKey *key);
184 void *getThreadLocalVar (ThreadLocalKey *key);
185 void  setThreadLocalVar (ThreadLocalKey *key, void *value);
186 void  freeThreadLocalKey (ThreadLocalKey *key);
187
188 // Processors and affinity
189 nat  getNumberOfProcessors (void);
190 void setThreadAffinity     (nat n, nat m);
191 #endif // !CMINUSMINUS
192
193 #else
194
195 #define ACQUIRE_LOCK(l)
196 #define RELEASE_LOCK(l)
197 #define ASSERT_LOCK_HELD(l)
198
199 #endif /* defined(THREADED_RTS) */
200
201 //
202 // Support for forkOS (defined regardless of THREADED_RTS, but does
203 // nothing when !THREADED_RTS).
204 //
205 #ifndef CMINUSMINUS
206 int forkOS_createThread ( HsStablePtr entry );
207 #endif
208
209 #endif /* RTS_OSTHREADS_H */