mirror of
https://sourceware.org/git/glibc.git
synced 2025-01-03 08:11:08 +00:00
Update.
2002-02-06 Ulrich Drepper <drepper@redhat.com> * Versions.def [ld]: Add GLIBC_2.3. * elf/Versions [ld]: Add __tls_get_addr to GLIBC_2.3. * elf/Makefile (dl-routines): Add dl-tls. (distribute): Add dl-tls.h. * sysdeps/generic/ldsodefs.h (struct rtld_global): Remove _dl_tls_module_cnt, add _dl_tls_max_dtv_idx and _dl_tls_dtv_gaps. Add prototypes for _dl_next_tls_modid and _dl_determine_tlsoffset. * elf/dl-load.c (_dl_map_object_from_fd): Store alignment requirement along with the other info in the link map. Change queueing of init images for double linked list. Use _dl_next_tls_modid to compute l_tls_modid. * elf/rtld.c (_dl_start_final): Store alignment requirement along with the other info in rtld map and executable map. (dl_main): Add ld.so to the init image list if necessary. Compute final module ID with _dl_next_tls_modid. * include/link.h (struct link_map): Add l_tls_previmage and l_tls_align. * eld/dl-support.c: Define _dl_tls_max_dtv_idx and _dl_tls_dtv_gaps. * sysdeps/i386/elf/Versions: New file. * sysdeps/generic/dl-tls.c: New file. * sysdeps/generic/dl-tls.h: New file. * sysdeps/i386/dl-tls.h: New file. attribute((packed)) to counter stupid people misusing gcc options.
This commit is contained in:
parent
a53a253b90
commit
3fb558781f
27
ChangeLog
27
ChangeLog
@ -1,3 +1,28 @@
|
||||
2002-02-06 Ulrich Drepper <drepper@redhat.com>
|
||||
|
||||
* Versions.def [ld]: Add GLIBC_2.3.
|
||||
* elf/Versions [ld]: Add __tls_get_addr to GLIBC_2.3.
|
||||
* elf/Makefile (dl-routines): Add dl-tls.
|
||||
(distribute): Add dl-tls.h.
|
||||
* sysdeps/generic/ldsodefs.h (struct rtld_global): Remove
|
||||
_dl_tls_module_cnt, add _dl_tls_max_dtv_idx and _dl_tls_dtv_gaps.
|
||||
Add prototypes for _dl_next_tls_modid and _dl_determine_tlsoffset.
|
||||
* elf/dl-load.c (_dl_map_object_from_fd): Store alignment requirement
|
||||
along with the other info in the link map. Change queueing of init
|
||||
images for double linked list. Use _dl_next_tls_modid to compute
|
||||
l_tls_modid.
|
||||
* elf/rtld.c (_dl_start_final): Store alignment requirement
|
||||
along with the other info in rtld map and executable map.
|
||||
(dl_main): Add ld.so to the init image list if necessary. Compute
|
||||
final module ID with _dl_next_tls_modid.
|
||||
* include/link.h (struct link_map): Add l_tls_previmage and
|
||||
l_tls_align.
|
||||
* eld/dl-support.c: Define _dl_tls_max_dtv_idx and _dl_tls_dtv_gaps.
|
||||
* sysdeps/i386/elf/Versions: New file.
|
||||
* sysdeps/generic/dl-tls.c: New file.
|
||||
* sysdeps/generic/dl-tls.h: New file.
|
||||
* sysdeps/i386/dl-tls.h: New file.
|
||||
|
||||
2002-02-06 Roland McGrath <roland@frob.com>
|
||||
|
||||
* sysdeps/unix/sysv/linux/netinet/ip.h: Moved to ...
|
||||
@ -19,7 +44,7 @@
|
||||
2002-02-06 Ulrich Drepper <drepper@redhat.com>
|
||||
|
||||
* sysdeps/unix/sysv/linux/bits/stat.h (struct stat): Add
|
||||
attribute((packed)) to counter stupid people misuing gcc options.
|
||||
attribute((packed)) to counter stupid people misusing gcc options.
|
||||
(struct stat64): Likewise.
|
||||
|
||||
2002-02-05 Ulrich Drepper <drepper@redhat.com>
|
||||
|
@ -143,8 +143,10 @@ __libc_lock_define_initialized_recursive (, _dl_load_lock)
|
||||
initialize new TLS blocks. */
|
||||
struct link_map *_dl_initimage_list;
|
||||
|
||||
/* Count the number of modules which define TLS data. */
|
||||
size_t _dl_tls_module_cnt;
|
||||
/* Highest dtv index currently needed. */
|
||||
size_t _dl_tls_max_dtv_idx;
|
||||
/* Flag signalling whether there are gaps in the module ID allocation. */
|
||||
bool _dl_tls_dtv_gaps;
|
||||
#endif
|
||||
|
||||
|
||||
|
72
elf/rtld.c
72
elf/rtld.c
@ -259,9 +259,11 @@ _dl_start_final (void *arg, struct link_map *bootstrap_map_p,
|
||||
if (phdr[cnt].p_type == PT_TLS)
|
||||
{
|
||||
void *tlsblock;
|
||||
size_t align = MAX (TLS_INIT_TCB_ALIGN, phdr[cnt].p_align);
|
||||
size_t max_align = MAX (TLS_INIT_TCB_ALIGN, phdr[cnt].p_align);
|
||||
|
||||
GL(dl_rtld_map).l_tls_blocksize = phdr[cnt].p_memsz;
|
||||
GL(dl_rtld_map).l_tls_align = phdr[cnt].p_align;
|
||||
assert (GL(dl_rtld_map).l_tls_blocksize != 0);
|
||||
GL(dl_rtld_map).l_tls_initimage_size = phdr[cnt].p_filesz;
|
||||
GL(dl_rtld_map).l_tls_initimage = (void *) (GL(dl_rtld_map).l_map_start
|
||||
+ phdr[cnt].p_offset);
|
||||
@ -274,19 +276,20 @@ _dl_start_final (void *arg, struct link_map *bootstrap_map_p,
|
||||
tlsblock = alloca (roundup (GL(dl_rtld_map).l_tls_blocksize,
|
||||
TLS_INIT_TCB_ALIGN)
|
||||
+ TLS_INIT_TCB_SIZE
|
||||
+ align);
|
||||
+ max_align);
|
||||
# elif TLS_DTV_AT_TP
|
||||
tlsblock = alloca (roundup (TLS_INIT_TCB_SIZE, phdr[cnt].p_align)
|
||||
tlsblock = alloca (roundup (TLS_INIT_TCB_SIZE,
|
||||
GL(dl_rtld_map).l_tls_align)
|
||||
+ GL(dl_rtld_map).l_tls_blocksize
|
||||
+ align);
|
||||
+ max_align);
|
||||
# else
|
||||
/* In case a model with a different layout for the TCB and DTV
|
||||
is defined add another #elif here and in the following #ifs. */
|
||||
# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
|
||||
# endif
|
||||
/* Align the TLS block. */
|
||||
tlsblock = (void *) (((uintptr_t) tlsblock + align - 1)
|
||||
& ~(align - 1));
|
||||
tlsblock = (void *) (((uintptr_t) tlsblock + max_align - 1)
|
||||
& ~(max_align - 1));
|
||||
|
||||
/* Initialize the dtv. */
|
||||
initdtv[0].counter = 1;
|
||||
@ -296,7 +299,7 @@ _dl_start_final (void *arg, struct link_map *bootstrap_map_p,
|
||||
initdtv[1].pointer = tlsblock;
|
||||
# elif TLS_DTV_AT_TP
|
||||
GL(dl_rtld_map).l_tls_offset = roundup (TLS_INIT_TCB_SIZE,
|
||||
phdr[cnt].p_align);
|
||||
GL(dl_rtld_map).l_tls_align);
|
||||
initdtv[1].pointer = (char *) tlsblock + GL(dl_rtld_map).l_tls_offset);
|
||||
# else
|
||||
# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
|
||||
@ -716,16 +719,18 @@ of this helper program; chances are you did not intend to run this program.\n\
|
||||
_dl_start_final. But the result is repeatable so do not
|
||||
check for this special but unimportant case. */
|
||||
GL(dl_loaded)->l_tls_blocksize = ph->p_memsz;
|
||||
GL(dl_loaded)->l_tls_align = ph->p_align;
|
||||
GL(dl_loaded)->l_tls_initimage_size = ph->p_filesz;
|
||||
GL(dl_loaded)->l_tls_initimage = (void *) (GL(dl_loaded)->l_addr
|
||||
+ ph->p_offset);
|
||||
/* This is the first element of the initialization image list.
|
||||
It is created as a circular list so that we can easily
|
||||
append to it. */
|
||||
GL(dl_initimage_list) = GL(dl_loaded)->l_tls_nextimage = GL(dl_loaded);
|
||||
We create the list as circular since we have to append at
|
||||
the end. */
|
||||
GL(dl_initimage_list) = GL(dl_loaded)->l_tls_nextimage
|
||||
= GL(dl_loaded)->l_tls_previmage = GL(dl_loaded);
|
||||
|
||||
/* This image get the ID one. */
|
||||
GL(dl_tls_module_cnt) = GL(dl_loaded)->l_tls_modid = 1;
|
||||
/* This image gets the ID one. */
|
||||
GL(dl_tls_max_dtv_idx) = GL(dl_loaded)->l_tls_modid = 1;
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
@ -736,7 +741,7 @@ of this helper program; chances are you did not intend to run this program.\n\
|
||||
/* We were invoked directly, so the program might not have a
|
||||
PT_INTERP. */
|
||||
_dl_rtld_libname.name = GL(dl_rtld_map).l_name;
|
||||
/* _dl_rtld_libname.next = NULL; Alread zero. */
|
||||
/* _dl_rtld_libname.next = NULL; Already zero. */
|
||||
GL(dl_rtld_map).l_libname = &_dl_rtld_libname;
|
||||
}
|
||||
else
|
||||
@ -973,7 +978,7 @@ of this helper program; chances are you did not intend to run this program.\n\
|
||||
|
||||
assert (GL(dl_rtld_map).l_prev->l_next == GL(dl_rtld_map).l_next);
|
||||
GL(dl_rtld_map).l_prev->l_next = &GL(dl_rtld_map);
|
||||
if (GL(dl_rtld_map).l_next)
|
||||
if (GL(dl_rtld_map).l_next != NULL)
|
||||
{
|
||||
assert (GL(dl_rtld_map).l_next->l_prev == GL(dl_rtld_map).l_prev);
|
||||
GL(dl_rtld_map).l_next->l_prev = &GL(dl_rtld_map);
|
||||
@ -1328,6 +1333,41 @@ of this helper program; chances are you did not intend to run this program.\n\
|
||||
we need it in the memory handling later. */
|
||||
GL(dl_initial_searchlist) = *GL(dl_main_searchlist);
|
||||
|
||||
#ifdef USE_TLS
|
||||
/* Now it is time to determine the layout of the static TLS block
|
||||
and allocate it for the initial thread. Note that we always
|
||||
allocate the static block, we never defer it even if no
|
||||
DF_STATIC_TLS bit is set. The reason is that we know glibc will
|
||||
use the static model. First add the dynamic linker to the list
|
||||
if it also uses TLS. */
|
||||
if (GL(dl_rtld_map).l_tls_blocksize != 0)
|
||||
{
|
||||
/* At to the list. */
|
||||
if (GL(dl_initimage_list) == NULL)
|
||||
GL(dl_initimage_list) = GL(dl_rtld_map).l_tls_nextimage
|
||||
= GL(dl_rtld_map).l_tls_previmage = &GL(dl_rtld_map);
|
||||
else
|
||||
{
|
||||
GL(dl_rtld_map).l_tls_nextimage
|
||||
= GL(dl_initimage_list)->l_tls_nextimage;
|
||||
GL(dl_rtld_map).l_tls_nextimage->l_tls_previmage
|
||||
= &GL(dl_rtld_map);
|
||||
GL(dl_rtld_map).l_tls_previmage = GL(dl_initimage_list);
|
||||
GL(dl_rtld_map).l_tls_previmage->l_tls_nextimage
|
||||
= &GL(dl_rtld_map);
|
||||
GL(dl_initimage_list) = &GL(dl_rtld_map);
|
||||
}
|
||||
|
||||
/* Assign a module ID. */
|
||||
GL(dl_rtld_map).l_tls_modid = _dl_next_tls_modid ();
|
||||
}
|
||||
|
||||
if (GL(dl_initimage_list) != NULL)
|
||||
/* This means we actually have some modules which use TLS.
|
||||
Computer the TLS offsets for the various blocks. */
|
||||
_dl_determine_tlsoffset (GL(dl_initimage_list)->l_tls_nextimage);
|
||||
#endif
|
||||
|
||||
{
|
||||
/* Initialize _r_debug. */
|
||||
struct r_debug *r = _dl_debug_initialize (GL(dl_rtld_map).l_addr);
|
||||
@ -1344,14 +1384,14 @@ of this helper program; chances are you did not intend to run this program.\n\
|
||||
|
||||
#else
|
||||
|
||||
if (l->l_info[DT_DEBUG])
|
||||
if (l->l_info[DT_DEBUG] != NULL)
|
||||
/* There is a DT_DEBUG entry in the dynamic section. Fill it in
|
||||
with the run-time address of the r_debug structure */
|
||||
l->l_info[DT_DEBUG]->d_un.d_ptr = (ElfW(Addr)) r;
|
||||
|
||||
/* Fill in the pointer in the dynamic linker's own dynamic section, in
|
||||
case you run gdb on the dynamic linker directly. */
|
||||
if (GL(dl_rtld_map).l_info[DT_DEBUG])
|
||||
if (GL(dl_rtld_map).l_info[DT_DEBUG] != NULL)
|
||||
GL(dl_rtld_map).l_info[DT_DEBUG]->d_un.d_ptr = (ElfW(Addr)) r;
|
||||
|
||||
#endif
|
||||
|
@ -256,20 +256,26 @@ struct link_map
|
||||
const ElfW(Sym) *ret;
|
||||
} l_lookup_cache;
|
||||
|
||||
#ifdef USE_TLS
|
||||
/* Thread-local storage related info. */
|
||||
|
||||
/* Next module in list of initialization images. */
|
||||
struct link_map *l_tls_nextimage;
|
||||
/* Previous module in list of initialization images. */
|
||||
struct link_map *l_tls_previmage;
|
||||
/* Start of the initialization image. */
|
||||
void *l_tls_initimage;
|
||||
/* Size of the initialization image. */
|
||||
size_t l_tls_initimage_size;
|
||||
/* Size of the TLS block. */
|
||||
size_t l_tls_blocksize;
|
||||
/* Alignment rquirement of the TLS block. */
|
||||
size_t l_tls_align;
|
||||
/* For objects present at startup time: offset in the static TLS block. */
|
||||
ptrdiff_t l_tls_offset;
|
||||
/* Index of the module in the dtv array. */
|
||||
size_t l_tls_modid;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct dl_phdr_info
|
||||
|
@ -1,3 +1,7 @@
|
||||
2002-02-06 Ulrich Drepper <drepper@redhat.com>
|
||||
|
||||
* sysdeps/i386/tls.h: Define THREAD_DTV.
|
||||
|
||||
2002-02-04 Ulrich Drepper <drepper@redhat.com>
|
||||
|
||||
* internals.h: Move thread descriptor definition...
|
||||
|
@ -90,6 +90,13 @@ typedef struct
|
||||
asm ("hlt"); \
|
||||
} while (0)
|
||||
|
||||
|
||||
/* Return the address of the dtv for the current thread. */
|
||||
# define THREAD_DTV() \
|
||||
({ struct _pthread_descr_struct *__descr; \
|
||||
THREAD_GETMEM (__descr, p_header.data.dtvp); })
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* tls.h */
|
||||
|
155
sysdeps/generic/dl-tls.c
Normal file
155
sysdeps/generic/dl-tls.c
Normal file
@ -0,0 +1,155 @@
|
||||
/* Thread-local storage handling in the ELF dynamic linker. Generic version.
|
||||
Copyright (C) 2002 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
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA. */
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include <dl-tls.h>
|
||||
#include <ldsodefs.h>
|
||||
|
||||
|
||||
/* We don't need any of this if TLS is not supported. */
|
||||
#ifdef USE_TLS
|
||||
|
||||
/* Value used for dtv entries for which the allocation is delayed. */
|
||||
# define TLS_DTV_UNALLOCATE ((void *) -1l)
|
||||
|
||||
|
||||
size_t
|
||||
internal_function
|
||||
_dl_next_tls_modid (void)
|
||||
{
|
||||
size_t result;
|
||||
|
||||
if (__builtin_expect (GL(dl_tls_dtv_gaps), false))
|
||||
{
|
||||
/* XXX If this method proves too costly we can optimize
|
||||
it to use a constant time method. But I don't think
|
||||
it's a problem. */
|
||||
struct link_map *runp = GL(dl_initimage_list);
|
||||
bool used[GL(dl_tls_max_dtv_idx)];
|
||||
|
||||
assert (runp != NULL);
|
||||
do
|
||||
{
|
||||
assert (runp->l_tls_modid > 0
|
||||
&& runp->l_tls_modid <= GL(dl_tls_max_dtv_idx));
|
||||
used[runp->l_tls_modid - 1] = true;
|
||||
}
|
||||
while ((runp = runp->l_tls_nextimage) != GL(dl_initimage_list));
|
||||
|
||||
result = 0;
|
||||
do
|
||||
/* The information about the gaps is pessimistic. It might be
|
||||
there are actually none. */
|
||||
if (result >= GL(dl_tls_max_dtv_idx))
|
||||
{
|
||||
/* Now we know there is actually no gap. Bump the maximum
|
||||
ID number and remember that there are no gaps. */
|
||||
result = ++GL(dl_tls_max_dtv_idx);
|
||||
GL(dl_tls_dtv_gaps) = false;
|
||||
break;
|
||||
}
|
||||
while (used[result++]);
|
||||
}
|
||||
else
|
||||
/* No gaps, allocate a new entry. */
|
||||
result = ++GL(dl_tls_max_dtv_idx);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
internal_function
|
||||
_dl_determine_tlsoffset (struct link_map *firstp)
|
||||
{
|
||||
struct link_map *runp = firstp;
|
||||
size_t max_align = 0;
|
||||
size_t offset;
|
||||
|
||||
# if TLS_TCB_AT_TP
|
||||
/* We simply start with zero. */
|
||||
offset = 0;
|
||||
|
||||
do
|
||||
{
|
||||
max_align = MAX (max_align, runp->l_tls_align);
|
||||
|
||||
/* Compute the offset of the next TLS block. */
|
||||
offset = roundup (offset + runp->l_tls_blocksize, runp->l_tls_align);
|
||||
|
||||
/* XXX For some architectures we perhaps should store the
|
||||
negative offset. */
|
||||
runp->l_tls_offset = offset;
|
||||
}
|
||||
while ((runp = runp->l_tls_nextimage) != firstp);
|
||||
# elif TLS_DTV_AT_TP
|
||||
struct link_map *lastp;
|
||||
|
||||
/* The first block starts right after the TCB. */
|
||||
offset = TLS_TCB_SIZE;
|
||||
max_align = runp->l_tls_align;
|
||||
runp->l_tls_offset = offset;
|
||||
lastp = runp;
|
||||
|
||||
while ((runp = runp->l_tls_nextimage) != firstp)
|
||||
{
|
||||
max_align = MAX (max_align, runp->l_tls_align);
|
||||
|
||||
/* Compute the offset of the next TLS block. */
|
||||
offset = roundup (offset + lastp->l_tls_blocksize, runp->l_tls_align);
|
||||
|
||||
runp->l_tls_offset = offset;
|
||||
}
|
||||
# else
|
||||
# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
|
||||
# endif
|
||||
}
|
||||
|
||||
|
||||
/* The __tls_get_addr function has two basic forms which differ in the
|
||||
arguments. The IA-64 form takes two parameters, the module ID and
|
||||
offset. The form used, among others, on IA-32 takes a reference to
|
||||
a special structure which contain the same information. The second
|
||||
form seems to be more often used (in the moment) so we default to
|
||||
it. Users of the IA-64 form have to provide adequate definitions
|
||||
of the following macros. */
|
||||
# ifndef GET_ADDR_ARGS
|
||||
# define GET_ADDR_ARGS struct tls_index *ti
|
||||
# endif
|
||||
# ifndef GET_ADDR_MODULE
|
||||
# define GET_ADDR_MODULE ti->ti_module
|
||||
# endif
|
||||
# ifndef GET_ADDR_OFFSET
|
||||
# define GET_ADDR_OFFSET ti->ti_offset
|
||||
# endif
|
||||
|
||||
|
||||
void *
|
||||
__tls_get_addr (GET_ADDR_ARGS)
|
||||
{
|
||||
dtv_t *dtv = THREAD_DTV ();
|
||||
|
||||
if (dtv[GET_ADDR_MODULE].pointer == TLS_DTV_UNALLOCATE)
|
||||
/* XXX */;
|
||||
|
||||
return (char *) dtv[GET_ADDR_MODULE].pointer + GET_ADDR_OFFSET;
|
||||
}
|
||||
|
||||
#endif /* use TLS */
|
2
sysdeps/generic/dl-tls.h
Normal file
2
sysdeps/generic/dl-tls.h
Normal file
@ -0,0 +1,2 @@
|
||||
/* There has to be an architecture specific version of this file. */
|
||||
#error "architecture-specific version of <dl-tls.h> missing"
|
@ -22,6 +22,7 @@
|
||||
|
||||
#include <features.h>
|
||||
|
||||
#include <stdbool.h>
|
||||
#define __need_size_t
|
||||
#define __need_NULL
|
||||
#include <stddef.h>
|
||||
@ -230,7 +231,7 @@ struct rtld_global
|
||||
#define DL_DEBUG_RELOC (1 << 5)
|
||||
#define DL_DEBUG_FILES (1 << 6)
|
||||
#define DL_DEBUG_STATISTICS (1 << 7)
|
||||
/* This one is used only internally. */
|
||||
/* These two are used only internally. */
|
||||
#define DL_DEBUG_HELP (1 << 8)
|
||||
#define DL_DEBUG_PRELINK (1 << 9)
|
||||
|
||||
@ -293,8 +294,10 @@ struct rtld_global
|
||||
initialize new TLS blocks. */
|
||||
EXTERN struct link_map *_dl_initimage_list;
|
||||
|
||||
/* Count the number of modules which define TLS data. */
|
||||
EXTERN size_t _dl_tls_module_cnt;
|
||||
/* Highest dtv index currently needed. */
|
||||
EXTERN size_t _dl_tls_max_dtv_idx;
|
||||
/* Flag signalling whether there are gaps in the module ID allocation. */
|
||||
EXTERN bool _dl_tls_dtv_gaps;
|
||||
#endif
|
||||
|
||||
/* Name of the shared object to be profiled (if any). */
|
||||
@ -651,6 +654,14 @@ extern void _dl_sysdep_start_cleanup (void)
|
||||
internal_function;
|
||||
|
||||
|
||||
/* Determine next available module ID. */
|
||||
extern size_t _dl_next_tls_modid (void) internal_function;
|
||||
|
||||
/* Calculate offset of the TLS blocks in the static TLS block. */
|
||||
extern void _dl_determine_tlsoffset (struct link_map *firstp)
|
||||
internal_function;
|
||||
|
||||
|
||||
__END_DECLS
|
||||
|
||||
#endif /* ldsodefs.h */
|
||||
|
47
sysdeps/i386/dl-tls.h
Normal file
47
sysdeps/i386/dl-tls.h
Normal file
@ -0,0 +1,47 @@
|
||||
/* Thread-local storage handling in the ELF dynamic linker. i386 version.
|
||||
Copyright (C) 2002 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
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA. */
|
||||
|
||||
/* Type used for the representation of TLS information in the GOT. */
|
||||
struct tls_index
|
||||
{
|
||||
unsigned long int ti_module;
|
||||
unsigned long int ti_offset;
|
||||
};
|
||||
|
||||
|
||||
/* This is the prototype for the GNU version. */
|
||||
extern void *___tls_get_addr (struct tls_index *ti)
|
||||
__attribute__ ((__regparm__ (1)));
|
||||
|
||||
/* The special thing about the x86 TLS ABI is that we have two
|
||||
variants of the __tls_get_addr function with different calling
|
||||
conventions. The GNU version, which we are mostly concerned here,
|
||||
takes the parameter in a register. The name is changed by adding
|
||||
an additional underscore at the beginning. The Sun version uses
|
||||
the normal calling convention. */
|
||||
void *
|
||||
__tls_get_addr (struct tls_index *ti)
|
||||
{
|
||||
return ___tls_get_addr (ti);
|
||||
}
|
||||
|
||||
|
||||
/* Prepare using the definition of __tls_get_addr in the generic
|
||||
version of this file. */
|
||||
#define __tls_get_addr __attribute__ ((__regparm__ (1))) ___tls_get_addr
|
Loading…
Reference in New Issue
Block a user