]> git.ipfire.org Git - thirdparty/glibc.git/blame - stdlib/cxa_atexit.c
Update.
[thirdparty/glibc.git] / stdlib / cxa_atexit.c
CommitLineData
5ef50d00 1/* Copyright (C) 1999, 2001 Free Software Foundation, Inc.
c41041bc
UD
2 This file is part of the GNU C Library.
3
4 The GNU C Library is free software; you can redistribute it and/or
41bdb6e2
AJ
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2.1 of the License, or (at your option) any later version.
c41041bc
UD
8
9 The GNU C Library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
41bdb6e2 12 Lesser General Public License for more details.
c41041bc 13
41bdb6e2
AJ
14 You should have received a copy of the GNU Lesser General Public
15 License along with the GNU C Library; if not, write to the Free
16 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
17 02111-1307 USA. */
c41041bc 18
c08bc50a 19#include <bits/libc-lock.h>
c41041bc
UD
20#include <stdlib.h>
21#include "exit.h"
22
23/* Register a function to be called by exit or when a shared library
24 is unloaded. This function is only called from code generated by
25 the C++ compiler. */
26int
27__cxa_atexit (void (*func) (void *), void *arg, void *d)
28{
29 struct exit_function *new = __new_exitfn ();
30
31 if (new == NULL)
32 return -1;
33
34 new->flavor = ef_cxa;
5ef50d00 35 new->func.cxa.fn = (void (*) (void *, int)) func;
c41041bc
UD
36 new->func.cxa.arg = arg;
37 new->func.cxa.dso_handle = d;
38 return 0;
39}
c08bc50a
UD
40
41
42/* We change global data, so we need locking. */
43__libc_lock_define_initialized (static, lock)
44
45
46static struct exit_function_list initial;
47struct exit_function_list *__exit_funcs = &initial;
48
49struct exit_function *
50__new_exitfn (void)
51{
52 struct exit_function_list *l;
53 size_t i = 0;
54
55 __libc_lock_lock (lock);
56
57 for (l = __exit_funcs; l != NULL; l = l->next)
58 {
59 for (i = 0; i < l->idx; ++i)
60 if (l->fns[i].flavor == ef_free)
61 break;
62 if (i < l->idx)
63 break;
64
65 if (l->idx < sizeof (l->fns) / sizeof (l->fns[0]))
66 {
67 i = l->idx++;
68 break;
69 }
70 }
71
72 if (l == NULL)
73 {
74 l = (struct exit_function_list *)
75 malloc (sizeof (struct exit_function_list));
76 if (l != NULL)
77 {
78 l->next = __exit_funcs;
79 __exit_funcs = l;
80
81 l->idx = 1;
82 i = 0;
83 }
84 }
85
86 /* Mark entry as used, but we don't know the flavor now. */
87 if (l != NULL)
88 l->fns[i].flavor = ef_us;
89
90 __libc_lock_unlock (lock);
91
92 return l == NULL ? NULL : &l->fns[i];
93}