build/stlport/src/cxa.c

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

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

mercurial