
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: }