Don't read TLS header if TLS is not needed.
[platform/upstream/glibc.git] / sysdeps / generic / dl-tls.c
1 /* Thread-local storage handling in the ELF dynamic linker.  Generic version.
2    Copyright (C) 2002 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, write to the Free
17    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18    02111-1307 USA.  */
19
20 #include <assert.h>
21
22
23 /* We don't need any of this if TLS is not supported.  */
24 #ifdef USE_TLS
25
26 #include <tls.h>
27 #include <dl-tls.h>
28 #include <ldsodefs.h>
29
30 /* Value used for dtv entries for which the allocation is delayed.  */
31 # define TLS_DTV_UNALLOCATE     ((void *) -1l)
32
33
34 size_t
35 internal_function
36 _dl_next_tls_modid (void)
37 {
38   size_t result;
39
40   if (__builtin_expect (GL(dl_tls_dtv_gaps), false))
41     {
42       /* XXX If this method proves too costly we can optimize
43          it to use a constant time method.  But I don't think
44          it's a problem.  */
45       struct link_map *runp = GL(dl_initimage_list);
46       bool used[GL(dl_tls_max_dtv_idx)];
47
48       assert (runp != NULL);
49       do
50         {
51           assert (runp->l_tls_modid > 0
52                   && runp->l_tls_modid <= GL(dl_tls_max_dtv_idx));
53           used[runp->l_tls_modid - 1] = true;
54         }
55       while ((runp = runp->l_tls_nextimage) != GL(dl_initimage_list));
56
57       result = 0;
58       do
59         /* The information about the gaps is pessimistic.  It might be
60            there are actually none.  */
61         if (result >= GL(dl_tls_max_dtv_idx))
62           {
63             /* Now we know there is actually no gap.  Bump the maximum
64                ID number and remember that there are no gaps.  */
65             result = ++GL(dl_tls_max_dtv_idx);
66             GL(dl_tls_dtv_gaps) = false;
67             break;
68           }
69       while (used[result++]);
70     }
71   else
72     /* No gaps, allocate a new entry.  */
73     result = ++GL(dl_tls_max_dtv_idx);
74
75   return result;
76 }
77
78
79 void
80 internal_function
81 _dl_determine_tlsoffset (struct link_map *firstp)
82 {
83   struct link_map *runp = firstp;
84   size_t max_align = 0;
85   size_t offset;
86
87 # if TLS_TCB_AT_TP
88   /* We simply start with zero.  */
89   offset = 0;
90
91   do
92     {
93       max_align = MAX (max_align, runp->l_tls_align);
94
95       /* Compute the offset of the next TLS block.  */
96       offset = roundup (offset + runp->l_tls_blocksize, runp->l_tls_align);
97
98       /* XXX For some architectures we perhaps should store the
99          negative offset.  */
100       runp->l_tls_offset = offset;
101     }
102   while ((runp = runp->l_tls_nextimage) != firstp);
103
104   /* The thread descriptor (pointed to by the thread pointer) has its
105      own alignment requirement.  Adjust the static TLS size
106      and TLS offsets appropriately.  */
107   if (offset % TLS_TCB_ALIGN != 0)
108     {
109       size_t add = TLS_TCB_ALIGN - offset % TLS_TCB_ALIGN;
110
111       /* XXX If the offset stored is negative we must subtract here.  */
112       offset += add;
113
114       runp = firstp;
115       do
116         runp->l_tls_offset += add;
117       while ((runp = runp->l_tls_nextimage) != firstp);
118     }
119
120   GL(dl_tls_static_size) = offset + TLS_TCB_SIZE;
121 # elif TLS_DTV_AT_TP
122   struct link_map *lastp;
123
124   /* The first block starts right after the TCB.  */
125   offset = TLS_TCB_SIZE;
126   max_align = runp->l_tls_align;
127   runp->l_tls_offset = offset;
128   lastp = runp;
129
130   while ((runp = runp->l_tls_nextimage) != firstp)
131     {
132       max_align = MAX (max_align, runp->l_tls_align);
133
134       /* Compute the offset of the next TLS block.  */
135       offset = roundup (offset + lastp->l_tls_blocksize, runp->l_tls_align);
136
137       runp->l_tls_offset = offset;
138
139       lastp = runp;
140     }
141
142   GL(dl_tls_static_size) = offset + lastp->l_tls_blocksize;
143 # else
144 #  error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
145 # endif
146
147   /* The alignment requirement for the static TLS block.  */
148   GL(dl_tls_static_align) = MAX (TLS_TCB_ALIGN, max_align);
149 }
150
151
152 /* The __tls_get_addr function has two basic forms which differ in the
153    arguments.  The IA-64 form takes two parameters, the module ID and
154    offset.  The form used, among others, on IA-32 takes a reference to
155    a special structure which contain the same information.  The second
156    form seems to be more often used (in the moment) so we default to
157    it.  Users of the IA-64 form have to provide adequate definitions
158    of the following macros.  */
159 # ifndef GET_ADDR_ARGS
160 #  define GET_ADDR_ARGS tls_index *ti
161 # endif
162 # ifndef GET_ADDR_MODULE
163 #  define GET_ADDR_MODULE ti->ti_module
164 # endif
165 # ifndef GET_ADDR_OFFSET
166 #  define GET_ADDR_OFFSET ti->ti_offset
167 # endif
168
169
170 void *
171 __tls_get_addr (GET_ADDR_ARGS)
172 {
173   dtv_t *dtv = THREAD_DTV ();
174
175   if (dtv[GET_ADDR_MODULE].pointer == TLS_DTV_UNALLOCATE)
176     /* XXX */;
177
178   return (char *) dtv[GET_ADDR_MODULE].pointer + GET_ADDR_OFFSET;
179 }
180
181 #endif  /* use TLS */