aboutsummaryrefslogtreecommitdiff
path: root/sys/rt
diff options
context:
space:
mode:
Diffstat (limited to 'sys/rt')
-rw-r--r--sys/rt/atexit.c49
-rw-r--r--sys/rt/boot.c4
-rw-r--r--sys/rt/dummy.c3
-rw-r--r--sys/rt/exit.c19
4 files changed, 69 insertions, 6 deletions
diff --git a/sys/rt/atexit.c b/sys/rt/atexit.c
new file mode 100644
index 0000000..208cc6e
--- /dev/null
+++ b/sys/rt/atexit.c
@@ -0,0 +1,49 @@
+#include <u.h>
+#include <rt.h>
+
+#define COUNT 32
+
+static struct cleaner
+{
+ struct cleaner *next;
+ void (*clean[COUNT])(void *);
+ void *arg[COUNT];
+} arena, *head;
+static int slot;
+
+void weaklink exit(int code){};
+
+void
+rt·clean(void)
+{
+ void (*clean)(void *), *arg;
+ /*LOCK*/
+ for(; head; head=head->next, slot=COUNT) {
+ while(slot-- > 0){
+ arg = head->arg[slot];
+ clean = head->clean[slot];
+ /* UNLOCK */
+ clean(arg);
+ /* LOCK */
+ }
+ }
+}
+
+int
+rt·atexit(void (*clean)(void *), void *arg)
+{
+ /* LOCK */
+ if(!head)
+ head = &arena;
+
+ /* we need malloc... */
+ if(slot==COUNT)
+ return -1;
+
+ head->arg[slot] = arg;
+ head->clean[slot] = clean;
+ slot++;
+
+ /* UNLOCK */
+ return 0;
+}
diff --git a/sys/rt/boot.c b/sys/rt/boot.c
index 320a596..8c6616d 100644
--- a/sys/rt/boot.c
+++ b/sys/rt/boot.c
@@ -3,7 +3,10 @@
#include <elf.h>
/* tell linker to go find */
+int atexit(void (*)(void));
int __libc_start_main(int (*main)(int,char **,char **), int argc, char **argv);
+
+void rt·clean(void);
void rt·guardstack(void);
#define NAUX 38
@@ -30,6 +33,7 @@ rt·boot(int (*main)(), int argc, char **argv, void (*init)(), void (*fini)(), v
rt·init(env, argv[0]);
/* ring libc, anyone home? */
+ atexit(rt·clean);
__libc_start_main(main, argc, argv);
/* no? ok we continue on if there is no libc linked */
diff --git a/sys/rt/dummy.c b/sys/rt/dummy.c
index f123d16..0cef224 100644
--- a/sys/rt/dummy.c
+++ b/sys/rt/dummy.c
@@ -4,3 +4,6 @@
/* provide a dummy implementation if libc is not linked */
static int noop(int (*main)(), int argc, char **argv) { return 0; }
weakalias(noop, __libc_start_main);
+
+static int noop2(void (*func)(void)) { return 0; }
+weakalias(noop, atexit);
diff --git a/sys/rt/exit.c b/sys/rt/exit.c
index e6027b7..386a1bf 100644
--- a/sys/rt/exit.c
+++ b/sys/rt/exit.c
@@ -2,10 +2,13 @@
#include <rt.h>
#include <syscall.h>
-/* XXX:
- * if we are here, we are in charge, call exit syscalls
- * think of better way to encapsulate these syscalls?
- */
+/* tell linker to go find */
+void noreturn exit(int code);
+
+/* if did not call rt·atexit, then don't pull it in */
+static void noop(void){}
+weakalias(noop, rt·clean);
+
static noreturn void
rt·shutdown(int code)
{
@@ -14,14 +17,18 @@ rt·shutdown(int code)
if(rt·context.exit)
rt·context.exit();
+ /* XXX: better way to encapsulate these calls? */
_syscall1(·ExitGroup, code);
for(;;)
_syscall1(·Exit, code);
}
-weakalias(rt·shutdown, exit);
noreturn void
rt·exit(int code)
{
- rt·shutdown(code);
+ /* ring libc, anyone home? */
+ exit(code);
+ /* if we are here, we are in charge, shut it down */
+ rt·clean();
+ rt·shutdown(code);
}