Use INTERNAL_SYSCALL.
[glibc.git] / nptl_db / td_thr_tsd.c
blobd1a54537ff8da4e0b8c6d9bf322215ed74f29e87
1 /* Get a thread-specific data pointer for a thread.
2 Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4 Contributed by Ulrich Drepper <drepper@redhat.com>, 1999.
6 The GNU C Library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2.1 of the License, or (at your option) any later version.
11 The GNU C Library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public
17 License along with the GNU C Library; if not, write to the Free
18 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19 02111-1307 USA. */
21 #include "thread_dbP.h"
24 td_err_e
25 td_thr_tsd (const td_thrhandle_t *th, const thread_key_t tk, void **data)
27 LOG ("td_thr_tsd");
29 /* Check correct value of key. */
30 if (tk >= th->th_ta_p->pthread_keys_max)
31 return TD_BADKEY;
33 /* Get the key entry. */
34 uintptr_t seq;
35 if (ps_pdread (th->th_ta_p->ph, &th->th_ta_p->keys[tk].seq, &seq,
36 sizeof (uintptr_t)) != PS_OK)
37 return TD_ERR; /* XXX Other error value? */
39 /* Fail if this key is not at all used. */
40 if (KEY_UNUSED (seq))
41 return TD_BADKEY;
43 /* Compute the indeces. */
44 int pthread_key_2ndlevel_size = th->th_ta_p->pthread_key_2ndlevel_size;
45 unsigned int idx1st = tk / pthread_key_2ndlevel_size;
46 unsigned int idx2nd = tk % pthread_key_2ndlevel_size;
48 struct pthread_key_data *level1;
49 if (ps_pdread (th->th_ta_p->ph,
50 &((struct pthread *) th->th_unique)->specific[idx1st],
51 &level1, sizeof (level1)) != PS_OK)
52 return TD_ERR; /* XXX Other error value? */
54 /* Check the pointer to the second level array. */
55 if (level1 == NULL)
56 return TD_NOTSD;
58 struct pthread_key_data level2;
59 if (ps_pdread (th->th_ta_p->ph, &level1[idx2nd], &level2,
60 sizeof (level2)) != PS_OK)
61 return TD_ERR; /* XXX Other error value? */
63 /* Check whether the data is valid. */
64 if (level2.seq != seq)
65 return TD_NOTSD;
67 if (level2.data != NULL)
68 *data = level2.data;
70 return TD_OK;