1 /*
2 C++ Library
3
4 Copyright 1983-2008 Green Hills Software,Inc.
5
6 This program is the property of Green Hills Software, Inc,
7 its contents are proprietary information and no part of it
8 is to be disclosed to anyone except employees of Green Hills
9 Software, Inc., or as agreed in writing signed by the President
10 of Green Hills Software, Inc.
11 */
12
13 /*
14 * Implementation of the C++ library locks
15 */
16
17 /* Take a lock specified by the parameter passed in. A thread can return from
18 * this function only if no other thread has called it with with the same
19 * value of 'i' without releasing the lock. Currently, the values of 'i' are
20 * in the range [0,2], inclusive. See 'yvals.h' in the ecxx, eecxx, scxx
21 * directories.
22 */
23
24 #if defined(__Chorus)
25
26 /*
27 * Chorus does not provide a recursive mutex which is required by
28 * the C++ libraries. We synthesize one here.
29 * DO NOT CHANGE THE ORDER OF ANY STATEMENTS in __ghs{Unl,L}ockCpp()
30 */
31
32 #include <sync/chMutex.h>
33 #include <exec/chExec.h>
34
35 struct RecursiveMutex {
36 KnMutex mutex;
37 KnThreadLid owner;
38 int count;
39 };
40
41 #define THREAD_ID_NIL (0)
42
43 struct RecursiveMutex theLocks[3] = {
44 { K_KNMUTEX_INITIALIZER, THREAD_ID_NIL, 0},
45 { K_KNMUTEX_INITIALIZER, THREAD_ID_NIL, 0},
46 { K_KNMUTEX_INITIALIZER, THREAD_ID_NIL, 0}
47 };
48
__ghsLockCpp(int i)49 void __ghsLockCpp(int i)
50 {
51 struct RecursiveMutex * rm = theLocks+i;
52 KnThreadLid myThreadId = threadSelf();
53
54 if(rm->owner==myThreadId) {
55 rm->count++;
56 } else {
57 mutexGet(&rm->mutex);
58 rm->owner = myThreadId;
59 rm->count = 1;
60 }
61 }
62
__ghsUnlockCpp(int i)63 void __ghsUnlockCpp(int i)
64 {
65 struct RecursiveMutex * rm = theLocks+i;
66 if(--(rm->count)==0) {
67 rm->owner = THREAD_ID_NIL;
68 mutexRel(&rm->mutex);
69 }
70 }
71
72 /* End __Chorus */
73 #elif defined(SOLARIS20) /* Solaris Native */
74 # define _REENTRANT
75 # include <thread.h>
76 # define MUTEX_INITIALIZER (0)
77 # define THREAD_ID_NIL (0)
78
79 struct RecursiveMutex {
80 mutex_t mutex;
81 thread_t owner;
82 int count;
83 } theLocks[3] = {
84 { MUTEX_INITIALIZER, THREAD_ID_NIL, 0},
85 { MUTEX_INITIALIZER, THREAD_ID_NIL, 0},
86 { MUTEX_INITIALIZER, THREAD_ID_NIL, 0}
87 };
88
89
__ghsLockCpp(int i)90 void __ghsLockCpp(int i)
91 {
92 struct RecursiveMutex * rm = theLocks+i;
93 thread_t myThreadId = thr_self();
94
95 if(rm->owner==myThreadId) {
96 rm->count++;
97 } else {
98 if(mutex_lock(&rm->mutex)==0) {
99 rm->owner = myThreadId;
100 rm->count = 1;
101 }
102 }
103 }
104
__ghsUnlockCpp(int i)105 void __ghsUnlockCpp(int i)
106 {
107 struct RecursiveMutex * rm = theLocks+i;
108 if(--(rm->count)==0) {
109 rm->owner = THREAD_ID_NIL;
110 mutex_unlock(&rm->mutex);
111 }
112 }
113
114 /* End Solaris Native */
115 #elif defined(__OSE)
116
117 #include "ose.h"
118 #include "ind_thrd.h"
119
120 /* we can't use plain OSE semaphores, as we need reentrant locks */
121 typedef struct ReentrantLock_struct {
122 SEMAPHORE mutex;
123 PROCESS owner;
124 int count; /* how many times has the same process entered */
125 } ReentrantLock;
126
127 #define PROC_ID_NIL (0)
128
129 #define LOCK_COUNT 3
130 ReentrantLock lock_r[LOCK_COUNT] = {
131 { {1, 0, 0}, PROC_ID_NIL, 1},
132 { {1, 0, 0}, PROC_ID_NIL, 1},
133 { {1, 0, 0}, PROC_ID_NIL, 1}
134 };
135
ose_lock_acquire(int i)136 static void ose_lock_acquire( int i ) {
137 PROCESS my_pid = current_process();
138 if ( lock_r[i].owner == my_pid ) {
139 ++lock_r[i].count;
140 } else {
141 wait_sem( & lock_r[i].mutex );
142 lock_r[i].owner = my_pid;
143 lock_r[i].count = 1;
144 }
145 }
146
ose_lock_release(int i)147 static void ose_lock_release( int i ) {
148 if ( --lock_r[i].count == 0 ) {
149 lock_r[i].owner = 0;
150 signal_sem( & lock_r[i].mutex );
151 }
152 }
153
__ghsLockCpp(int i)154 void __ghsLockCpp(int i)
155 {
156 if ( i < LOCK_COUNT )
157 ose_lock_acquire( i );
158 }
159
__ghsUnlockCpp(int i)160 void __ghsUnlockCpp(int i)
161 {
162 if (i < LOCK_COUNT )
163 ose_lock_release( i );
164 }
165 /* End OSE */
166
167 /* End LynxOS */
168 #elif defined(__LYNX)
169
170 /* The LynxOS docs and headers are elusive as to whether they offer */
171 /* a builtin recursive mutex or not, so be safe and synthesize */
172 /* one here. */
173 #include <st.h>
174 #include <sem.h>
175 # define THREAD_ID_NIL (0)
176
177 struct RecursiveMutex {
178 synch_struct mutex;
179 tid_t owner;
180 int count;
181 } theLocks[3] = {
182 { U_MUTEX_INITIALIZER, THREAD_ID_NIL, 0 },
183 { U_MUTEX_INITIALIZER, THREAD_ID_NIL, 0 },
184 { U_MUTEX_INITIALIZER, THREAD_ID_NIL, 0 }
185 };
186
__ghsLockCpp(int i)187 void __ghsLockCpp(int i)
188 {
189 struct RecursiveMutex * rm = theLocks+i;
190 tid_t my_id = getstid();
191
192 if(rm->owner==my_id) {
193 rm->count++;
194 } else {
195 if(mutex_enter(&rm->mutex, NULL)==0) {
196 rm->owner = my_id;
197 rm->count = 1;
198 }
199 }
200 }
201
__ghsUnlockCpp(int i)202 void __ghsUnlockCpp(int i)
203 {
204 struct RecursiveMutex * rm = theLocks+i;
205 if(--(rm->count)==0) {
206 rm->owner = THREAD_ID_NIL;
207 mutex_exit(&rm->mutex);
208 }
209 }
210
211 /* End LynxOS */
212 #elif defined(__LINUX)
213
214 #include <features.h>
215 #define __USE_GNU /* Do this to get access to the non-posix (*_NP) */
216 /* GNU extensions defined in pthreads.h */
217 #include <pthread.h>
218
219 static pthread_mutex_t theLocks[3] = {
220 PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP,
221 PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP,
222 PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
223 };
224
__ghsLockCpp(int i)225 void __ghsLockCpp(int i)
226 {
227 pthread_mutex_lock(&theLocks[i]);
228 }
229
__ghsUnlockCpp(int i)230 void __ghsUnlockCpp(int i)
231 {
232 pthread_mutex_unlock(&theLocks[i]);
233 }
234
235 /* End Linux */
236 #elif defined(_MC_EXEC)
237 /* Mercury libraries */
238 #include <pthread.h>
239
240 static pthread_mutex_t theLocks[3] = {
241 PTHREAD_MUTEX_INITIALIZER,
242 PTHREAD_MUTEX_INITIALIZER,
243 PTHREAD_MUTEX_INITIALIZER
244 };
245
__ghsLockCpp(int i)246 void __ghsLockCpp(int i)
247 {
248 pthread_mutex_lock(&theLocks[i]);
249 }
250
__ghsUnlockCpp(int i)251 void __ghsUnlockCpp(int i)
252 {
253 pthread_mutex_unlock(&theLocks[i]);
254 }
255
256 /* End Mercury */
257
258 /* Begin Win32 (multithreaded only) */
259 #elif defined(__windows)
260
261 #if !defined (_MT)
262
__ghsLockCpp(int i)263 void __ghsLockCpp(int i) { }
__ghsUnlockCpp(int i)264 void __ghsUnlockCpp(int i) { }
265
266 #else /* !defined(_MT) */
267
268
269 #include <stdlib.h>
270 #include <windows.h>
271 #include <winbase.h>
272
273 /* We need this typedef from xmtx.h */
274 typedef long _Once_t;
275
276 static CRITICAL_SECTION winLocks[3];
277 static _Once_t winOnce[3] = { 0, 0, 0 };
278
__ghsLockCpp(int i)279 void __ghsLockCpp(int i)
280 {
281 /* From Plauger src/pjp/c++/sxl/xmtx.c
282 This will initialize the critical section only once for each mutex. */
283 _Once_t *_Cntrl = winOnce+i;
284 _Once_t old;
285
286 if (*_Cntrl == 2)
287 ;
288 else if ((old = InterlockedExchange(_Cntrl, 1)) == 0)
289 { /* execute _Func, mark as executed */
290 InitializeCriticalSection(&winLocks[i]);
291 *_Cntrl = 2;
292 }
293 else if (old == 2)
294 *_Cntrl = 2;
295 else
296 while (*_Cntrl != 2)
297 Sleep(1);
298
299 EnterCriticalSection(winLocks+i);
300 }
301
__ghsUnlockCpp(int i)302 void __ghsUnlockCpp(int i)
303 {
304 LeaveCriticalSection(winLocks+i);
305 }
306
307 #endif /* !defined(_MT) */
308
309 /* End Win32 */
310 #else
311
312 #include "ind_thrd.h"
313
314 extern __ghs_cpp_locks[3];
315
__ghsLockCpp(int i)316 void __ghsLockCpp(int i)
317 {
318 OSLockMutex(&__ghs_cpp_locks[i]);
319 }
320
__ghsUnlockCpp(int i)321 void __ghsUnlockCpp(int i)
322 {
323 OSUnlockMutex(&__ghs_cpp_locks[i]);
324 }
325
326
327 #endif
328
329
330
331
332
333
334
335
336
337
338