diff options
Diffstat (limited to 'libc')
| -rw-r--r-- | libc/stdlib/atexit.c | 96 | 
1 files changed, 68 insertions, 28 deletions
diff --git a/libc/stdlib/atexit.c b/libc/stdlib/atexit.c index 44abc343b..e82f53fe3 100644 --- a/libc/stdlib/atexit.c +++ b/libc/stdlib/atexit.c @@ -52,8 +52,6 @@ extern pthread_mutex_t mylock;  #endif -#define __MAX_EXIT __UCLIBC_MAX_ATEXIT -  typedef void (*aefuncp) (void);         /* atexit function pointer */  typedef void (*oefuncp) (int, void *);  /* on_exit function pointer */  typedef enum { @@ -65,9 +63,10 @@ typedef enum {  extern void (*__exit_cleanup) (int);  /* these are in the L___do_exit object */ +extern int __exit_slots;  extern int __exit_count;  extern void __exit_handler(int); -extern struct exit_function { +struct exit_function {  	ef_type type;	/* ef_atexit or ef_on_exit */  	union {  		aefuncp atexit; @@ -76,7 +75,12 @@ extern struct exit_function {  			void *arg;  		} on_exit;  	} funcs; -} __exit_function_table[__MAX_EXIT]; +}; +#ifdef __UCLIBC_DYNAMIC_ATEXIT__ +extern struct exit_function *__exit_function_table; +#else +extern struct exit_function __exit_function_table[__UCLIBC_MAX_ATEXIT]; +#endif  #ifdef L_atexit  	/* @@ -85,22 +89,34 @@ extern struct exit_function {  	 */  int atexit(aefuncp func)  { -	struct exit_function *efp; - -	LOCK; -	if (__exit_count >= __MAX_EXIT) { +    struct exit_function *efp; + +    LOCK; +    if (func) { +#ifdef __UCLIBC_DYNAMIC_ATEXIT__ +	/* If we are out of function table slots, make some more */ +	if (__exit_slots < __exit_count+1) { +	    __exit_function_table=realloc(__exit_function_table, __exit_slots+20); +	    if (__exit_function_table==NULL) {  		UNLOCK;  		__set_errno(ENOMEM);  		return -1; +	    }  	} -	if (func) { -		__exit_cleanup = __exit_handler; /* enable cleanup */ -		efp = &__exit_function_table[__exit_count++]; -		efp->type = ef_atexit; -		efp->funcs.atexit = func; +#else +	if (__exit_count >= __UCLIBC_MAX_ATEXIT) { +	    UNLOCK; +	    __set_errno(ENOMEM); +	    return -1;  	} -	UNLOCK; -	return 0; +#endif +	__exit_cleanup = __exit_handler; /* enable cleanup */ +	efp = &__exit_function_table[__exit_count++]; +	efp->type = ef_atexit; +	efp->funcs.atexit = func; +    } +    UNLOCK; +    return 0;  }  #endif @@ -113,29 +129,48 @@ int atexit(aefuncp func)   */  int on_exit(oefuncp func, void *arg)  { -	struct exit_function *efp; - -	LOCK; -	if (__exit_count >= __MAX_EXIT) { +    struct exit_function *efp; + +    LOCK; +    if (func) { +#ifdef __UCLIBC_DYNAMIC_ATEXIT__ +	/* If we are out of function table slots, make some more */ +	if (__exit_slots < __exit_count+1) { +	    __exit_function_table=realloc(__exit_function_table, __exit_slots+20); +	    if (__exit_function_table==NULL) {  		UNLOCK;  		__set_errno(ENOMEM);  		return -1; +	    }  	} -	if (func) { -		__exit_cleanup = __exit_handler; /* enable cleanup */ -		efp = &__exit_function_table[__exit_count++]; -		efp->type = ef_on_exit; -		efp->funcs.on_exit.func = func; -		efp->funcs.on_exit.arg = arg; +#else +	if (__exit_count >= __UCLIBC_MAX_ATEXIT) { +	    UNLOCK; +	    __set_errno(ENOMEM); +	    return -1;  	} -	UNLOCK; -	return 0; +#endif + +	__exit_cleanup = __exit_handler; /* enable cleanup */ +	efp = &__exit_function_table[__exit_count++]; +	efp->type = ef_on_exit; +	efp->funcs.on_exit.func = func; +	efp->funcs.on_exit.arg = arg; +    } +    UNLOCK; +    return 0;  }  #endif  #ifdef L___exit_handler -struct exit_function __exit_function_table[__MAX_EXIT];  int __exit_count = 0; /* Number of registered exit functions */ +#ifdef __UCLIBC_DYNAMIC_ATEXIT__ +struct exit_function *__exit_function_table = NULL; +int __exit_slots = 0; /* Size of __exit_function_table */ +#else +struct exit_function __exit_function_table[__UCLIBC_MAX_ATEXIT]; +#endif +  /*   * Handle the work of executing the registered exit functions @@ -162,6 +197,11 @@ void __exit_handler(int status)  			break;  		}  	} +#ifdef __UCLIBC_DYNAMIC_ATEXIT__ +	/* Free up memory used by the __exit_function_table structure */  +	if (__exit_function_table) +	    free(__exit_function_table); +#endif  }  #endif  | 
