[project @ 2005-11-03 14:35:20 by simonmar]
[ghc-hetmet.git] / ghc / includes / OSThreads.h
1 /* ---------------------------------------------------------------------------
2  *
3  * (c) The GHC Team, 2001
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_MUTEX_VAR      PTHREAD_MUTEX_INITIALIZER
27 #define INIT_COND_VAR       PTHREAD_COND_INITIALIZER
28
29 #ifdef LOCK_DEBUG
30
31 #define ACQUIRE_LOCK(mutex) \
32   debugBelch("ACQUIRE_LOCK(0x%p) %s %d\n", mutex,__FILE__,__LINE__); \
33   pthread_mutex_lock(mutex)
34 #define RELEASE_LOCK(mutex) \
35   debugBelch("RELEASE_LOCK(0x%p) %s %d\n", mutex,__FILE__,__LINE__); \
36   pthread_mutex_unlock(mutex)
37 #define ASSERT_LOCK_HELD(mutex) /* nothing */
38
39 #elif defined(DEBUG) && defined(linux_HOST_OS)
40 #include <errno.h>
41 /* 
42  * On Linux, we can use extensions to determine whether we already
43  * hold a lock or not, which is useful for debugging.
44  */
45 #define ACQUIRE_LOCK(mutex) \
46   if (pthread_mutex_lock(mutex) == EDEADLK) { \
47     barf("multiple ACQUIRE_LOCK: %s %d", __FILE__,__LINE__); \
48   }
49 #define RELEASE_LOCK(mutex) \
50   if (pthread_mutex_unlock(mutex) != 0) { \
51     barf("RELEASE_LOCK: I do not own this lock: %s %d", __FILE__,__LINE__); \
52   }
53
54 #define ASSERT_LOCK_HELD(mutex) ASSERT(pthread_mutex_lock(mutex) == EDEADLK)
55
56 #define ASSERT_LOCK_NOTHELD(mutex)              \
57   if (pthread_mutex_lock(mutex) != EDEADLK) {   \
58      pthread_mutex_unlock(mutex);               \
59   } else {                                      \
60     ASSERT(0);                                  \
61   }
62
63
64 #else
65
66 #define ACQUIRE_LOCK(mutex) pthread_mutex_lock(mutex)
67 #define RELEASE_LOCK(mutex) pthread_mutex_unlock(mutex)
68 #define ASSERT_LOCK_HELD(mutex) /* nothing */
69
70 #endif
71
72 # elif defined(HAVE_WINDOWS_H)
73 #include <windows.h>
74
75 typedef HANDLE Condition;
76 typedef HANDLE Mutex;
77 typedef DWORD OSThreadId;
78 typedef DWORD ThreadLocalKey;
79
80 #define OSThreadProcAttr __stdcall
81
82 #define INIT_MUTEX_VAR 0
83 #define INIT_COND_VAR  0
84
85 // casting to (Mutex *) here required due to use in .cmm files where
86 // the argument has (void *) type.
87 #define ACQUIRE_LOCK(mutex)                                     \
88     if (WaitForSingleObject(*((Mutex *)mutex),INFINITE) == WAIT_FAILED) { \
89         barf("WaitForSingleObject: %d", GetLastError());        \
90     }
91
92 #define RELEASE_LOCK(mutex)                             \
93     if (ReleaseMutex(*((Mutex *)mutex)) == 0) {         \
94         barf("ReleaseMutex: %d", GetLastError());       \
95     }
96
97 #define ASSERT_LOCK_HELD(mutex) /* nothing */
98
99 # else
100 #  error "Threads not supported"
101 # endif
102
103 //
104 // General thread operations
105 //
106 extern OSThreadId osThreadId      ( void );
107 extern void shutdownThread        ( void );
108 extern void yieldThread           ( void );
109
110 typedef void OSThreadProcAttr OSThreadProc(void *);
111
112 extern int  createOSThread        ( OSThreadId* tid, 
113                                     OSThreadProc *startProc, void *param);
114
115 //
116 // Condition Variables
117 //
118 extern void initCondition         ( Condition* pCond );
119 extern void closeCondition        ( Condition* pCond );
120 extern rtsBool broadcastCondition ( Condition* pCond );
121 extern rtsBool signalCondition    ( Condition* pCond );
122 extern rtsBool waitCondition      ( Condition* pCond, 
123                                     Mutex* pMut );
124
125 //
126 // Mutexes
127 //
128 extern void initMutex             ( Mutex* pMut );
129
130 //
131 // Thread-local storage
132 //
133 void  newThreadLocalKey (ThreadLocalKey *key);
134 void *getThreadLocalVar (ThreadLocalKey *key);
135 void  setThreadLocalVar (ThreadLocalKey *key, void *value);
136
137 #else
138
139 #define ACQUIRE_LOCK(l)
140 #define RELEASE_LOCK(l)
141 #define ASSERT_LOCK_HELD(l)
142
143 #endif /* defined(RTS_SUPPORTS_THREADS) */
144
145 #endif /* __OSTHREADS_H__ */