diff options
Diffstat (limited to 'stdlib/atexit.c')
-rw-r--r-- | stdlib/atexit.c | 57 |
1 files changed, 41 insertions, 16 deletions
diff --git a/stdlib/atexit.c b/stdlib/atexit.c index a2ab453..675de66 100644 --- a/stdlib/atexit.c +++ b/stdlib/atexit.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991 Free Software Foundation, Inc. +/* Copyright (C) 1991, 1996 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -16,16 +16,16 @@ License along with the GNU C Library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include <ansidecl.h> +#include <libc-lock.h> #include <stdlib.h> #include "exit.h" /* Register FUNC to be executed by `exit'. */ int -DEFUN(atexit, (func), void EXFUN((*func), (NOARGS))) +atexit (void (*func) (void)) { - struct exit_function *new = __new_exitfn(); + struct exit_function *new = __new_exitfn (); if (new == NULL) return -1; @@ -36,30 +36,55 @@ DEFUN(atexit, (func), void EXFUN((*func), (NOARGS))) } +/* We change global data, so we need locking. */ +__libc_lock_define_initialized (static, lock) + + static struct exit_function_list fnlist = { NULL, 0, }; struct exit_function_list *__exit_funcs = &fnlist; struct exit_function * -DEFUN_VOID(__new_exitfn) +__new_exitfn (void) { - register struct exit_function_list *l; + struct exit_function_list *l; + size_t i = 0; + + __libc_lock_lock (lock) for (l = __exit_funcs; l != NULL; l = l->next) { - register size_t i; for (i = 0; i < l->idx; ++i) if (l->fns[i].flavor == ef_free) - return &l->fns[i]; - if (l->idx < sizeof(l->fns) / sizeof(l->fns[0])) - return &l->fns[l->idx++]; + break; + if (i < l->idx) + break; + + if (l->idx < sizeof (l->fns) / sizeof (l->fns[0])) + { + i = l->idx++; + break; + } } - l = (struct exit_function_list *) malloc(sizeof(struct exit_function_list)); if (l == NULL) - return NULL; - l->next = __exit_funcs; - __exit_funcs = l; + { + l = (struct exit_function_list *) + malloc (sizeof (struct exit_function_list)); + if (l != NULL) + { + l->next = __exit_funcs; + __exit_funcs = l; + + l->idx = 1; + i = 0; + } + } + + /* Mark entry as used, but we don't know the flavor now. */ + if (l != NULL) + l->fns[i].flavor = ef_us; + + __libc_lock_unlock (lock) - l->idx = 1; - return &l->fns[0]; + return l == NULL ? NULL : &l->fns[i]; } |