1e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#include "stlport_prefix.h" 2e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott 3e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#if defined(__unix) && defined(__GNUC__) 4e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott 5e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#ifdef __FreeBSD__ 6e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott# include <osreldate.h> 7e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#endif 8e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott 9e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#if (defined(__FreeBSD__) && (__FreeBSD_version < 503001)) || defined(__sun) || defined (__hpux) 10e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott/* Note: __cxa_finalize and __cxa_atexit present in libc in FreeBSD 5.3 */ 11e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott 12e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#include <stdlib.h> 13e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#include <stdio.h> 14e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#include <pthread.h> 15e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott 16e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott/* __asm__ (".symver " "__cxa_finalize" "," "__cxa_finalize" "@" "STLPORT_5_0_0"); */ 17e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott/* __asm__ (".symver " "__cxa_finalize" "," "__cxa_finalize" "@@" "STLPORT_5_0_0"); */ 18e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott 19e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott/* Not atomic! */ 20e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott/* But we can use static mutexes here: I hope that performance issue isn't very 21e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott significant on unloading (for only few calls, ~10) - ptr */ 22e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott 23e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott/* 24e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#define atomic_compare_and_exchange_bool_acq(mem, newval, oldval) \ 25e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott ({ __typeof (mem) __gmemp = (mem); \ 26e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott __typeof (*mem) __gnewval = (newval); \ 27e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott \ 28e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott *__gmemp == (oldval) ? (*__gmemp = __gnewval, 0) : 1; }) 29e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott*/ 30e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott 31e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scottenum { 32e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott ef_free, /* `ef_free' MUST be zero! */ 33e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott ef_us, 34e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott ef_on, 35e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott ef_at, 36e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott ef_cxa 37e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott}; 38e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott 39e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scottstruct exit_function 40e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott{ 41e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott /* `flavour' should be of type of the `enum' above but since we need 42e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott this element in an atomic operation we have to use `long int'. */ 43e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott long int flavor; 44e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott union { 45e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott void (*at)(void); 46e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott struct { 47e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott void (*fn)(int status, void *arg); 48e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott void *arg; 49e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott } on; 50e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott struct { 51e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott void (*fn)(void *arg, int status); 52e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott void *arg; 53e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott void *dso_handle; 54e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott } cxa; 55e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott } func; 56e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott}; 57e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott 58e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scottstruct exit_function_list 59e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott{ 60e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott struct exit_function_list *next; 61e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott size_t idx; 62e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott struct exit_function fns[32]; 63e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott}; 64e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott 65e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scottstruct exit_function *__new_exitfn (void); 66e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott 67e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott/* Register a function to be called by exit or when a shared library 68e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott is unloaded. This function is only called from code generated by 69e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott the C++ compiler. */ 70e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scottint __cxa_atexit(void (*func)(void *), void *arg, void *d) 71e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott{ 72e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott struct exit_function *new = __new_exitfn (); 73e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott 74e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott if ( new == NULL ) 75e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott return -1; 76e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott 77e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott new->flavor = ef_cxa; 78e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott new->func.cxa.fn = (void (*) (void *, int)) func; 79e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott new->func.cxa.arg = arg; 80e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott new->func.cxa.dso_handle = d; 81e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott return 0; 82e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott} 83e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott 84e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott 85e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott/* We change global data, so we need locking. */ 86e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#ifdef __linux__ 87e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scottstatic pthread_mutex_t lock = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP; 88e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#endif 89e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott/* #ifdef __FreeBSD__ */ 90e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#if 0 91e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scottstatic pthread_mutex_t lock = 92e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott { PTHREAD_MUTEX_RECURSIVE /* PTHREAD_MUTEX_DEFAULT */, PTHREAD_PRIO_NONE, {NULL,NULL}, 93e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott NULL, { NULL }, /* MUTEX_FLAGS_PRIVATE */ 0x1, 0, 0, 0, {NULL, NULL}, 94e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott { 0, 0, 0, 0 } }; 95e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#endif 96e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#ifdef __sun 97e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scottstatic pthread_mutex_t lock = 98e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott {{0, 0, 0, PTHREAD_MUTEX_RECURSIVE, _MUTEX_MAGIC}, {{{0}}}, 0}; 99e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#endif 100e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#ifdef __hpux 101e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scottstatic pthread_mutex_t lock = PTHREAD_MUTEX_RECURSIVE_INITIALIZER_NP; 102e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott# ifdef __ia64 103e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scottvoid *__dso_handle = (void *) &__dso_handle; 104e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott# endif 105e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#endif 106e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott 107e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott 108e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scottstatic struct exit_function_list initial; 109e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scottstruct exit_function_list *__exit_funcs = &initial; 110e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott 111e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scottstruct exit_function *__new_exitfn(void) 112e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott{ 113e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott struct exit_function_list *l; 114e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott size_t i = 0; 115e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott 116e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#ifndef __FreeBSD__ 117e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott pthread_mutex_lock( &lock ); 118e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#endif 119e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott 120e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott for (l = __exit_funcs; l != NULL; l = l->next) { 121e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott for (i = 0; i < l->idx; ++i) 122e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott if (l->fns[i].flavor == ef_free) 123e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott break; 124e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott if ( i < l->idx ) 125e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott break; 126e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott 127e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott if (l->idx < sizeof (l->fns) / sizeof (l->fns[0])) { 128e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott i = l->idx++; 129e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott break; 130e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott } 131e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott } 132e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott 133e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott if (l == NULL) { 134e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott l = (struct exit_function_list *)malloc( sizeof(struct exit_function_list) ); 135e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott if (l != NULL) { 136e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott l->next = __exit_funcs; 137e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott __exit_funcs = l; 138e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott 139e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott l->idx = 1; 140e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott i = 0; 141e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott } 142e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott } 143e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott 144e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott /* Mark entry as used, but we don't know the flavor now. */ 145e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott if ( l != NULL ) 146e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott l->fns[i].flavor = ef_us; 147e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott 148e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#ifndef __FreeBSD__ 149e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott pthread_mutex_unlock( &lock ); 150e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#endif 151e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott 152e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott return l == NULL ? NULL : &l->fns[i]; 153e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott} 154e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott 155e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott/* If D is non-NULL, call all functions registered with `__cxa_atexit' 156e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott with the same dso handle. Otherwise, if D is NULL, call all of the 157e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott registered handlers. */ 158e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott 159e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott/* 160e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott * Note, that original __cxa_finalize don't use lock, but use __exit_funcs 161e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott * i.e. global data. 162e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott */ 163e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scottvoid __cxa_finalize(void *d) 164e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott{ 165e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott struct exit_function_list *funcs; 166e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott 167e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#ifndef __FreeBSD__ 168e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott pthread_mutex_lock( &lock ); 169e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#endif 170e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott 171e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott for (funcs = __exit_funcs; funcs; funcs = funcs->next) { 172e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott struct exit_function *f; 173e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott 174e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott for (f = &funcs->fns[funcs->idx - 1]; f >= &funcs->fns[0]; --f) { 175e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott if ( (d == NULL || d == f->func.cxa.dso_handle) && (f->flavor == ef_cxa) ) { 176e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott f->flavor = ef_free; 177e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott (*f->func.cxa.fn) (f->func.cxa.arg, 0); 178e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott } 179e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott } 180e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott } 181e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott 182e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott /* Remove the registered fork handlers. We do not have to 183e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott unregister anything if the program is going to terminate anyway. */ 184e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#ifdef UNREGISTER_ATFORK 185e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott if (d != NULL) 186e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott UNREGISTER_ATFORK (d); 187e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#endif 188e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#ifndef __FreeBSD__ 189e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott pthread_mutex_unlock( &lock ); 190e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#endif 191e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott} 192e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott 193e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott/* __asm__ (".symver " "__cxa_finalize" "," "__cxa_finalize" "@@" "STLPORT_5_0_0"); */ 194e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott/* void __cxa_finalize(void *d) __attribute__ ((weak)); */ 195e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott 196e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#endif /* OS name */ 197e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#endif /* __unix */ 198e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott 199