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