summaryrefslogtreecommitdiff
path: root/libpthread/linuxthreads_db/td_thr_tls_get_addr.c
diff options
context:
space:
mode:
Diffstat (limited to 'libpthread/linuxthreads_db/td_thr_tls_get_addr.c')
-rw-r--r--libpthread/linuxthreads_db/td_thr_tls_get_addr.c36
1 files changed, 30 insertions, 6 deletions
diff --git a/libpthread/linuxthreads_db/td_thr_tls_get_addr.c b/libpthread/linuxthreads_db/td_thr_tls_get_addr.c
index 892acba6b..ac4d706c4 100644
--- a/libpthread/linuxthreads_db/td_thr_tls_get_addr.c
+++ b/libpthread/linuxthreads_db/td_thr_tls_get_addr.c
@@ -20,24 +20,48 @@
#include <link.h>
#include "thread_dbP.h"
+/* Value used for dtv entries for which the allocation is delayed. */
+# define TLS_DTV_UNALLOCATED ((void *) -1l)
+
+
td_err_e
td_thr_tls_get_addr (const td_thrhandle_t *th __attribute__ ((unused)),
void *map_address __attribute__ ((unused)),
size_t offset __attribute__ ((unused)),
void **address __attribute__ ((unused)))
{
-#ifdef __UCLIBC_HAS_TLS__
- /* Read the module ID from the link_map. */
+#if defined(USE_TLS) && USE_TLS
size_t modid;
+ union dtv pdtv, *dtvp;
+
+ LOG ("td_thr_tls_get_addr");
+
+ /* Get the DTV pointer from the thread descriptor. */
+ if (ps_pdread (th->th_ta_p->ph,
+ &((struct _pthread_descr_struct *) th->th_unique)->p_header.data.dtvp,
+ &dtvp, sizeof dtvp) != PS_OK)
+ return TD_ERR; /* XXX Other error value? */
+
+ /* Read the module ID from the link_map. */
if (ps_pdread (th->th_ta_p->ph,
&((struct link_map *) map_address)->l_tls_modid,
&modid, sizeof modid) != PS_OK)
return TD_ERR; /* XXX Other error value? */
- td_err_e result = td_thr_tlsbase (th, modid, address);
- if (result == TD_OK)
- *address += offset;
- return result;
+ /* Get the corresponding entry in the DTV. */
+ if (ps_pdread (th->th_ta_p->ph, dtvp + modid,
+ &pdtv, sizeof (union dtv)) != PS_OK)
+ return TD_ERR; /* XXX Other error value? */
+
+ /* It could be that the memory for this module is not allocated for
+ the given thread. */
+ if (pdtv.pointer == TLS_DTV_UNALLOCATED)
+ /* There is not much we can do. */
+ return TD_NOTALLOC;
+
+ *address = (char *) pdtv.pointer + offset;
+
+ return TD_OK;
#else
return TD_ERR;
#endif