ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

cxa.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.