Back to index

glibc  2.9
td_thr_tsd.c
Go to the documentation of this file.
00001 /* Get a thread-specific data pointer for a thread.
00002    Copyright (C) 1999,2001,2002,2003 Free Software Foundation, Inc.
00003    This file is part of the GNU C Library.
00004    Contributed by Ulrich Drepper <drepper@redhat.com>, 1999.
00005 
00006    The GNU C Library is free software; you can redistribute it and/or
00007    modify it under the terms of the GNU Lesser General Public
00008    License as published by the Free Software Foundation; either
00009    version 2.1 of the License, or (at your option) any later version.
00010 
00011    The GNU C Library is distributed in the hope that it will be useful,
00012    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014    Lesser General Public License for more details.
00015 
00016    You should have received a copy of the GNU Lesser General Public
00017    License along with the GNU C Library; if not, write to the Free
00018    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00019    02111-1307 USA.  */
00020 
00021 #include "thread_dbP.h"
00022 
00023 
00024 td_err_e
00025 td_thr_tsd (const td_thrhandle_t *th, const thread_key_t tk, void **data)
00026 {
00027   td_err_e err;
00028   psaddr_t tk_seq, level1, level2, seq, value;
00029   void *copy;
00030   uint32_t pthread_key_2ndlevel_size, idx1st, idx2nd;
00031 
00032   LOG ("td_thr_tsd");
00033 
00034   /* Get the key entry.  */
00035   err = DB_GET_VALUE (tk_seq, th->th_ta_p, __pthread_keys, tk);
00036   if (err == TD_NOAPLIC)
00037     return TD_BADKEY;
00038   if (err != TD_OK)
00039     return err;
00040 
00041   /* Fail if this key is not at all used.  */
00042   if (((uintptr_t) tk_seq & 1) == 0)
00043     return TD_BADKEY;
00044 
00045   /* This makes sure we have the size information on hand.  */
00046   err = DB_GET_FIELD_ADDRESS (level2, th->th_ta_p, 0, pthread_key_data_level2,
00047                            data, 1);
00048   if (err != TD_OK)
00049     return err;
00050 
00051   /* Compute the indeces.  */
00052   pthread_key_2ndlevel_size
00053     = DB_DESC_NELEM (th->th_ta_p->ta_field_pthread_key_data_level2_data);
00054   idx1st = tk / pthread_key_2ndlevel_size;
00055   idx2nd = tk % pthread_key_2ndlevel_size;
00056 
00057   /* Now fetch the first level pointer.  */
00058   err = DB_GET_FIELD (level1, th->th_ta_p, th->th_unique, pthread,
00059                     specific, idx1st);
00060   if (err == TD_NOAPLIC)
00061     return TD_DBERR;
00062   if (err != TD_OK)
00063     return err;
00064 
00065   /* Check the pointer to the second level array.  */
00066   if (level1 == 0)
00067     return TD_NOTSD;
00068 
00069   /* Locate the element within the second level array.  */
00070   err = DB_GET_FIELD_ADDRESS (level2, th->th_ta_p,
00071                            level1, pthread_key_data_level2, data, idx2nd);
00072   if (err == TD_NOAPLIC)
00073     return TD_DBERR;
00074   if (err != TD_OK)
00075     return err;
00076 
00077   /* Now copy in that whole structure.  */
00078   err = DB_GET_STRUCT (copy, th->th_ta_p, level2, pthread_key_data);
00079   if (err != TD_OK)
00080     return err;
00081 
00082   /* Check whether the data is valid.  */
00083   err = DB_GET_FIELD_LOCAL (seq, th->th_ta_p, copy, pthread_key_data, seq, 0);
00084   if (err != TD_OK)
00085     return err;
00086   if (seq != tk_seq)
00087     return TD_NOTSD;
00088 
00089   /* Finally, fetch the value.  */
00090   err = DB_GET_FIELD_LOCAL (value, th->th_ta_p, copy, pthread_key_data,
00091                          data, 0);
00092   if (err == TD_OK)
00093     *data = value;
00094 
00095   return err;
00096 }