about summary refs log tree commit diff
path: root/stdlib/atexit.c
diff options
context:
space:
mode:
Diffstat (limited to 'stdlib/atexit.c')
-rw-r--r--stdlib/atexit.c57
1 files changed, 41 insertions, 16 deletions
diff --git a/stdlib/atexit.c b/stdlib/atexit.c
index a2ab453576..675de668cc 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];
 }