Changing internal data structures used by Hpc
[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 #include <pthread.h>
18
19 typedef pthread_cond_t  Condition;
20 typedef pthread_mutex_t Mutex;
21 typedef pthread_t       OSThreadId;
22 typedef pthread_key_t   ThreadLocalKey;
23
24 #define OSThreadProcAttr /* nothing */
25
26 #define INIT_COND_VAR       PTHREAD_COND_INITIALIZER
27
28 #ifdef LOCK_DEBUG
29
30 #define ACQUIRE_LOCK(mutex) \
31   debugBelch("ACQUIRE_LOCK(0x%p) %s %d\n", mutex,__FILE__,__LINE__); \
32   pthread_mutex_lock(mutex)
33 #define RELEASE_LOCK(mutex) \
34   debugBelch("RELEASE_LOCK(0x%p) %s %d\n", mutex,__FILE__,__LINE__); \
35   pthread_mutex_unlock(mutex)
36 #define ASSERT_LOCK_HELD(mutex) /* nothing */
37
38 #elif defined(DEBUG) && defined(linux_HOST_OS)
39 #include <errno.h>
40 /* 
41  * On Linux, we can use extensions to determine whether we already
42  * hold a lock or not, which is useful for debugging.
43  */
44 #define ACQUIRE_LOCK(mutex) \
45   if (pthread_mutex_lock(mutex) == EDEADLK) { \
46     barf("multiple ACQUIRE_LOCK: %s %d", __FILE__,__LINE__); \
47   }
48 #define RELEASE_LOCK(mutex) \
49   if (pthread_mutex_unlock(mutex) != 0) { \
50     barf("RELEASE_LOCK: I do not own this lock: %s %d", __FILE__,__LINE__); \
51   }
52
53 #define ASSERT_LOCK_HELD(mutex) ASSERT(pthread_mutex_lock(mutex) == EDEADLK)
54
55 #define ASSERT_LOCK_NOTHELD(mutex)              \
56   if (pthread_mutex_lock(mutex) != EDEADLK) {   \
57      pthread_mutex_unlock(mutex);               \
58   } else {                                      \
59     ASSERT(0);                                  \
60   }
61
62
63 #else
64
65 #define ACQUIRE_LOCK(mutex) pthread_mutex_lock(mutex)
66 #define RELEASE_LOCK(mutex) pthread_mutex_unlock(mutex)
67 #define ASSERT_LOCK_HELD(mutex) /* nothing */
68
69 #endif
70
71 # elif defined(HAVE_WINDOWS_H)
72 #include <windows.h>
73
74 typedef HANDLE Condition;
75 typedef DWORD OSThreadId;
76 // don't be tempted to use HANDLE as the OSThreadId: there can be 
77 // many HANDLES to a given thread, so comparison would not work.
78 typedef DWORD ThreadLocalKey;
79
80 #define OSThreadProcAttr __stdcall
81
82 #define INIT_COND_VAR  0
83
84 // We have a choice for implementing Mutexes on Windows.  Standard
85 // Mutexes are kernel objects that require kernel calls to
86 // acquire/release, whereas CriticalSections are spin-locks that block
87 // in the kernel after spinning for a configurable number of times.
88 // CriticalSections are *much* faster, so we use those.  The Mutex
89 // implementation is left here for posterity.
90 #define USE_CRITICAL_SECTIONS 1
91
92 #if USE_CRITICAL_SECTIONS
93
94 typedef CRITICAL_SECTION Mutex;
95
96 #ifdef LOCK_DEBUG
97
98 #define ACQUIRE_LOCK(mutex) \
99   debugBelch("ACQUIRE_LOCK(0x%p) %s %d\n", mutex,__FILE__,__LINE__); \
100   EnterCriticalSection(mutex)
101 #define RELEASE_LOCK(mutex) \
102   debugBelch("RELEASE_LOCK(0x%p) %s %d\n", mutex,__FILE__,__LINE__); \
103   LeaveCriticalSection(mutex)
104 #define ASSERT_LOCK_HELD(mutex) /* nothing */
105
106 #else
107
108 #define ACQUIRE_LOCK(mutex)  EnterCriticalSection(mutex)
109 #define RELEASE_LOCK(mutex)  LeaveCriticalSection(mutex)
110
111 // I don't know how to do this.  TryEnterCriticalSection() doesn't do
112 // the right thing.
113 #define ASSERT_LOCK_HELD(mutex) /* nothing */
114
115 #endif
116
117 #else
118
119 typedef HANDLE Mutex;
120
121 // casting to (Mutex *) here required due to use in .cmm files where
122 // the argument has (void *) type.
123 #define ACQUIRE_LOCK(mutex)                                     \
124     if (WaitForSingleObject(*((Mutex *)mutex),INFINITE) == WAIT_FAILED) { \
125         barf("WaitForSingleObject: %d", GetLastError());        \
126     }
127
128 #define RELEASE_LOCK(mutex)                             \
129     if (ReleaseMutex(*((Mutex *)mutex)) == 0) {         \
130         barf("ReleaseMutex: %d", GetLastError());       \
131     }
132
133 #define ASSERT_LOCK_HELD(mutex) /* nothing */
134 #endif
135
136 # else
137 #  error "Threads not supported"
138 # endif
139
140 //
141 // General thread operations
142 //
143 extern OSThreadId osThreadId      ( void );
144 extern void shutdownThread        ( void );
145 extern void yieldThread           ( void );
146
147 typedef void OSThreadProcAttr OSThreadProc(void *);
148
149 extern int  createOSThread        ( OSThreadId* tid, 
150                                     OSThreadProc *startProc, void *param);
151 extern rtsBool osThreadIsAlive    ( OSThreadId id );
152
153 //
154 // Condition Variables
155 //
156 extern void initCondition         ( Condition* pCond );
157 extern void closeCondition        ( Condition* pCond );
158 extern rtsBool broadcastCondition ( Condition* pCond );
159 extern rtsBool signalCondition    ( Condition* pCond );
160 extern rtsBool waitCondition      ( Condition* pCond, 
161                                     Mutex* pMut );
162
163 //
164 // Mutexes
165 //
166 extern void initMutex             ( Mutex* pMut );
167 extern void closeMutex            ( Mutex* pMut );
168
169 //
170 // Thread-local storage
171 //
172 void  newThreadLocalKey (ThreadLocalKey *key);
173 void *getThreadLocalVar (ThreadLocalKey *key);
174 void  setThreadLocalVar (ThreadLocalKey *key, void *value);
175 void  freeThreadLocalKey (ThreadLocalKey *key);
176
177 #else
178
179 #define ACQUIRE_LOCK(l)
180 #define RELEASE_LOCK(l)
181 #define ASSERT_LOCK_HELD(l)
182
183 #endif /* defined(THREADED_RTS) */
184
185 #endif /* __OSTHREADS_H__ */