Add closeMutex and use it on clean up
[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 #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 typedef DWORD ThreadLocalKey;
77
78 #define OSThreadProcAttr __stdcall
79
80 #define INIT_COND_VAR 0
81
82 // We have a choice for implementing Mutexes on Windows. Standard
83 // Mutexes are kernel objects that require kernel calls to
84 // acquire/release, whereas CriticalSections are spin-locks that block
85 // in the kernel after spinning for a configurable number of times.
86 // CriticalSections are *much* faster, so we use those. The Mutex
87 // implementation is left here for posterity.
88 #define USE_CRITICAL_SECTIONS 1
89
90 #if USE_CRITICAL_SECTIONS
91
92 typedef CRITICAL_SECTION Mutex;
93
94 #ifdef LOCK_DEBUG
95
96 #define ACQUIRE_LOCK(mutex) \
97 debugBelch("ACQUIRE_LOCK(0x%p) %s %d\n", mutex,__FILE__,__LINE__); \
98 EnterCriticalSection(mutex)
99 #define RELEASE_LOCK(mutex) \
100 debugBelch("RELEASE_LOCK(0x%p) %s %d\n", mutex,__FILE__,__LINE__); \
101 LeaveCriticalSection(mutex)
102 #define ASSERT_LOCK_HELD(mutex) /* nothing */
103
104 #else
105
106 #define ACQUIRE_LOCK(mutex) EnterCriticalSection(mutex)
107 #define RELEASE_LOCK(mutex) LeaveCriticalSection(mutex)
108
109 // I don't know how to do this. TryEnterCriticalSection() doesn't do
110 // the right thing.
111 #define ASSERT_LOCK_HELD(mutex) /* nothing */
112
113 #endif
114
115 #else
116
117 typedef HANDLE Mutex;
118
119 // casting to (Mutex *) here required due to use in .cmm files where
120 // the argument has (void *) type.
121 #define ACQUIRE_LOCK(mutex) \
122 if (WaitForSingleObject(*((Mutex *)mutex),INFINITE) == WAIT_FAILED) { \
123 barf("WaitForSingleObject: %d", GetLastError()); \
124 }
125
126 #define RELEASE_LOCK(mutex) \
127 if (ReleaseMutex(*((Mutex *)mutex)) == 0) { \
128 barf("ReleaseMutex: %d", GetLastError()); \
129 }
130
131 #define ASSERT_LOCK_HELD(mutex) /* nothing */
132 #endif
133
134 # else
135 # error "Threads not supported"
136 # endif
137
138 //
139 // General thread operations
140 //
141 extern OSThreadId osThreadId ( void );
142 extern void shutdownThread ( void );
143 extern void yieldThread ( void );
144
145 typedef void OSThreadProcAttr OSThreadProc(void *);
146
147 extern int createOSThread ( OSThreadId* tid,
148 OSThreadProc *startProc, void *param);
149
150 //
151 // Condition Variables
152 //
153 extern void initCondition ( Condition* pCond );
154 extern void closeCondition ( Condition* pCond );
155 extern rtsBool broadcastCondition ( Condition* pCond );
156 extern rtsBool signalCondition ( Condition* pCond );
157 extern rtsBool waitCondition ( Condition* pCond,
158 Mutex* pMut );
159
160 //
161 // Mutexes
162 //
163 extern void initMutex ( Mutex* pMut );
164 extern void closeMutex ( Mutex* pMut );
165
166 //
167 // Thread-local storage
168 //
169 void newThreadLocalKey (ThreadLocalKey *key);
170 void *getThreadLocalVar (ThreadLocalKey *key);
171 void setThreadLocalVar (ThreadLocalKey *key, void *value);
172
173 #else
174
175 #define ACQUIRE_LOCK(l)
176 #define RELEASE_LOCK(l)
177 #define ASSERT_LOCK_HELD(l)
178
179 #endif /* defined(THREADED_RTS) */
180
181 #endif /* __OSTHREADS_H__ */