X-Git-Url: https://git.saurik.com/apple/libc.git/blobdiff_plain/1f2f436a38f7ae2d39a943ad2898d8fed4ed2e58..a28bf75d63c6a64e4c3b417c6052e45f42c6cedd:/stdlib/FreeBSD/atexit.c diff --git a/stdlib/FreeBSD/atexit.c b/stdlib/FreeBSD/atexit.c index 05dad84..6acc776 100644 --- a/stdlib/FreeBSD/atexit.c +++ b/stdlib/FreeBSD/atexit.c @@ -41,14 +41,23 @@ __FBSDID("$FreeBSD: src/lib/libc/stdlib/atexit.c,v 1.8 2007/01/09 00:28:09 imp E #include #include #include +#if defined(__DYNAMIC__) || defined (__BLOCKS__) +#include +#endif /* defined(__DYNAMIC__) */ #include "atexit.h" #include "un-namespace.h" +#ifdef __BLOCKS__ +#include +#endif /* __BLOCKS__ */ #include "libc_private.h" #define ATEXIT_FN_EMPTY 0 #define ATEXIT_FN_STD 1 #define ATEXIT_FN_CXA 2 +#ifdef __BLOCKS__ +#define ATEXIT_FN_BLK 3 +#endif /* __BLOCKS__ */ static pthread_mutex_t atexit_mutex = PTHREAD_MUTEX_INITIALIZER; @@ -63,6 +72,9 @@ struct atexit { union { void (*std_func)(void); void (*cxa_func)(void *); +#ifdef __BLOCKS__ + void (^block)(void); +#endif /* __BLOCKS__ */ } fn_ptr; /* function pointer */ void *fn_arg; /* argument for CXA callback */ void *fn_dso; /* shared module handle */ @@ -70,6 +82,7 @@ struct atexit { }; static struct atexit *__atexit; /* points to head of LIFO stack */ +static int new_registration; /* * Register the function described by 'fptr' to be called at application @@ -105,6 +118,7 @@ atexit_register(struct atexit_fn *fptr) __atexit = p; } p->fns[p->ind++] = *fptr; + new_registration = 1; _MUTEX_UNLOCK(&atexit_mutex); return 0; } @@ -116,17 +130,50 @@ int atexit(void (*func)(void)) { struct atexit_fn fn; + struct dl_info info; int error; fn.fn_type = ATEXIT_FN_STD; - fn.fn_ptr.std_func = func;; + fn.fn_ptr.std_func = func; fn.fn_arg = NULL; +#if defined(__DYNAMIC__) + if ( dladdr(func, &info) ) + fn.fn_dso = info.dli_fbase; + else + fn.fn_dso = NULL; +#else /* ! defined(__DYNAMIC__) */ fn.fn_dso = NULL; +#endif /* defined(__DYNAMIC__) */ error = atexit_register(&fn); return (error); } +#ifdef __BLOCKS__ +int +atexit_b(void (^block)(void)) +{ + struct atexit_fn fn; + struct dl_info info; + int error; + + fn.fn_type = ATEXIT_FN_BLK; + fn.fn_ptr.block = Block_copy(block); + fn.fn_arg = NULL; +#if defined(__DYNAMIC__) + if ( dladdr(block, &info) ) + fn.fn_dso = info.dli_fbase; + else + fn.fn_dso = NULL; +#else /* ! defined(__DYNAMIC__) */ + fn.fn_dso = NULL; +#endif /* defined(__DYNAMIC__) */ + + error = atexit_register(&fn); + return (error); +} +#endif /* __BLOCKS__ */ + /* * Register a function to be performed at exit or when an shared object * with given dso handle is unloaded dynamically. @@ -152,13 +199,14 @@ __cxa_atexit(void (*func)(void *), void *arg, void *dso) * handlers are called. */ void -__cxa_finalize(void *dso) +__cxa_finalize(const void *dso) { struct atexit *p; struct atexit_fn fn; int n; _MUTEX_LOCK(&atexit_mutex); +restart: for (p = __atexit; p; p = p->next) { for (n = p->ind; --n >= 0;) { if (p->fns[n].fn_type == ATEXIT_FN_EMPTY) @@ -171,6 +219,7 @@ __cxa_finalize(void *dso) has already been called. */ p->fns[n].fn_type = ATEXIT_FN_EMPTY; + new_registration = 0; _MUTEX_UNLOCK(&atexit_mutex); /* Call the function of correct type. */ @@ -178,7 +227,13 @@ __cxa_finalize(void *dso) fn.fn_ptr.cxa_func(fn.fn_arg); else if (fn.fn_type == ATEXIT_FN_STD) fn.fn_ptr.std_func(); +#ifdef __BLOCKS__ + else if (fn.fn_type == ATEXIT_FN_BLK) + fn.fn_ptr.block(); +#endif /* __BLOCKS__ */ _MUTEX_LOCK(&atexit_mutex); + if (new_registration) + goto restart; } } _MUTEX_UNLOCK(&atexit_mutex);