1 // Copyright (C) 2012 Free Software Foundation, Inc.
3 // This file is part of GCC.
5 // GCC is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation; either version 3, or (at your option)
10 // GCC is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
15 // Under Section 7 of GPL version 3, you are granted additional
16 // permissions described in the GCC Runtime Library Exception, version
17 // 3.1, as published by the Free Software Foundation.
19 // You should have received a copy of the GNU General Public License and
20 // a copy of the GCC Runtime Library Exception along with this program;
21 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
22 // <http://www.gnu.org/licenses/>.
27 #include "bits/gthr.h"
30 // Data structure for the list of destructors: Singly-linked list
37 void (*destructor
)(void *);
40 static const int max_nelts
= 32;
49 static void run(void *p
);
50 int add_elt(void (*)(void *), void *);
53 // Return the address of an open slot.
57 if (nelts
< max_nelts
)
58 return &array
[nelts
++];
60 next
= new (std::nothrow
) list();
63 return next
->allocate_elt();
66 // Run all the cleanups in the list.
70 for (int i
= nelts
- 1; i
>= 0; --i
)
71 array
[i
].destructor (array
[i
].object
);
76 // Static version to use as a callback to __gthread_key_create.
80 static_cast<list
*>(p
)->run();
83 // The list of cleanups is per-thread.
84 thread_local list first
;
86 // The pthread data structures for actually running the destructors at
87 // thread exit are shared. The constructor of the thread-local sentinel
88 // object in add_elt performs the initialization.
90 __gthread_once_t once
= __GTHREAD_ONCE_INIT
;
91 void run_current () { first
.run(); }
93 __gthread_key_create (&key
, list::run
);
94 // Also make sure the destructors are run by std::exit.
95 // FIXME TLS cleanups should run before static cleanups and atexit
97 std::atexit (run_current
);
103 if (__gthread_active_p ())
105 __gthread_once (&once
, key_init
);
106 __gthread_setspecific (key
, &first
);
109 std::atexit (run_current
);
113 // Actually insert an element.
115 list::add_elt(void (*dtor
)(void *), void *obj
)
117 thread_local sentinel s
;
118 elt
*e
= allocate_elt ();
122 e
->destructor
= dtor
;
130 __cxa_thread_atexit (void (*dtor
)(void *), void *obj
, void */
*dso_handle*/
)
133 return first
.add_elt (dtor
, obj
);