From 336849ea6e8dc302f7e77aeabadd8961f9666bfb Mon Sep 17 00:00:00 2001
From: Eric Andersen <andersen@codepoet.org>
Date: Tue, 19 Nov 2002 07:08:33 +0000
Subject: Implement dynamic atexit handling.  Adds a few bytes and a dependancy
 on malloc (via realloc).  -Erik

---
 libc/stdlib/atexit.c | 96 +++++++++++++++++++++++++++++++++++++---------------
 1 file changed, 68 insertions(+), 28 deletions(-)

(limited to 'libc/stdlib')

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
 
-- 
cgit v1.2.3