1ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <config.h> 2ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <pthread.h> 3ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <stdio.h> 4ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <unistd.h> 5ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <time.h> 6ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 7ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifdef HAVE_TLS 8ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 9ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define COUNT 10 10ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 11ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int race; 12ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic __thread int local; 13ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown__thread int global; 14ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownextern __thread int static_extern; 15ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownextern __thread int so_extern; 16ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 17ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* deliberate failure */ 18ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int *test_race(void) 19ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 20ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return ∽̱ 21ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 22ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 23ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int *test_local(void) 24ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 25ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return &local; 26ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 27ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 28ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int *test_global(void) 29ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 30ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return &global; 31ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 32ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 33ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int *test_static_extern(void) 34ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 35ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return &static_extern; 36ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 37ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 38ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int *test_so_extern(void) 39ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 40ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return &so_extern; 41ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 42ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 43b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic const struct timespec awhile = { 0, 200000000 }; 44ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 45ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef int *(*func_t)(void); 46ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstruct testcase { 47ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown const char *name; 48ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown func_t func; 49ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}; 50ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 51ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void *tls_ptr(void *p) 52ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 53ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct testcase *test = (struct testcase *)p; 54ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown int *ip = (*test->func)(); 55ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown int here = 0; 56ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown int i; 57ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 58ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for(i = 0; i < COUNT; i++) { 59ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown int a = (*ip)++; 60ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown int b = here++; 61ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (a != b) 62ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown printf("tls_ptr: case \"%s\" has mismatch: *ip=%d here=%d\n", 63ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown test->name, a, b); 64ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown nanosleep(&awhile, 0); 65ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 66ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 67ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return 0; 68ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 69ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 70ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint *test_so_extern(void); 71ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint *test_so_local(void); 72ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint *test_so_global(void); 73ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 74ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic const struct testcase tests[] = { 75ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define T(t) { #t, test_##t } 76ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown T(race), 77ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown T(local), 78ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown T(global), 79ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown T(static_extern), 80ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown T(so_extern), 81ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown T(so_local), 82ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown T(so_global), 83ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#undef T 84ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}; 85ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 86ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define NTESTS (sizeof(tests)/sizeof(*tests)) 87ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 88ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint main() 89ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 90ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_t threads[NTESTS*2]; 91ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown int curthread = 0; 92ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown static 93ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown int i; 94ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 95ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for(i = 0; i < NTESTS; i++) { 96ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_create(&threads[curthread++], NULL, tls_ptr, (void *)&tests[i]); 97ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_create(&threads[curthread++], NULL, tls_ptr, (void *)&tests[i]); 98ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 99ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for(i = 0; i < curthread; i++) 101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_join(threads[i], NULL); 102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return 0; 104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else 106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint main() 107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown printf("FAILED: no compiler support for __thread\n"); 109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return 1; 110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 112