Remove unused variable from stdlib/setenv.c
[platform/upstream/glibc.git] / stdlib / cxa_thread_atexit_impl.c
1 /* Register destructors for C++ TLS variables declared with thread_local.
2    Copyright (C) 2013-2014 Free Software Foundation, Inc.
3    This file is part of the GNU C Library.
4
5    The GNU C Library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public
7    License as published by the Free Software Foundation; either
8    version 2.1 of the License, or (at your option) any later version.
9
10    The GNU C Library 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 GNU
13    Lesser General Public License for more details.
14
15    You should have received a copy of the GNU Lesser General Public
16    License along with the GNU C Library; if not, see
17    <http://www.gnu.org/licenses/>.  */
18
19 #include <stdlib.h>
20 #include <ldsodefs.h>
21
22 typedef void (*dtor_func) (void *);
23
24 struct dtor_list
25 {
26   dtor_func func;
27   void *obj;
28   struct link_map *map;
29   struct dtor_list *next;
30 };
31
32 static __thread struct dtor_list *tls_dtor_list;
33 static __thread void *dso_symbol_cache;
34 static __thread struct link_map *lm_cache;
35
36 /* Register a destructor for TLS variables declared with the 'thread_local'
37    keyword.  This function is only called from code generated by the C++
38    compiler.  FUNC is the destructor function and OBJ is the object to be
39    passed to the destructor.  DSO_SYMBOL is the __dso_handle symbol that each
40    DSO has at a unique address in its map, added from crtbegin.o during the
41    linking phase.  */
42 int
43 __cxa_thread_atexit_impl (dtor_func func, void *obj, void *dso_symbol)
44 {
45   /* Prepend.  */
46   struct dtor_list *new = calloc (1, sizeof (struct dtor_list));
47   new->func = func;
48   new->obj = obj;
49   new->next = tls_dtor_list;
50   tls_dtor_list = new;
51
52   /* See if we already encountered the DSO.  */
53   __rtld_lock_lock_recursive (GL(dl_load_lock));
54
55   if (__glibc_unlikely (dso_symbol_cache != dso_symbol))
56     {
57       ElfW(Addr) caller = (ElfW(Addr)) dso_symbol;
58
59       struct link_map *l = _dl_find_dso_for_object (caller);
60
61       /* If the address is not recognized the call comes from the main
62          program (we hope).  */
63       lm_cache = l ? l : GL(dl_ns)[LM_ID_BASE]._ns_loaded;
64     }
65   /* A destructor could result in a thread_local construction and the former
66      could have cleared the flag.  */
67   if (lm_cache->l_type == lt_loaded && lm_cache->l_tls_dtor_count == 0)
68     lm_cache->l_flags_1 |= DF_1_NODELETE;
69
70   new->map = lm_cache;
71   new->map->l_tls_dtor_count++;
72
73   __rtld_lock_unlock_recursive (GL(dl_load_lock));
74
75   return 0;
76 }
77
78 /* Call the destructors.  This is called either when a thread returns from the
79    initial function or when the process exits via the exit function.  */
80 void
81 __call_tls_dtors (void)
82 {
83   while (tls_dtor_list)
84     {
85       struct dtor_list *cur = tls_dtor_list;
86       tls_dtor_list = tls_dtor_list->next;
87
88       cur->func (cur->obj);
89
90       __rtld_lock_lock_recursive (GL(dl_load_lock));
91
92       /* Allow DSO unload if count drops to zero.  */
93       cur->map->l_tls_dtor_count--;
94       if (cur->map->l_tls_dtor_count == 0 && cur->map->l_type == lt_loaded)
95         cur->map->l_flags_1 &= ~DF_1_NODELETE;
96
97       __rtld_lock_unlock_recursive (GL(dl_load_lock));
98
99       free (cur);
100     }
101 }
102 libc_hidden_def (__call_tls_dtors)