summaryrefslogtreecommitdiff
path: root/libc
diff options
context:
space:
mode:
Diffstat (limited to 'libc')
-rw-r--r--libc/stdlib/atexit.c96
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