Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygencxa.c
Go to the documentation of this file.
00001 #include "stlport_prefix.h" 00002 00003 #if defined(__unix) && defined(__GNUC__) 00004 00005 #ifdef __FreeBSD__ 00006 # include <osreldate.h> 00007 #endif 00008 00009 #if (defined(__FreeBSD__) && (__FreeBSD_version < 503001)) || defined(__sun) || defined (__hpux) 00010 /* Note: __cxa_finalize and __cxa_atexit present in libc in FreeBSD 5.3 */ 00011 00012 #include <stdlib.h> 00013 #include <stdio.h> 00014 #include <pthread.h> 00015 00016 /* __asm__ (".symver " "__cxa_finalize" "," "__cxa_finalize" "@" "STLPORT_5_0_0"); */ 00017 /* __asm__ (".symver " "__cxa_finalize" "," "__cxa_finalize" "@@" "STLPORT_5_0_0"); */ 00018 00019 /* Not atomic! */ 00020 /* But we can use static mutexes here: I hope that performance issue isn't very 00021 significant on unloading (for only few calls, ~10) - ptr */ 00022 00023 /* 00024 #define atomic_compare_and_exchange_bool_acq(mem, newval, oldval) \ 00025 ({ __typeof (mem) __gmemp = (mem); \ 00026 __typeof (*mem) __gnewval = (newval); \ 00027 \ 00028 *__gmemp == (oldval) ? (*__gmemp = __gnewval, 0) : 1; }) 00029 */ 00030 00031 enum { 00032 ef_free, /* `ef_free' MUST be zero! */ 00033 ef_us, 00034 ef_on, 00035 ef_at, 00036 ef_cxa 00037 }; 00038 00039 struct exit_function 00040 { 00041 /* `flavour' should be of type of the `enum' above but since we need 00042 this element in an atomic operation we have to use `long int'. */ 00043 long int flavor; 00044 union { 00045 void (*at)(void); 00046 struct { 00047 void (*fn)(int status, void *arg); 00048 void *arg; 00049 } on; 00050 struct { 00051 void (*fn)(void *arg, int status); 00052 void *arg; 00053 void *dso_handle; 00054 } cxa; 00055 } func; 00056 }; 00057 00058 struct exit_function_list 00059 { 00060 struct exit_function_list *next; 00061 size_t idx; 00062 struct exit_function fns[32]; 00063 }; 00064 00065 struct exit_function *__new_exitfn (void); 00066 00067 /* Register a function to be called by exit or when a shared library 00068 is unloaded. This function is only called from code generated by 00069 the C++ compiler. */ 00070 int __cxa_atexit(void (*func)(void *), void *arg, void *d) 00071 { 00072 struct exit_function *new = __new_exitfn (); 00073 00074 if ( new == NULL ) 00075 return -1; 00076 00077 new->flavor = ef_cxa; 00078 new->func.cxa.fn = (void (*) (void *, int)) func; 00079 new->func.cxa.arg = arg; 00080 new->func.cxa.dso_handle = d; 00081 return 0; 00082 } 00083 00084 00085 /* We change global data, so we need locking. */ 00086 #ifdef __linux__ 00087 static pthread_mutex_t lock = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP; 00088 #endif 00089 /* #ifdef __FreeBSD__ */ 00090 #if 0 00091 static pthread_mutex_t lock = 00092 { PTHREAD_MUTEX_RECURSIVE /* PTHREAD_MUTEX_DEFAULT */, PTHREAD_PRIO_NONE, {NULL,NULL}, 00093 NULL, { NULL }, /* MUTEX_FLAGS_PRIVATE */ 0x1, 0, 0, 0, {NULL, NULL}, 00094 { 0, 0, 0, 0 } }; 00095 #endif 00096 #ifdef __sun 00097 static pthread_mutex_t lock = 00098 {{0, 0, 0, PTHREAD_MUTEX_RECURSIVE, _MUTEX_MAGIC}, {{{0}}}, 0}; 00099 #endif 00100 #ifdef __hpux 00101 static pthread_mutex_t lock = PTHREAD_MUTEX_RECURSIVE_INITIALIZER_NP; 00102 # ifdef __ia64 00103 void *__dso_handle = (void *) &__dso_handle; 00104 # endif 00105 #endif 00106 00107 00108 static struct exit_function_list initial; 00109 struct exit_function_list *__exit_funcs = &initial; 00110 00111 struct exit_function *__new_exitfn(void) 00112 { 00113 struct exit_function_list *l; 00114 size_t i = 0; 00115 00116 #ifndef __FreeBSD__ 00117 pthread_mutex_lock( &lock ); 00118 #endif 00119 00120 for (l = __exit_funcs; l != NULL; l = l->next) { 00121 for (i = 0; i < l->idx; ++i) 00122 if (l->fns[i].flavor == ef_free) 00123 break; 00124 if ( i < l->idx ) 00125 break; 00126 00127 if (l->idx < sizeof (l->fns) / sizeof (l->fns[0])) { 00128 i = l->idx++; 00129 break; 00130 } 00131 } 00132 00133 if (l == NULL) { 00134 l = (struct exit_function_list *)malloc( sizeof(struct exit_function_list) ); 00135 if (l != NULL) { 00136 l->next = __exit_funcs; 00137 __exit_funcs = l; 00138 00139 l->idx = 1; 00140 i = 0; 00141 } 00142 } 00143 00144 /* Mark entry as used, but we don't know the flavor now. */ 00145 if ( l != NULL ) 00146 l->fns[i].flavor = ef_us; 00147 00148 #ifndef __FreeBSD__ 00149 pthread_mutex_unlock( &lock ); 00150 #endif 00151 00152 return l == NULL ? NULL : &l->fns[i]; 00153 } 00154 00155 /* If D is non-NULL, call all functions registered with `__cxa_atexit' 00156 with the same dso handle. Otherwise, if D is NULL, call all of the 00157 registered handlers. */ 00158 00159 /* 00160 * Note, that original __cxa_finalize don't use lock, but use __exit_funcs 00161 * i.e. global data. 00162 */ 00163 void __cxa_finalize(void *d) 00164 { 00165 struct exit_function_list *funcs; 00166 00167 #ifndef __FreeBSD__ 00168 pthread_mutex_lock( &lock ); 00169 #endif 00170 00171 for (funcs = __exit_funcs; funcs; funcs = funcs->next) { 00172 struct exit_function *f; 00173 00174 for (f = &funcs->fns[funcs->idx - 1]; f >= &funcs->fns[0]; --f) { 00175 if ( (d == NULL || d == f->func.cxa.dso_handle) && (f->flavor == ef_cxa) ) { 00176 f->flavor = ef_free; 00177 (*f->func.cxa.fn) (f->func.cxa.arg, 0); 00178 } 00179 } 00180 } 00181 00182 /* Remove the registered fork handlers. We do not have to 00183 unregister anything if the program is going to terminate anyway. */ 00184 #ifdef UNREGISTER_ATFORK 00185 if (d != NULL) 00186 UNREGISTER_ATFORK (d); 00187 #endif 00188 #ifndef __FreeBSD__ 00189 pthread_mutex_unlock( &lock ); 00190 #endif 00191 } 00192 00193 /* __asm__ (".symver " "__cxa_finalize" "," "__cxa_finalize" "@@" "STLPORT_5_0_0"); */ 00194 /* void __cxa_finalize(void *d) __attribute__ ((weak)); */ 00195 00196 #endif /* OS name */ 00197 #endif /* __unix */ 00198 Generated on Thu May 24 2012 04:35:36 for ReactOS by
1.7.6.1
|