build/stlport/src/cxa.c

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

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

mercurial