diff options
author | Stefan Liebler <stli@linux.ibm.com> | 2019-02-06 09:06:34 +0100 |
---|---|---|
committer | Stefan Liebler <stli@linux.ibm.com> | 2019-02-06 09:06:34 +0100 |
commit | bc79db3fd487daea36e7c130f943cfb9826a41b4 (patch) | |
tree | 5b5834de499eeade464a532b0a9c7f7d7087622b /nptl/tst-tls1.c | |
parent | f1ac7455831546e5dca0ed98fe8af2686fae7ce6 (diff) | |
download | glibc-bc79db3fd487daea36e7c130f943cfb9826a41b4.zip glibc-bc79db3fd487daea36e7c130f943cfb9826a41b4.tar.gz glibc-bc79db3fd487daea36e7c130f943cfb9826a41b4.tar.bz2 |
Fix alignment of TLS variables for tls variant TLS_TCB_AT_TP [BZ #23403]
The alignment of TLS variables is wrong if accessed from within a thread
for architectures with tls variant TLS_TCB_AT_TP.
For the main thread the static tls data is properly aligned.
For other threads the alignment depends on the alignment of the thread
pointer as the static tls data is located relative to this pointer.
This patch adds this alignment for TLS_TCB_AT_TP variants in the same way
as it is already done for TLS_DTV_AT_TP. The thread pointer is also already
properly aligned if the user provides its own stack for the new thread.
This patch extends the testcase nptl/tst-tls1.c in order to check the
alignment of the tls variables and it adds a pthread_create invocation
with a user provided stack.
The test itself is migrated from test-skeleton.c to test-driver.c
and the missing support functions xpthread_attr_setstack and xposix_memalign
are added.
ChangeLog:
[BZ #23403]
* nptl/allocatestack.c (allocate_stack): Align pointer pd for
TLS_TCB_AT_TP tls variant.
* nptl/tst-tls1.c: Migrate to support/test-driver.c.
Add alignment checks.
* support/Makefile (libsupport-routines): Add xposix_memalign and
xpthread_setstack.
* support/support.h: Add xposix_memalign.
* support/xthread.h: Add xpthread_attr_setstack.
* support/xposix_memalign.c: New File.
* support/xpthread_attr_setstack.c: Likewise.
Diffstat (limited to 'nptl/tst-tls1.c')
-rw-r--r-- | nptl/tst-tls1.c | 90 |
1 files changed, 49 insertions, 41 deletions
diff --git a/nptl/tst-tls1.c b/nptl/tst-tls1.c index 00489e2..1a91522 100644 --- a/nptl/tst-tls1.c +++ b/nptl/tst-tls1.c @@ -19,12 +19,16 @@ #include <pthread.h> #include <stdio.h> #include <stdlib.h> - +#include <stdint.h> +#include <inttypes.h> +#include <support/support.h> +#include <support/check.h> +#include <support/xthread.h> struct test_s { - int a; - int b; + __attribute__ ((aligned(0x20))) int a; + __attribute__ ((aligned(0x200))) int b; }; #define INIT_A 1 @@ -36,15 +40,34 @@ __thread struct test_s s __attribute__ ((tls_model ("initial-exec"))) = .b = INIT_B }; +/* Use noinline in combination with not static to ensure that the + alignment check is really done. Otherwise it was optimized out! */ +__attribute__ ((noinline)) void +check_alignment (const char *thr_name, const char *ptr_name, + int *ptr, int alignment) +{ + uintptr_t offset_aligment = ((uintptr_t) ptr) & (alignment - 1); + if (offset_aligment) + { + FAIL_EXIT1 ("%s (%p) is not 0x%x-byte aligned in %s thread\n", + ptr_name, ptr, alignment, thr_name); + } +} + +static void +check_s (const char *thr_name) +{ + if (s.a != INIT_A || s.b != INIT_B) + FAIL_EXIT1 ("initial value of s in %s thread wrong\n", thr_name); + + check_alignment (thr_name, "s.a", &s.a, 0x20); + check_alignment (thr_name, "s.b", &s.b, 0x200); +} static void * tf (void *arg) { - if (s.a != INIT_A || s.b != INIT_B) - { - puts ("initial value of s in child thread wrong"); - exit (1); - } + check_s ("child"); ++s.a; @@ -55,25 +78,14 @@ tf (void *arg) int do_test (void) { - if (s.a != INIT_A || s.b != INIT_B) - { - puts ("initial value of s in main thread wrong"); - exit (1); - } + check_s ("main"); pthread_attr_t a; - if (pthread_attr_init (&a) != 0) - { - puts ("attr_init failed"); - exit (1); - } + xpthread_attr_init (&a); - if (pthread_attr_setstacksize (&a, 1 * 1024 * 1024) != 0) - { - puts ("attr_setstacksize failed"); - return 1; - } +#define STACK_SIZE (1 * 1024 * 1024) + xpthread_attr_setstacksize (&a, STACK_SIZE); #define N 10 int i; @@ -83,29 +95,25 @@ do_test (void) pthread_t th[M]; int j; for (j = 0; j < M; ++j, ++s.a) - if (pthread_create (&th[j], &a, tf, NULL) != 0) - { - puts ("pthread_create failed"); - exit (1); - } + th[j] = xpthread_create (&a, tf, NULL); for (j = 0; j < M; ++j) - if (pthread_join (th[j], NULL) != 0) - { - puts ("pthread_join failed"); - exit (1); - } + xpthread_join (th[j]); } - if (pthread_attr_destroy (&a) != 0) - { - puts ("attr_destroy failed"); - exit (1); - } + /* Also check the alignment of the tls variables if a misaligned stack is + specified. */ + pthread_t th; + void *thr_stack = NULL; + thr_stack = xposix_memalign (0x200, STACK_SIZE + 1); + xpthread_attr_setstack (&a, thr_stack + 1, STACK_SIZE); + th = xpthread_create (&a, tf, NULL); + xpthread_join (th); + free (thr_stack); + + xpthread_attr_destroy (&a); return 0; } - -#define TEST_FUNCTION do_test () -#include "../test-skeleton.c" +#include <support/test-driver.c> |