/* * Copyright 2004-2008 * Green Hills Software, Inc. * * This program is the property of Green Hills Software, Inc, * its contents are proprietary information and no part of it * is to be disclosed to anyone except employees of Green Hills * Software, Inc., or as agreed in writing signed by the President * of Green Hills Software, Inc. * */ #if 1 // CAFE MOD #define __Declare_Initialization_Routines__ 1 #include #include #endif // CAFE MOD #include "ind_thrd.h" #include #include #pragma weak __cpp_exception_init extern void __cpp_exception_init(void **); #pragma weak __cpp_exception_cleanup extern void __cpp_exception_cleanup(void **); /* Thread-Local Library Data Retrieval =================================== ThreadLocalStorage is a structure that contains all static library data that the Green Hills libraries allow to be allocated per-thread. To configure the libraries to allow the maximum amount of thread safety, the contents of this structure must be allocated for each thread and __ghs_GetThreadLocalStorageItem must return the specified thread-specific library data when called. An implementation can choose which of these data structures to allocate for each thread. For example, an implementation may choose to allocate an errno value for each thread, but not the strtok_saved_pos pointer. The application could then use strtok_r instead of strtok for thread-safety. If C++ with exceptions is being used, the __eh_globals entry must be allocated for each thread. If __ghs_GetThreadLocalStorageItem is customized to return a per-thread errno value, define the preprocessor symbol USE_THREAD_LOCAL_ERRNO in ind_errn.c. */ /* Provide global __eh_globals value to support C++ exception handling in a single-threaded system. */ #if 0 // CAFE MOD static void *__eh_globals; #endif // CAFE MOD /* __ghs_GetThreadLocalStorageItem returns pointers to various per-thread library data. Return NULL for any per-thread data item not implemented. A global value will be used. Exception: The default implementation of C++ Exception Handling support defined below depends on this function using a global __eh_globals value if a per-thread value is not implemented. */ #pragma ghs startnomisra #if 0 // CAFE GHS ORIG void *__ghs_GetThreadLocalStorageItem(int specifier) { void *ptlsitem = 0; switch (specifier) { case (int)__ghs_TLS_Errno: /* Set ptslsitem to the address of the per-thread errno value. The per-thread errno value should have the type int. If returning a per-thread errno value, define the preprocessor symbol USE_THREAD_LOCAL_ERRNO in ind_errn.c. This item is used by numerous library functions. */ break; case (int)__ghs_TLS_SignalHandlers: /* Set ptslsitem to the address of the per-thread SignalHandlers array. The per-thread SignalHandlers array should have the array type as in the following declaration: SignalHandler SignalHandlers[_SIGMAX]; The SignalHandler type is defined in ind_thrd.h and the _SIGMAX constant is defined in signal.h. This item is used by the library functions signal() and raise(). If you provide a per-thread SignalHandlers array, the entries must be initialized properly before use. See __gh_signal_init() in ind_thrd.c for an example of how this can be done. */ break; case (int)__ghs_TLS_asctime_buff: /* Set ptslsitem to the address of the per-thread asctime_buff array. The per-thread asctime_buff array should have the array type as in the following declaration: char asctime_buff[30]; This item is used by the library functions asctime() and ctime(). The library provides asctime_r() and ctime_r(), inherently thread-safe versions of these functions. */ break; case (int)__ghs_TLS_tmpnam_space: /* Set ptslsitem to the address of the per-thread tmpnam_space array. The per-thread tmpnam_space array should have the array type as in the following declaration: char tmpnam_space[L_tmpnam]; The constant is defined in This item is used by the library function tmpnam() when passed NULL. The library provides tmpnam_r(), an inherently thread-safe version of tmpnam(). */ break; case (int)__ghs_TLS_strtok_saved_pos: /* Set ptslsitem to the address of the per-thread strtok_saved_pos pointer. The per-thread strtok_saved_pos pointer should have the type "char *". This item is used by the library function strtok(). The library provides strtok_r(), an inherently thread-safe version of strtok(). */ break; case (int)__ghs_TLS_gmtime_temp: /* Set ptslsitem to the address of the per-thread gmtime_temp value. The per-thread gmtime_temp value should have the type "struct tm" defined in time.h, included by indos.h. This item is used by the library functions gmtime() and localtime(). The library provides gmtime_r() and localtime_r(), inherently thread-safe versions of these functions. */ break; case (int)__ghs_TLS___eh_globals: /* Set ptslsitem to the address of the per-thread __eh_globals value. The per-thread __eh_globals value should have the type "void *". This item is used by C++ exception handling. The default implementation of C++ exception handling support defined below requires that the address of the global __eh_globals, and not NULL, be returned here. */ ptlsitem = (void *)&__eh_globals; break; case (int)__ghs_TLS__eh_mem_manage: /* Set ptlsitem to the address of the per-thread exception stack memory manager. The exception stack memory manager should be an array of 9 void *s. If not set, the memory will be requested via malloc(). */ break; case (int)__ghs_TLS__eh_store_globals: /* Set ptlsitem to the address of the per-thread exception stack state. This variable should be an array of 6 void *s. If not set, the memory will be requested via malloc(). */ break; case (int)__ghs_TLS__eh_store_globals_tdeh: /* Set ptlsitem to the address of the per-thread exception stack state used only with TDEH. This variable should be an array of 76 void *s. If not set, the memory will be requested via malloc(). Only one of __ghs_TLS__eh_store_globals and __ghs_TLS__eh_store_globals_tdeh will be used based on the exception handling method used in the program. */ break; case (int)__ghs_TLS__eh_init_block: /* Set ptlsitem to an initial per-thread pool of memory used to allocate entries on the exception stack. The initial pool returned here should be an array of 2048 void *s. If this is not enough, the runtime will allocate more pools from the heap using malloc. If not set, the memory will be requested via malloc(). */ break; default: /* Return NULL for any unknown per-thread data item to cause a global value to be used. */ break; } return ptlsitem; } #endif // CAFE GHS ORIG #if 1 // CAFE MOD void *__ghs_GetThreadLocalStorageItem(int specifier) { OSThread *pThread = OSGetCurrentThread(); void *ptlsitem = (void *)0; switch (specifier) { case (int)__ghs_TLS_Errno: /* Set ptslsitem to the address of the per-thread errno value. The per-thread errno value should have the type int. If returning a per-thread errno value, define the preprocessor symbol USE_THREAD_LOCAL_ERRNO in ind_errn.c. This item is used by numerous library functions. */ ptlsitem = &pThread->context.error; break; case (int)__ghs_TLS_SignalHandlers: /* Set ptslsitem to the address of the per-thread SignalHandlers array. The per-thread SignalHandlers array should have the array type as in the following declaration: SignalHandler SignalHandlers[_SIGMAX]; The SignalHandler type is defined in ind_thrd.h and the _SIGMAX constant is defined in signal.h. This item is used by the library functions signal() and raise(). If you provide a per-thread SignalHandlers array, the entries must be initialized properly before use. See __gh_signal_init() in ind_thrd.c for an example of how this can be done. */ /* n/a - return null */ break; case (int)__ghs_TLS_asctime_buff: /* Set ptslsitem to the address of the per-thread asctime_buff array. The per-thread asctime_buff array should have the array type as in the following declaration: char asctime_buff[30]; This item is used by the library functions asctime() and ctime(). The library provides asctime_r() and ctime_r(), inherently thread-safe versions of these functions. */ ptlsitem = &pThread->crt.asctime_buff; break; case (int)__ghs_TLS_tmpnam_space: /* Set ptslsitem to the address of the per-thread tmpnam_space array. The per-thread tmpnam_space array should have the array type as in the following declaration: char tmpnam_space[L_tmpnam]; The constant is defined in This item is used by the library function tmpnam() when passed NULL. The library provides tmpnam_r(), an inherently thread-safe version of tmpnam(). */ ptlsitem = &pThread->crt.tmpnam_space; break; case (int)__ghs_TLS_strtok_saved_pos: /* Set ptslsitem to the address of the per-thread strtok_saved_pos pointer. The per-thread strtok_saved_pos pointer should have the type "char *". This item is used by the library function strtok(). The library provides strtok_r(), an inherently thread-safe version of strtok(). */ ptlsitem = &pThread->crt.strtok_saved_pos; break; case (int)__ghs_TLS_gmtime_temp: /* Set ptslsitem to the address of the per-thread gmtime_temp value. The per-thread gmtime_temp value should have the type "struct tm" defined in time.h, included by indos.h. This item is used by the library functions gmtime() and localtime(). The library provides gmtime_r() and localtime_r(), inherently thread-safe versions of these functions. */ ptlsitem = &pThread->crt.gmtime_temp; break; case (int)__ghs_TLS___eh_globals: /* Set ptslsitem to the address of the per-thread __eh_globals value. The per-thread __eh_globals value should have the type "void *". This item is used by C++ exception handling. The default implementation of C++ exception handling support defined below requires that the address of the global __eh_globals, and not NULL, be returned here. */ ptlsitem = &pThread->crt.__eh_globals; break; case (int)__ghs_TLS__eh_mem_manage: /* Set ptlsitem to the address of the per-thread exception stack memory manager. The exception stack memory manager should be an array of 9 void *s. If not set, the memory will be requested via malloc(). */ ptlsitem = &pThread->crt.__eh_mem_manage; break; case (int)__ghs_TLS__eh_store_globals: /* Set ptlsitem to the address of the per-thread exception stack state. This variable should be an array of 6 void *s. If not set, the memory will be requested via malloc(). */ ptlsitem = &pThread->crt.__eh_store_globals; break; case (int)__ghs_TLS__eh_store_globals_tdeh: /* Set ptlsitem to the address of the per-thread exception stack state used only with TDEH. This variable should be an array of 76 void *s. If not set, the memory will be requested via malloc(). Only one of __ghs_TLS__eh_store_globals and __ghs_TLS__eh_store_globals_tdeh will be used based on the exception handling method used in the program. */ ptlsitem = &pThread->crt.__eh_store_globals_tdeh; break; case (int)__ghs_TLS__eh_init_block: /* Set ptlsitem to an initial per-thread pool of memory used to allocate entries on the exception stack. The initial pool returned here should be an array of 2048 void *s. If this is not enough, the runtime will allocate more pools from the heap using malloc. If not set, the memory will be requested via malloc(). */ ptlsitem = NULL; // &pThread->crt.__eh_init_block; break; default: /* Return NULL for any unknown per-thread data item to cause a global value to be used. */ break; } return ptlsitem; } #endif // CAFE MOD #pragma ghs endnomisra /* Saving State Across setjmp() Calls ================================== These routines can be used to save and restore arbitrary state across calls to setjmp() and longjmp(). */ int __ghs_SaveSignalContext(jmp_buf jmpbuf) { return 0; } /* Restore arbitrary state across a longjmp() */ void __ghs_RestoreSignalContext(jmp_buf jmpbuf) { } /* C++ Exception Handling ====================== These routines allow C++ exceptions to be used in multiple threads. The default implementation uses __ghs_GetThreadLocalStorageItem to return a thread-specific __eh_globals pointer. */ #ifndef __disable_thread_safe_extensions #if 0 // move to OSThread.c /* Must be called after __cpp_except_init() is called to allocate * and initialize the per-thread exception handling structure */ void *__get_eh_globals(void) { return *(void **)__ghs_GetThreadLocalStorageItem(__ghs_TLS___eh_globals); } void *__get_eh_init_block(void) { return __ghs_GetThreadLocalStorageItem(__ghs_TLS__eh_init_block); } void *__get_eh_store_globals(void) { return __ghs_GetThreadLocalStorageItem(__ghs_TLS__eh_store_globals); } void *__get_eh_store_globals_tdeh(void) { return __ghs_GetThreadLocalStorageItem(__ghs_TLS__eh_store_globals_tdeh); } void *__get_eh_mem_manage(void) { return __ghs_GetThreadLocalStorageItem(__ghs_TLS__eh_mem_manage); } #endif // move to OSThread.c /* __ghs_cpp_exception_init retrieves the eh_globals field from thread-local storage and calls __cpp_exception_init to avoid having all thread-local storage routines linked into minimal programs. This function is pulled in by the C++ library when exceptions are enabled because __get_eh_globals (above) is referenced. */ #if 0 // CAFE GHS ORIG void __ghs_cpp_exception_init(void) { void *eh_globals; if(__cpp_exception_init) { eh_globals = __ghs_GetThreadLocalStorageItem(__ghs_TLS___eh_globals); __cpp_exception_init(eh_globals); } } #endif // CAFE GHS ORIG #if 1 // CAFE MOD void __ghs_cpp_exception_init(void) { void *eh_globals; if(__cpp_exception_init) { __cpp_exception_init_ptr = __cpp_exception_init; __cpp_exception_cleanup_ptr = __cpp_exception_cleanup; eh_globals = __ghs_GetThreadLocalStorageItem(__ghs_TLS___eh_globals); __cpp_exception_init(eh_globals); } } #endif // CAFE MOD /* __ghs_cpp_exception_cleanup retrieves the eh_globals field from thread-local storage and calls __cpp_exception_cleanup to avoid having all thread-local storage routines linked into minimal programs. This function is pulled in by the C++ library when exceptions are enabled because __get_eh_globals (above) is referenced. */ void __ghs_cpp_exception_cleanup(void) { void *eh_globals; if(__cpp_exception_cleanup) { eh_globals = __ghs_GetThreadLocalStorageItem(__ghs_TLS___eh_globals); __cpp_exception_cleanup(eh_globals); } } #endif /* __disable_thread_safe_extensions */ /* File Locks ====================== These routines can be customized to implement per-file locks to allow thread-safe I/O. */ #if 0 // CAFE GHS ORIG /* Acquire lock for FILE *addr */ void __ghs_flock_file(void *addr) {} /* Release lock for FILE *addr */ void __ghs_funlock_file(void *addr) {} /* Non blocking acquire lock for FILE *addr. May return -1 if */ /* this cannot be implemented. Returns 0 on success and nonzero. */ int __ghs_ftrylock_file(void *addr) { return -1; } /* Callbacks to initialize local lock data structures before they */ /* are used. */ void __ghs_flock_create(void **addr) {} void __ghs_flock_destroy(void *addr) {} #endif // CAFE GHS ORIG