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