>From a63e13b24d619e4a6ac68436e159649298311fa5 Mon Sep 17 00:00:00 2001 From: Szabolcs Nagy Date: Wed, 11 Mar 2015 12:48:12 +0000 Subject: [PATCH 1/4] copy the dtv pointer to the end of the pthread struct for TLS_ABOVE_TP archs There are two main abi variants for thread local storage layout: (1) TLS is above the thread pointer at a fixed offset and the pthread struct is below that. So the end of the struct is at known offset. (2) the thread pointer points to the pthread struct and TLS starts below it. So the start of the struct is at known (zero) offset. Assembly code for the dynamic TLSDESC callback needs to access the dynamic thread vector (dtv) pointer which is currently at the front of the pthread struct. So in case of (1) the asm code needs to hard code the offset from the end of the struct which can easily break if the struct changes. This commit adds a copy of the dtv at the end of the struct. New members must not be added after dtv_copy, only before it. The size of the struct is increased a bit, but there is opportunity for size optimizations. --- src/env/__init_tls.c | 2 +- src/internal/pthread_impl.h | 1 + src/ldso/dynlink.c | 6 +++--- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/env/__init_tls.c b/src/env/__init_tls.c index b0dad42..e651c7a 100644 --- a/src/env/__init_tls.c +++ b/src/env/__init_tls.c @@ -54,7 +54,7 @@ void *__copy_tls(unsigned char *mem) td = (pthread_t)mem; mem -= T.size; #endif - td->dtv = dtv; + td->dtv = td->dtv_copy = dtv; dtv[1] = mem; memcpy(mem, T.image, T.len); return td; diff --git a/src/internal/pthread_impl.h b/src/internal/pthread_impl.h index 441b075..7c352bc 100644 --- a/src/internal/pthread_impl.h +++ b/src/internal/pthread_impl.h @@ -45,6 +45,7 @@ struct pthread { volatile int startlock[2]; unsigned long sigmask[_NSIG/8/sizeof(long)]; void *stdio_locks; + void **dtv_copy; }; struct __timer { diff --git a/src/ldso/dynlink.c b/src/ldso/dynlink.c index ca10199..b0d5ff4 100644 --- a/src/ldso/dynlink.c +++ b/src/ldso/dynlink.c @@ -1015,7 +1015,7 @@ void *__copy_tls(unsigned char *mem) dtv[0] = (void *)tls_cnt; if (!tls_cnt) { td = (void *)(dtv+1); - td->dtv = dtv; + td->dtv = td->dtv_copy = dtv; return td; } @@ -1041,7 +1041,7 @@ void *__copy_tls(unsigned char *mem) memcpy(dtv[p->tls_id], p->tls_image, p->tls_len); } #endif - td->dtv = dtv; + td->dtv = td->dtv_copy = dtv; return td; } @@ -1071,7 +1071,7 @@ void *__tls_get_new(size_t *v) memcpy(newdtv, self->dtv, ((size_t)self->dtv[0]+1) * sizeof(void *)); newdtv[0] = (void *)v[0]; - self->dtv = newdtv; + self->dtv = self->dtv_copy = newdtv; } /* Get new TLS memory from all new DSOs up to the requested one */ -- 1.7.9.5