diff options
Diffstat (limited to 'sys/rt')
-rw-r--r-- | sys/rt/atexit.c | 49 | ||||
-rw-r--r-- | sys/rt/boot.c | 4 | ||||
-rw-r--r-- | sys/rt/dummy.c | 3 | ||||
-rw-r--r-- | sys/rt/exit.c | 19 |
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); } |