Use error-checking mutexes on all platforms when DEBUG is on
[ghc.git] / rts / posix / OSThreads.c
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 #if defined(DEBUG) && defined(__linux__)
11 /* We want GNU extensions in DEBUG mode for mutex error checking */
12 #define _GNU_SOURCE
13 #endif
14
15 #include "Rts.h"
16 #if defined(THREADED_RTS)
17 #include "OSThreads.h"
18 #include "RtsUtils.h"
19 #include "Task.h"
20
21 #if HAVE_STRING_H
22 #include <string.h>
23 #endif
24
25 #if !defined(HAVE_PTHREAD_H)
26 #error pthreads.h is required for the threaded RTS on Posix platforms
27 #endif
28
29 /*
30 * This (allegedly) OS threads independent layer was initially
31 * abstracted away from code that used Pthreads, so the functions
32 * provided here are mostly just wrappers to the Pthreads API.
33 *
34 */
35
36 void
37 initCondition( Condition* pCond )
38 {
39 pthread_cond_init(pCond, NULL);
40 return;
41 }
42
43 void
44 closeCondition( Condition* pCond )
45 {
46 pthread_cond_destroy(pCond);
47 return;
48 }
49
50 rtsBool
51 broadcastCondition ( Condition* pCond )
52 {
53 return (pthread_cond_broadcast(pCond) == 0);
54 }
55
56 rtsBool
57 signalCondition ( Condition* pCond )
58 {
59 return (pthread_cond_signal(pCond) == 0);
60 }
61
62 rtsBool
63 waitCondition ( Condition* pCond, Mutex* pMut )
64 {
65 return (pthread_cond_wait(pCond,pMut) == 0);
66 }
67
68 void
69 yieldThread()
70 {
71 sched_yield();
72 return;
73 }
74
75 void
76 shutdownThread()
77 {
78 pthread_exit(NULL);
79 }
80
81 int
82 createOSThread (OSThreadId* pId, OSThreadProc *startProc, void *param)
83 {
84 int result = pthread_create(pId, NULL, (void *(*)(void *))startProc, param);
85 if(!result)
86 pthread_detach(*pId);
87 return result;
88 }
89
90 OSThreadId
91 osThreadId()
92 {
93 return pthread_self();
94 }
95
96 rtsBool
97 osThreadIsAlive(OSThreadId id STG_UNUSED)
98 {
99 // no good way to implement this on POSIX, AFAICT. Returning true
100 // is safe.
101 return rtsTrue;
102 }
103
104 void
105 initMutex(Mutex* pMut)
106 {
107 #if defined(DEBUG)
108 pthread_mutexattr_t attr;
109 pthread_mutexattr_init(&attr);
110 #if defined(linux_HOST_OS)
111 pthread_mutexattr_settype(&attr,PTHREAD_MUTEX_ERRORCHECK_NP);
112 #else
113 pthread_mutexattr_settype(&attr,PTHREAD_MUTEX_ERRORCHECK);
114 #endif
115 pthread_mutex_init(pMut,&attr);
116 #else
117 pthread_mutex_init(pMut,NULL);
118 #endif
119 return;
120 }
121 void
122 closeMutex(Mutex* pMut)
123 {
124 pthread_mutex_destroy(pMut);
125 }
126
127 void
128 newThreadLocalKey (ThreadLocalKey *key)
129 {
130 int r;
131 if ((r = pthread_key_create(key, NULL)) != 0) {
132 barf("newThreadLocalKey: %s", strerror(r));
133 }
134 }
135
136 void *
137 getThreadLocalVar (ThreadLocalKey *key)
138 {
139 return pthread_getspecific(*key);
140 // Note: a return value of NULL can indicate that either the key
141 // is not valid, or the key is valid and the data value has not
142 // yet been set. We need to use the latter case, so we cannot
143 // detect errors here.
144 }
145
146 void
147 setThreadLocalVar (ThreadLocalKey *key, void *value)
148 {
149 int r;
150 if ((r = pthread_setspecific(*key,value)) != 0) {
151 barf("setThreadLocalVar: %s", strerror(r));
152 }
153 }
154
155 void
156 freeThreadLocalKey (ThreadLocalKey *key)
157 {
158 int r;
159 if ((r = pthread_key_delete(*key)) != 0) {
160 barf("freeThreadLocalKey: %s", strerror(r));
161 }
162 }
163
164 static void *
165 forkOS_createThreadWrapper ( void * entry )
166 {
167 Capability *cap;
168 cap = rts_lock();
169 cap = rts_evalStableIO(cap, (HsStablePtr) entry, NULL);
170 taskTimeStamp(myTask());
171 rts_unlock(cap);
172 return NULL;
173 }
174
175 int
176 forkOS_createThread ( HsStablePtr entry )
177 {
178 pthread_t tid;
179 int result = pthread_create(&tid, NULL,
180 forkOS_createThreadWrapper, (void*)entry);
181 if(!result)
182 pthread_detach(tid);
183 return result;
184 }
185
186 #else /* !defined(THREADED_RTS) */
187
188 int
189 forkOS_createThread ( HsStablePtr entry STG_UNUSED )
190 {
191 return -1;
192 }
193
194 #endif /* !defined(THREADED_RTS) */