Reorganisation of the source tree
[ghc-hetmet.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
20 #if HAVE_STRING_H
21 #include <string.h>
22 #endif
23
24 #if !defined(HAVE_PTHREAD_H)
25 #error pthreads.h is required for the threaded RTS on Posix platforms
26 #endif
27
28 /*
29  * This (allegedly) OS threads independent layer was initially
30  * abstracted away from code that used Pthreads, so the functions
31  * provided here are mostly just wrappers to the Pthreads API.
32  *
33  */
34
35 void
36 initCondition( Condition* pCond )
37 {
38   pthread_cond_init(pCond, NULL);
39   return;
40 }
41
42 void
43 closeCondition( Condition* pCond )
44 {
45   pthread_cond_destroy(pCond);
46   return;
47 }
48
49 rtsBool
50 broadcastCondition ( Condition* pCond )
51 {
52   return (pthread_cond_broadcast(pCond) == 0);
53 }
54
55 rtsBool
56 signalCondition ( Condition* pCond )
57 {
58   return (pthread_cond_signal(pCond) == 0);
59 }
60
61 rtsBool
62 waitCondition ( Condition* pCond, Mutex* pMut )
63 {
64   return (pthread_cond_wait(pCond,pMut) == 0);
65 }
66
67 void
68 yieldThread()
69 {
70   sched_yield();
71   return;
72 }
73
74 void
75 shutdownThread()
76 {
77   pthread_exit(NULL);
78 }
79
80 int
81 createOSThread (OSThreadId* pId, OSThreadProc *startProc, void *param)
82 {
83   int result = pthread_create(pId, NULL, (void *(*)(void *))startProc, param);
84   if(!result)
85     pthread_detach(*pId);
86   return result;
87 }
88
89 OSThreadId
90 osThreadId()
91 {
92   return pthread_self();
93 }
94
95 void
96 initMutex(Mutex* pMut)
97 {
98 #if defined(DEBUG) && defined(linux_HOST_OS)
99     pthread_mutexattr_t attr;
100     pthread_mutexattr_init(&attr);
101     pthread_mutexattr_settype(&attr,PTHREAD_MUTEX_ERRORCHECK_NP);
102     pthread_mutex_init(pMut,&attr);
103 #else
104     pthread_mutex_init(pMut,NULL);
105 #endif
106     return;
107 }
108
109 void
110 newThreadLocalKey (ThreadLocalKey *key)
111 {
112     int r;
113     if ((r = pthread_key_create(key, NULL)) != 0) {
114         barf("newThreadLocalKey: %s", strerror(r));
115     }
116 }
117
118 void *
119 getThreadLocalVar (ThreadLocalKey *key)
120 {
121     return pthread_getspecific(*key);
122     // Note: a return value of NULL can indicate that either the key
123     // is not valid, or the key is valid and the data value has not
124     // yet been set.  We need to use the latter case, so we cannot
125     // detect errors here.
126 }
127
128 void
129 setThreadLocalVar (ThreadLocalKey *key, void *value)
130 {
131     int r;
132     if ((r = pthread_setspecific(*key,value)) != 0) {
133         barf("setThreadLocalVar: %s", strerror(r));
134     }
135 }
136
137 static void *
138 forkOS_createThreadWrapper ( void * entry )
139 {
140     Capability *cap;
141     cap = rts_lock();
142     cap = rts_evalStableIO(cap, (HsStablePtr) entry, NULL);
143     rts_unlock(cap);
144     return NULL;
145 }
146
147 int
148 forkOS_createThread ( HsStablePtr entry )
149 {
150     pthread_t tid;
151     int result = pthread_create(&tid, NULL,
152                                 forkOS_createThreadWrapper, (void*)entry);
153     if(!result)
154         pthread_detach(tid);
155     return result;
156 }
157
158 #else /* !defined(THREADED_RTS) */
159
160 int
161 forkOS_createThread ( HsStablePtr entry STG_UNUSED )
162 {
163     return -1;
164 }
165
166 #endif /* !defined(THREADED_RTS) */