Back to index

glibc  2.9
td_thr_tlsbase.c
Go to the documentation of this file.
00001 /* Locate TLS data for a thread.
00002    Copyright (C) 2003, 2006, 2007 Free Software Foundation, Inc.
00003    This file is part of the GNU C Library.
00004 
00005    The GNU C Library is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Lesser General Public
00007    License as published by the Free Software Foundation; either
00008    version 2.1 of the License, or (at your option) any later version.
00009 
00010    The GNU C Library is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Lesser General Public License for more details.
00014 
00015    You should have received a copy of the GNU Lesser General Public
00016    License along with the GNU C Library; if not, write to the Free
00017    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00018    02111-1307 USA.  */
00019 
00020 #include "thread_dbP.h"
00021 
00022 td_err_e
00023 td_thr_tlsbase (const td_thrhandle_t *th,
00024               unsigned long int modid,
00025               psaddr_t *base)
00026 {
00027   td_err_e err;
00028   psaddr_t dtv, dtvslot, dtvptr;
00029 
00030   if (modid < 1)
00031     return TD_NOTLS;
00032 
00033   psaddr_t pd = th->th_unique;
00034   if (pd == 0)
00035     {
00036       /* This is the fake handle for the main thread before libpthread
00037         initialization.  We are using 0 for its th_unique because we can't
00038         trust that its thread register has been initialized.  But we need
00039         a real pointer to have any TLS access work.  In case of dlopen'd
00040         libpthread, initialization might not be for quite some time.  So
00041         try looking up the thread register now.  Worst case, it's nonzero
00042         uninitialized garbage and we get bogus results for TLS access
00043         attempted too early.  Tough.  */
00044 
00045       td_thrhandle_t main_th;
00046       err = __td_ta_lookup_th_unique (th->th_ta_p, ps_getpid (th->th_ta_p->ph),
00047                                   &main_th);
00048       if (err == 0)
00049        pd = main_th.th_unique;
00050       if (pd == 0)
00051        return TD_TLSDEFER;
00052     }
00053 
00054   /* Get the DTV pointer from the thread descriptor.  */
00055   err = DB_GET_FIELD (dtv, th->th_ta_p, pd, pthread, dtvp, 0);
00056   if (err != TD_OK)
00057     return err;
00058 
00059   /* Find the corresponding entry in the DTV.  */
00060   err = DB_GET_FIELD_ADDRESS (dtvslot, th->th_ta_p, dtv, dtv, dtv, modid);
00061   if (err != TD_OK)
00062     return err;
00063 
00064   /* Extract the TLS block address from that DTV slot.  */
00065   err = DB_GET_FIELD (dtvptr, th->th_ta_p, dtvslot, dtv_t, pointer_val, 0);
00066   if (err != TD_OK)
00067     return err;
00068 
00069   /* It could be that the memory for this module is not allocated for
00070      the given thread.  */
00071   if ((uintptr_t) dtvptr & 1)
00072     return TD_TLSDEFER;
00073 
00074   *base = dtvptr;
00075   return TD_OK;
00076 }