(linenum→info "unix/slp.c:2238")

glibc/2.7/nptl_db/td_thr_tlsbase.c

    1: /* Locate TLS data for a thread.
    2:    Copyright (C) 2003, 2006, 2007 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 "thread_dbP.h"
   21: 
   22: td_err_e
   23: td_thr_tlsbase (const td_thrhandle_t *th,
   24:                 unsigned long int modid,
   25:                 psaddr_t *base)
   26: {
   27:   td_err_e err;
   28:   psaddr_t dtv, dtvslot, dtvptr;
   29: 
   30:   if (modid < 1)
   31:     return TD_NOTLS;
   32: 
   33:   psaddr_t pd = th->th_unique;
   34:   if (pd == 0)
   35:     {
   36:       /* This is the fake handle for the main thread before libpthread
   37:          initialization.  We are using 0 for its th_unique because we can't
   38:          trust that its thread register has been initialized.  But we need
   39:          a real pointer to have any TLS access work.  In case of dlopen'd
   40:          libpthread, initialization might not be for quite some time.  So
   41:          try looking up the thread register now.  Worst case, it's nonzero
   42:          uninitialized garbage and we get bogus results for TLS access
   43:          attempted too early.  Tough.  */
   44: 
   45:       td_thrhandle_t main_th;
   46:       err = __td_ta_lookup_th_unique (th->th_ta_p, ps_getpid (th->th_ta_p->ph),
   47:                                       &main_th);
   48:       if (err == 0)
   49:         pd = main_th.th_unique;
   50:       if (pd == 0)
   51:         return TD_TLSDEFER;
   52:     }
   53: 
   54:   /* Get the DTV pointer from the thread descriptor.  */
   55:   err = DB_GET_FIELD (dtv, th->th_ta_p, pd, pthread, dtvp, 0);
   56:   if (err != TD_OK)
   57:     return err;
   58: 
   59:   /* Find the corresponding entry in the DTV.  */
   60:   err = DB_GET_FIELD_ADDRESS (dtvslot, th->th_ta_p, dtv, dtv, dtv, modid);
   61:   if (err != TD_OK)
   62:     return err;
   63: 
   64:   /* Extract the TLS block address from that DTV slot.  */
   65:   err = DB_GET_FIELD (dtvptr, th->th_ta_p, dtvslot, dtv_t, pointer_val, 0);
   66:   if (err != TD_OK)
   67:     return err;
   68: 
   69:   /* It could be that the memory for this module is not allocated for
   70:      the given thread.  */
   71:   if ((uintptr_t) dtvptr & 1)
   72:     return TD_TLSDEFER;
   73: 
   74:   *base = dtvptr;
   75:   return TD_OK;
   76: }
Syntax (Markdown)