Add getNumberOfProcessors(), FIX MacOS X build problem (hopefully)
[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 #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     pthread_mutexattr_settype(&attr,PTHREAD_MUTEX_ERRORCHECK);
111     pthread_mutex_init(pMut,&attr);
112 #else
113     pthread_mutex_init(pMut,NULL);
114 #endif
115     return;
116 }
117 void
118 closeMutex(Mutex* pMut)
119 {
120     pthread_mutex_destroy(pMut);
121 }
122
123 void
124 newThreadLocalKey (ThreadLocalKey *key)
125 {
126     int r;
127     if ((r = pthread_key_create(key, NULL)) != 0) {
128         barf("newThreadLocalKey: %s", strerror(r));
129     }
130 }
131
132 void *
133 getThreadLocalVar (ThreadLocalKey *key)
134 {
135     return pthread_getspecific(*key);
136     // Note: a return value of NULL can indicate that either the key
137     // is not valid, or the key is valid and the data value has not
138     // yet been set.  We need to use the latter case, so we cannot
139     // detect errors here.
140 }
141
142 void
143 setThreadLocalVar (ThreadLocalKey *key, void *value)
144 {
145     int r;
146     if ((r = pthread_setspecific(*key,value)) != 0) {
147         barf("setThreadLocalVar: %s", strerror(r));
148     }
149 }
150
151 void
152 freeThreadLocalKey (ThreadLocalKey *key)
153 {
154     int r;
155     if ((r = pthread_key_delete(*key)) != 0) {
156         barf("freeThreadLocalKey: %s", strerror(r));
157     }
158 }
159
160 static void *
161 forkOS_createThreadWrapper ( void * entry )
162 {
163     Capability *cap;
164     cap = rts_lock();
165     cap = rts_evalStableIO(cap, (HsStablePtr) entry, NULL);
166     taskTimeStamp(myTask());
167     rts_unlock(cap);
168     return NULL;
169 }
170
171 int
172 forkOS_createThread ( HsStablePtr entry )
173 {
174     pthread_t tid;
175     int result = pthread_create(&tid, NULL,
176                                 forkOS_createThreadWrapper, (void*)entry);
177     if(!result)
178         pthread_detach(tid);
179     return result;
180 }
181
182 nat
183 getNumberOfProcessors (void)
184 {
185     static nat nproc = 0;
186
187     if (nproc == 0) {
188 #if defined(HAVE_SYSCONF) && defined(_SC_NPROCESSORS_ONLN)
189         nproc = sysconf(_SC_NPROCESSORS_ONLN);
190 #elif defined(HAVE_SYSCONF) && defined(_SC_NPROCESSORS_CONF)
191         nproc = sysconf(_SC_NPROCESSORS_CONF);
192 #else
193         nproc = 1;
194 #endif
195     }
196
197     return nproc;
198 }
199
200 #else /* !defined(THREADED_RTS) */
201
202 int
203 forkOS_createThread ( HsStablePtr entry STG_UNUSED )
204 {
205     return -1;
206 }
207
208 #endif /* !defined(THREADED_RTS) */