1 /*
2  *                       Copyright 2004-2008
3  *                    Green Hills Software, Inc.
4  *
5  *    This program is the property of Green Hills Software, Inc,
6  *    its contents are proprietary information and no part of it
7  *    is to be disclosed to anyone except employees of Green Hills
8  *    Software, Inc., or as agreed in writing signed by the President
9  *    of Green Hills Software, Inc.
10  *
11  */
12 
13 #if 1 // CAFE MOD
14 #define __Declare_Initialization_Routines__ 1
15 #include <string.h>
16 #include <cafe/os.h>
17 #endif // CAFE MOD
18 
19 #include "ind_thrd.h"
20 #include <stddef.h>
21 #include <setjmp.h>
22 
23 #pragma weak __cpp_exception_init
24 extern void __cpp_exception_init(void **);
25 #pragma weak __cpp_exception_cleanup
26 extern void __cpp_exception_cleanup(void **);
27 
28 /*
29   Thread-Local Library Data Retrieval
30   ===================================
31 
32   ThreadLocalStorage is a structure that contains all static library data
33   that the Green Hills libraries allow to be allocated per-thread. To
34   configure the libraries to allow the maximum amount of thread safety,
35   the contents of this structure must be allocated for each thread
36   and __ghs_GetThreadLocalStorageItem must return the specified
37   thread-specific library data when called.
38 
39   An implementation can choose which of these data structures to allocate
40   for each thread. For example, an implementation may choose to
41   allocate an errno value for each thread, but not the strtok_saved_pos
42   pointer. The application could then use strtok_r instead of strtok for
43   thread-safety.
44 
45   If C++ with exceptions is being used, the __eh_globals entry must be
46   allocated for each thread.
47 
48   If __ghs_GetThreadLocalStorageItem is customized to
49   return a per-thread errno value, define the preprocessor symbol
50   USE_THREAD_LOCAL_ERRNO in ind_errn.c.
51 
52 */
53 
54 /* Provide global __eh_globals value to support C++ exception handling
55    in a single-threaded system.
56  */
57 
58 #if 0 // CAFE MOD
59 static void *__eh_globals;
60 #endif // CAFE MOD
61 
62 /* __ghs_GetThreadLocalStorageItem returns pointers to various
63    per-thread library data.
64 
65    Return NULL for any per-thread data item not implemented. A global
66    value will be used.
67 
68    Exception: The default implementation of C++ Exception Handling
69    support defined below depends on this function using a global
70    __eh_globals value if a per-thread value is not implemented.
71 */
72 #pragma ghs startnomisra
73 
74 #if 0 // CAFE GHS ORIG
75 void *__ghs_GetThreadLocalStorageItem(int specifier)
76 {
77     void *ptlsitem = 0;
78     switch (specifier) {
79 	case (int)__ghs_TLS_Errno:
80 	    /* Set ptslsitem to the address of the per-thread errno value.
81 	       The per-thread errno value should have the type int.
82 
83 	       If returning a per-thread errno value, define the
84 	       preprocessor symbol USE_THREAD_LOCAL_ERRNO in ind_errn.c.
85 
86 	       This item is used by numerous library functions.
87 	    */
88 	    break;
89 	case (int)__ghs_TLS_SignalHandlers:
90 	    /* Set ptslsitem to the address of the per-thread SignalHandlers
91 	       array. The per-thread SignalHandlers array should have the
92 	       array type as in the following declaration:
93 	       SignalHandler SignalHandlers[_SIGMAX];
94 	       The SignalHandler type is defined in ind_thrd.h and
95 	       the _SIGMAX constant is defined in signal.h.
96 
97 	       This item is used by the library functions signal() and
98 	       raise().
99 
100 	       If you provide a per-thread SignalHandlers array, the entries
101 	       must be initialized properly before use. See
102 	       __gh_signal_init() in ind_thrd.c for an example of how this
103 	       can be done.
104 	    */
105 	    break;
106 	case (int)__ghs_TLS_asctime_buff:
107 	    /* Set ptslsitem to the address of the per-thread asctime_buff
108 	       array. The per-thread asctime_buff array should have the
109 	       array type as in the following declaration:
110 	       char asctime_buff[30];
111 
112 	       This item is used by the library functions asctime() and
113 	       ctime(). The library provides asctime_r() and ctime_r(),
114 	       inherently thread-safe versions of these functions.
115 	    */
116 	    break;
117 	case (int)__ghs_TLS_tmpnam_space:
118 	    /* Set ptslsitem to the address of the per-thread tmpnam_space
119 	       array. The per-thread tmpnam_space array should have the
120 	       array type as in the following declaration:
121 	       char tmpnam_space[L_tmpnam];
122 	       The constant is defined in <stdio.h>
123 
124 	       This item is used by the library function tmpnam() when
125 	       passed NULL. The library provides tmpnam_r(), an
126 	       inherently thread-safe version of tmpnam().
127 	    */
128 	    break;
129 	case (int)__ghs_TLS_strtok_saved_pos:
130 	    /* Set ptslsitem to the address of the per-thread
131 	       strtok_saved_pos pointer. The per-thread strtok_saved_pos
132 	       pointer should have the type "char *".
133 
134 	       This item is used by the library function strtok().
135 	       The library provides strtok_r(), an inherently thread-safe
136 	       version of strtok().
137 	    */
138 	    break;
139 	case (int)__ghs_TLS_gmtime_temp:
140 	    /* Set ptslsitem to the address of the per-thread gmtime_temp
141 	       value. The per-thread gmtime_temp value should have the
142 	       type "struct tm" defined in time.h, included by indos.h.
143 
144 	       This item is used by the library functions gmtime() and
145 	       localtime(). The library provides gmtime_r() and
146 	       localtime_r(), inherently thread-safe versions of these
147 	       functions.
148 	    */
149 	    break;
150 	case (int)__ghs_TLS___eh_globals:
151 	    /* Set ptslsitem to the address of the per-thread __eh_globals
152 	       value. The per-thread __eh_globals value should have the
153 	       type "void *".
154 
155 	       This item is used by C++ exception handling.
156 
157 	       The default implementation of C++ exception handling
158 	       support defined below requires that the address of the
159 	       global __eh_globals, and not NULL, be returned here.
160 	    */
161 	    ptlsitem = (void *)&__eh_globals;
162 	    break;
163 
164         case (int)__ghs_TLS__eh_mem_manage:
165 	    /* Set ptlsitem to the address of the per-thread exception
166 	       stack memory manager. The exception stack memory manager
167 	       should be an array of 9 void *s. If not set, the memory
168 	       will be requested via malloc().
169 	     */
170 	    break;
171         case (int)__ghs_TLS__eh_store_globals:
172 	    /* Set ptlsitem to the address of the per-thread exception
173 	       stack state. This variable should be an array of 6 void *s.
174 	       If not set, the memory will be requested via malloc().
175 	     */
176 	    break;
177         case (int)__ghs_TLS__eh_store_globals_tdeh:
178 	    /* Set ptlsitem to the address of the per-thread exception
179 	       stack state used only with TDEH. This variable should
180 	       be an array of 76 void *s. If not set, the memory will
181 	       be requested via malloc().
182 	       Only one of __ghs_TLS__eh_store_globals and
183 	       __ghs_TLS__eh_store_globals_tdeh will be used based
184 	       on the exception handling method used in the program.
185 	     */
186 	    break;
187         case (int)__ghs_TLS__eh_init_block:
188 	    /* Set ptlsitem to an initial per-thread pool of memory
189 	       used to allocate entries on the exception stack. The
190 	       initial pool returned here should be an array of 2048
191 	       void *s. If this is not enough, the runtime will allocate
192 	       more pools from the heap using malloc.
193 	       If not set, the memory will be requested via malloc().
194 	     */
195 	    break;
196 
197 	default:
198             /* Return NULL for any unknown per-thread data item to
199                cause a global value to be used.
200              */
201 	    break;
202     }
203     return ptlsitem;
204 }
205 #endif // CAFE GHS ORIG
206 
207 #if 1 // CAFE MOD
__ghs_GetThreadLocalStorageItem(int specifier)208 void *__ghs_GetThreadLocalStorageItem(int specifier)
209 {
210     OSThread *pThread = OSGetCurrentThread();
211 
212     void *ptlsitem = (void *)0;
213     switch (specifier) {
214 	case (int)__ghs_TLS_Errno:
215 	    /* Set ptslsitem to the address of the per-thread errno value.
216 	       The per-thread errno value should have the type int.
217 
218 	       If returning a per-thread errno value, define the
219 	       preprocessor symbol USE_THREAD_LOCAL_ERRNO in ind_errn.c.
220 
221 	       This item is used by numerous library functions.
222 	    */
223 	    ptlsitem = &pThread->context.error;
224 	    break;
225 	case (int)__ghs_TLS_SignalHandlers:
226 	    /* Set ptslsitem to the address of the per-thread SignalHandlers
227 	       array. The per-thread SignalHandlers array should have the
228 	       array type as in the following declaration:
229 	       SignalHandler SignalHandlers[_SIGMAX];
230 	       The SignalHandler type is defined in ind_thrd.h and
231 	       the _SIGMAX constant is defined in signal.h.
232 
233 	       This item is used by the library functions signal() and
234 	       raise().
235 
236 	       If you provide a per-thread SignalHandlers array, the entries
237 	       must be initialized properly before use. See
238 	       __gh_signal_init() in ind_thrd.c for an example of how this
239 	       can be done.
240 	    */
241 	    /* n/a - return null */
242 	    break;
243 	case (int)__ghs_TLS_asctime_buff:
244 	    /* Set ptslsitem to the address of the per-thread asctime_buff
245 	       array. The per-thread asctime_buff array should have the
246 	       array type as in the following declaration:
247 	       char asctime_buff[30];
248 
249 	       This item is used by the library functions asctime() and
250 	       ctime(). The library provides asctime_r() and ctime_r(),
251 	       inherently thread-safe versions of these functions.
252 	    */
253 	    ptlsitem = &pThread->crt.asctime_buff;
254 	    break;
255 	case (int)__ghs_TLS_tmpnam_space:
256 	    /* Set ptslsitem to the address of the per-thread tmpnam_space
257 	       array. The per-thread tmpnam_space array should have the
258 	       array type as in the following declaration:
259 	       char tmpnam_space[L_tmpnam];
260 	       The constant is defined in <stdio.h>
261 
262 	       This item is used by the library function tmpnam() when
263 	       passed NULL. The library provides tmpnam_r(), an
264 	       inherently thread-safe version of tmpnam().
265 	    */
266 	    ptlsitem = &pThread->crt.tmpnam_space;
267 	    break;
268 	case (int)__ghs_TLS_strtok_saved_pos:
269 	    /* Set ptslsitem to the address of the per-thread
270 	       strtok_saved_pos pointer. The per-thread strtok_saved_pos
271 	       pointer should have the type "char *".
272 
273 	       This item is used by the library function strtok().
274 	       The library provides strtok_r(), an inherently thread-safe
275 	       version of strtok().
276 	    */
277 	    ptlsitem = &pThread->crt.strtok_saved_pos;
278 	    break;
279 	case (int)__ghs_TLS_gmtime_temp:
280 	    /* Set ptslsitem to the address of the per-thread gmtime_temp
281 	       value. The per-thread gmtime_temp value should have the
282 	       type "struct tm" defined in time.h, included by indos.h.
283 
284 	       This item is used by the library functions gmtime() and
285 	       localtime(). The library provides gmtime_r() and
286 	       localtime_r(), inherently thread-safe versions of these
287 	       functions.
288 	    */
289 	    ptlsitem = &pThread->crt.gmtime_temp;
290 	    break;
291 	case (int)__ghs_TLS___eh_globals:
292 	    /* Set ptslsitem to the address of the per-thread __eh_globals
293 	       value. The per-thread __eh_globals value should have the
294 	       type "void *".
295 
296 	       This item is used by C++ exception handling.
297 
298 	       The default implementation of C++ exception handling
299 	       support defined below requires that the address of the
300 	       global __eh_globals, and not NULL, be returned here.
301 	    */
302 	    ptlsitem = &pThread->crt.__eh_globals;
303 	    break;
304 
305         case (int)__ghs_TLS__eh_mem_manage:
306 	    /* Set ptlsitem to the address of the per-thread exception
307 	       stack memory manager. The exception stack memory manager
308 	       should be an array of 9 void *s. If not set, the memory
309 	       will be requested via malloc().
310 	     */
311 	    ptlsitem = &pThread->crt.__eh_mem_manage;
312 	    break;
313         case (int)__ghs_TLS__eh_store_globals:
314 	    /* Set ptlsitem to the address of the per-thread exception
315 	       stack state. This variable should be an array of 6 void *s.
316 	       If not set, the memory will be requested via malloc().
317 	     */
318 	    ptlsitem = &pThread->crt.__eh_store_globals;
319 	    break;
320         case (int)__ghs_TLS__eh_store_globals_tdeh:
321 	    /* Set ptlsitem to the address of the per-thread exception
322 	       stack state used only with TDEH. This variable should
323 	       be an array of 76 void *s. If not set, the memory will
324 	       be requested via malloc().
325 	       Only one of __ghs_TLS__eh_store_globals and
326 	       __ghs_TLS__eh_store_globals_tdeh will be used based
327 	       on the exception handling method used in the program.
328 	     */
329 	    ptlsitem = &pThread->crt.__eh_store_globals_tdeh;
330 	    break;
331         case (int)__ghs_TLS__eh_init_block:
332 	    /* Set ptlsitem to an initial per-thread pool of memory
333 	       used to allocate entries on the exception stack. The
334 	       initial pool returned here should be an array of 2048
335 	       void *s. If this is not enough, the runtime will allocate
336 	       more pools from the heap using malloc.
337 	       If not set, the memory will be requested via malloc().
338 	     */
339 	    ptlsitem = NULL; // &pThread->crt.__eh_init_block;
340 	    break;
341 
342 	default:
343             /* Return NULL for any unknown per-thread data item to
344                cause a global value to be used.
345              */
346 	    break;
347     }
348     return ptlsitem;
349 }
350 #endif // CAFE MOD
351 
352 #pragma ghs endnomisra
353 
354 /*
355   Saving State Across setjmp() Calls
356   ==================================
357 
358   These routines can be used to save and restore arbitrary state
359   across calls to setjmp() and longjmp().
360 */
__ghs_SaveSignalContext(jmp_buf jmpbuf)361 int __ghs_SaveSignalContext(jmp_buf jmpbuf)
362 {
363     return 0;
364 }
365 
366 /* Restore arbitrary state across a longjmp() */
__ghs_RestoreSignalContext(jmp_buf jmpbuf)367 void __ghs_RestoreSignalContext(jmp_buf jmpbuf)
368 {
369 }
370 
371 /*
372   C++ Exception Handling
373   ======================
374 
375   These routines allow C++ exceptions to be used in multiple threads.
376   The default implementation uses __ghs_GetThreadLocalStorageItem
377   to return a thread-specific __eh_globals pointer.
378 
379 */
380 #ifndef __disable_thread_safe_extensions
381 #if 0 // move to OSThread.c
382 /* Must be called after __cpp_except_init() is called to allocate
383  * and initialize the per-thread exception handling structure */
384 void *__get_eh_globals(void)
385 {
386     return *(void **)__ghs_GetThreadLocalStorageItem(__ghs_TLS___eh_globals);
387 }
388 
389 void *__get_eh_init_block(void)
390 {
391     return __ghs_GetThreadLocalStorageItem(__ghs_TLS__eh_init_block);
392 }
393 
394 void *__get_eh_store_globals(void)
395 {
396     return __ghs_GetThreadLocalStorageItem(__ghs_TLS__eh_store_globals);
397 }
398 
399 void *__get_eh_store_globals_tdeh(void)
400 {
401     return __ghs_GetThreadLocalStorageItem(__ghs_TLS__eh_store_globals_tdeh);
402 }
403 
404 void *__get_eh_mem_manage(void)
405 {
406     return __ghs_GetThreadLocalStorageItem(__ghs_TLS__eh_mem_manage);
407 }
408 #endif // move to OSThread.c
409 
410 /* __ghs_cpp_exception_init retrieves the eh_globals field from
411    thread-local storage and calls __cpp_exception_init to avoid
412    having all thread-local storage routines linked into minimal
413    programs.
414 
415    This function is pulled in by the C++ library when exceptions
416    are enabled because __get_eh_globals (above) is referenced.
417  */
418 
419 #if 0 // CAFE GHS ORIG
420 void __ghs_cpp_exception_init(void) {
421     void *eh_globals;
422     if(__cpp_exception_init) {
423 	eh_globals = __ghs_GetThreadLocalStorageItem(__ghs_TLS___eh_globals);
424 	__cpp_exception_init(eh_globals);
425     }
426 }
427 #endif // CAFE GHS ORIG
428 
429 #if 1 // CAFE MOD
__ghs_cpp_exception_init(void)430 void __ghs_cpp_exception_init(void) {
431     void *eh_globals;
432     if(__cpp_exception_init) {
433         __cpp_exception_init_ptr = __cpp_exception_init;
434         __cpp_exception_cleanup_ptr = __cpp_exception_cleanup;
435 	    eh_globals = __ghs_GetThreadLocalStorageItem(__ghs_TLS___eh_globals);
436 	    __cpp_exception_init(eh_globals);
437     }
438 }
439 #endif // CAFE MOD
440 
441 /* __ghs_cpp_exception_cleanup retrieves the eh_globals field from
442    thread-local storage and calls __cpp_exception_cleanup to avoid
443    having all thread-local storage routines linked into minimal
444    programs.
445 
446    This function is pulled in by the C++ library when exceptions
447    are enabled because __get_eh_globals (above) is referenced.
448  */
__ghs_cpp_exception_cleanup(void)449 void __ghs_cpp_exception_cleanup(void) {
450     void *eh_globals;
451     if(__cpp_exception_cleanup) {
452 	eh_globals = __ghs_GetThreadLocalStorageItem(__ghs_TLS___eh_globals);
453 	__cpp_exception_cleanup(eh_globals);
454     }
455 }
456 
457 #endif /* __disable_thread_safe_extensions */
458 
459 /*
460   File Locks
461   ======================
462 
463   These routines can be customized to implement per-file locks to allow
464   thread-safe I/O.
465 
466 */
467 
468 #if 0 // CAFE GHS ORIG
469 /* Acquire lock for FILE *addr */
470 void __ghs_flock_file(void *addr) {}
471 
472 /* Release lock for FILE *addr */
473 void __ghs_funlock_file(void *addr) {}
474 
475 /* Non blocking acquire lock for FILE *addr.  May return -1 if */
476 /* this cannot be implemented. Returns 0 on success and nonzero. */
477 int __ghs_ftrylock_file(void *addr) { return -1; }
478 
479 /* Callbacks to initialize local lock data structures before they */
480 /* are used. */
481 void __ghs_flock_create(void **addr) {}
482 void __ghs_flock_destroy(void *addr) {}
483 #endif // CAFE GHS ORIG
484