1b5f6f51ebcac183818061bf53427a3e7808ef10dsewardj#include <config.h>
247735af6c44b5f206d5e418aac87a1dbdf9df185fitzhardinge#include <pthread.h>
347735af6c44b5f206d5e418aac87a1dbdf9df185fitzhardinge#include <stdio.h>
447735af6c44b5f206d5e418aac87a1dbdf9df185fitzhardinge#include <unistd.h>
547735af6c44b5f206d5e418aac87a1dbdf9df185fitzhardinge#include <time.h>
647735af6c44b5f206d5e418aac87a1dbdf9df185fitzhardinge
7b5f6f51ebcac183818061bf53427a3e7808ef10dsewardj#ifdef HAVE_TLS
8b5f6f51ebcac183818061bf53427a3e7808ef10dsewardj
947735af6c44b5f206d5e418aac87a1dbdf9df185fitzhardinge#define COUNT 10
1047735af6c44b5f206d5e418aac87a1dbdf9df185fitzhardinge
1147735af6c44b5f206d5e418aac87a1dbdf9df185fitzhardingestatic int race;
1247735af6c44b5f206d5e418aac87a1dbdf9df185fitzhardingestatic __thread int local;
1347735af6c44b5f206d5e418aac87a1dbdf9df185fitzhardinge__thread int global;
1447735af6c44b5f206d5e418aac87a1dbdf9df185fitzhardingeextern __thread int static_extern;
1547735af6c44b5f206d5e418aac87a1dbdf9df185fitzhardingeextern __thread int so_extern;
1647735af6c44b5f206d5e418aac87a1dbdf9df185fitzhardinge
1747735af6c44b5f206d5e418aac87a1dbdf9df185fitzhardinge/* deliberate failure */
1847735af6c44b5f206d5e418aac87a1dbdf9df185fitzhardingestatic int *test_race(void)
1947735af6c44b5f206d5e418aac87a1dbdf9df185fitzhardinge{
2047735af6c44b5f206d5e418aac87a1dbdf9df185fitzhardinge	return &race;
2147735af6c44b5f206d5e418aac87a1dbdf9df185fitzhardinge}
2247735af6c44b5f206d5e418aac87a1dbdf9df185fitzhardinge
2347735af6c44b5f206d5e418aac87a1dbdf9df185fitzhardingestatic int *test_local(void)
2447735af6c44b5f206d5e418aac87a1dbdf9df185fitzhardinge{
2547735af6c44b5f206d5e418aac87a1dbdf9df185fitzhardinge	return &local;
2647735af6c44b5f206d5e418aac87a1dbdf9df185fitzhardinge}
2747735af6c44b5f206d5e418aac87a1dbdf9df185fitzhardinge
2847735af6c44b5f206d5e418aac87a1dbdf9df185fitzhardingestatic int *test_global(void)
2947735af6c44b5f206d5e418aac87a1dbdf9df185fitzhardinge{
3047735af6c44b5f206d5e418aac87a1dbdf9df185fitzhardinge	return &global;
3147735af6c44b5f206d5e418aac87a1dbdf9df185fitzhardinge}
3247735af6c44b5f206d5e418aac87a1dbdf9df185fitzhardinge
3347735af6c44b5f206d5e418aac87a1dbdf9df185fitzhardingestatic int *test_static_extern(void)
3447735af6c44b5f206d5e418aac87a1dbdf9df185fitzhardinge{
3547735af6c44b5f206d5e418aac87a1dbdf9df185fitzhardinge	return &static_extern;
3647735af6c44b5f206d5e418aac87a1dbdf9df185fitzhardinge}
3747735af6c44b5f206d5e418aac87a1dbdf9df185fitzhardinge
3847735af6c44b5f206d5e418aac87a1dbdf9df185fitzhardingestatic int *test_so_extern(void)
3947735af6c44b5f206d5e418aac87a1dbdf9df185fitzhardinge{
4047735af6c44b5f206d5e418aac87a1dbdf9df185fitzhardinge	return &so_extern;
4147735af6c44b5f206d5e418aac87a1dbdf9df185fitzhardinge}
4247735af6c44b5f206d5e418aac87a1dbdf9df185fitzhardinge
43bcc95cfa30412ef9afa11005e365db3b043c9f6bflorianstatic const struct timespec awhile = { 0, 200000000 };
4447735af6c44b5f206d5e418aac87a1dbdf9df185fitzhardinge
4547735af6c44b5f206d5e418aac87a1dbdf9df185fitzhardingetypedef int *(*func_t)(void);
4647735af6c44b5f206d5e418aac87a1dbdf9df185fitzhardingestruct testcase {
4747735af6c44b5f206d5e418aac87a1dbdf9df185fitzhardinge	const char *name;
4847735af6c44b5f206d5e418aac87a1dbdf9df185fitzhardinge	func_t func;
491670b05a4a415dbfd75b1a120713b4a206bb719ephilippe        char pad[2 * (8 - sizeof(void*))];
5047735af6c44b5f206d5e418aac87a1dbdf9df185fitzhardinge};
5147735af6c44b5f206d5e418aac87a1dbdf9df185fitzhardingestatic void *tls_ptr(void *p)
5247735af6c44b5f206d5e418aac87a1dbdf9df185fitzhardinge{
5347735af6c44b5f206d5e418aac87a1dbdf9df185fitzhardinge	struct testcase *test = (struct testcase *)p;
5447735af6c44b5f206d5e418aac87a1dbdf9df185fitzhardinge	int *ip = (*test->func)();
5547735af6c44b5f206d5e418aac87a1dbdf9df185fitzhardinge	int here = 0;
5647735af6c44b5f206d5e418aac87a1dbdf9df185fitzhardinge	int i;
5747735af6c44b5f206d5e418aac87a1dbdf9df185fitzhardinge
5847735af6c44b5f206d5e418aac87a1dbdf9df185fitzhardinge	for(i = 0; i < COUNT; i++) {
5947735af6c44b5f206d5e418aac87a1dbdf9df185fitzhardinge		int a = (*ip)++;
6047735af6c44b5f206d5e418aac87a1dbdf9df185fitzhardinge		int b = here++;
6147735af6c44b5f206d5e418aac87a1dbdf9df185fitzhardinge		if (a != b)
6247735af6c44b5f206d5e418aac87a1dbdf9df185fitzhardinge			printf("tls_ptr: case \"%s\" has mismatch: *ip=%d here=%d\n",
6347735af6c44b5f206d5e418aac87a1dbdf9df185fitzhardinge			       test->name, a, b);
6447735af6c44b5f206d5e418aac87a1dbdf9df185fitzhardinge		nanosleep(&awhile, 0);
6547735af6c44b5f206d5e418aac87a1dbdf9df185fitzhardinge	}
6647735af6c44b5f206d5e418aac87a1dbdf9df185fitzhardinge
6747735af6c44b5f206d5e418aac87a1dbdf9df185fitzhardinge	return 0;
6847735af6c44b5f206d5e418aac87a1dbdf9df185fitzhardinge}
6947735af6c44b5f206d5e418aac87a1dbdf9df185fitzhardinge
7047735af6c44b5f206d5e418aac87a1dbdf9df185fitzhardingeint *test_so_extern(void);
7147735af6c44b5f206d5e418aac87a1dbdf9df185fitzhardingeint *test_so_local(void);
7247735af6c44b5f206d5e418aac87a1dbdf9df185fitzhardingeint *test_so_global(void);
7347735af6c44b5f206d5e418aac87a1dbdf9df185fitzhardinge
7447735af6c44b5f206d5e418aac87a1dbdf9df185fitzhardingestatic const struct testcase tests[] = {
7547735af6c44b5f206d5e418aac87a1dbdf9df185fitzhardinge#define T(t)	{ #t, test_##t }
7647735af6c44b5f206d5e418aac87a1dbdf9df185fitzhardinge	T(race),
7747735af6c44b5f206d5e418aac87a1dbdf9df185fitzhardinge	T(local),
7847735af6c44b5f206d5e418aac87a1dbdf9df185fitzhardinge	T(global),
7947735af6c44b5f206d5e418aac87a1dbdf9df185fitzhardinge	T(static_extern),
8047735af6c44b5f206d5e418aac87a1dbdf9df185fitzhardinge	T(so_extern),
8147735af6c44b5f206d5e418aac87a1dbdf9df185fitzhardinge	T(so_local),
8247735af6c44b5f206d5e418aac87a1dbdf9df185fitzhardinge	T(so_global),
8347735af6c44b5f206d5e418aac87a1dbdf9df185fitzhardinge#undef T
8447735af6c44b5f206d5e418aac87a1dbdf9df185fitzhardinge};
8547735af6c44b5f206d5e418aac87a1dbdf9df185fitzhardinge
8647735af6c44b5f206d5e418aac87a1dbdf9df185fitzhardinge#define NTESTS	(sizeof(tests)/sizeof(*tests))
8747735af6c44b5f206d5e418aac87a1dbdf9df185fitzhardinge
8847735af6c44b5f206d5e418aac87a1dbdf9df185fitzhardingeint main()
8947735af6c44b5f206d5e418aac87a1dbdf9df185fitzhardinge{
9047735af6c44b5f206d5e418aac87a1dbdf9df185fitzhardinge	pthread_t threads[NTESTS*2];
9147735af6c44b5f206d5e418aac87a1dbdf9df185fitzhardinge	int curthread = 0;
9247735af6c44b5f206d5e418aac87a1dbdf9df185fitzhardinge	static
9347735af6c44b5f206d5e418aac87a1dbdf9df185fitzhardinge	int i;
9447735af6c44b5f206d5e418aac87a1dbdf9df185fitzhardinge
9547735af6c44b5f206d5e418aac87a1dbdf9df185fitzhardinge	for(i = 0; i < NTESTS; i++) {
9647735af6c44b5f206d5e418aac87a1dbdf9df185fitzhardinge		pthread_create(&threads[curthread++], NULL, tls_ptr, (void *)&tests[i]);
9747735af6c44b5f206d5e418aac87a1dbdf9df185fitzhardinge		pthread_create(&threads[curthread++], NULL, tls_ptr, (void *)&tests[i]);
9847735af6c44b5f206d5e418aac87a1dbdf9df185fitzhardinge	}
9947735af6c44b5f206d5e418aac87a1dbdf9df185fitzhardinge
10047735af6c44b5f206d5e418aac87a1dbdf9df185fitzhardinge	for(i = 0; i < curthread; i++)
10147735af6c44b5f206d5e418aac87a1dbdf9df185fitzhardinge		pthread_join(threads[i], NULL);
10247735af6c44b5f206d5e418aac87a1dbdf9df185fitzhardinge
10347735af6c44b5f206d5e418aac87a1dbdf9df185fitzhardinge	return 0;
10447735af6c44b5f206d5e418aac87a1dbdf9df185fitzhardinge}
105b5f6f51ebcac183818061bf53427a3e7808ef10dsewardj#else
106b5f6f51ebcac183818061bf53427a3e7808ef10dsewardjint main()
107b5f6f51ebcac183818061bf53427a3e7808ef10dsewardj{
108b5f6f51ebcac183818061bf53427a3e7808ef10dsewardj	printf("FAILED: no compiler support for __thread\n");
109b5f6f51ebcac183818061bf53427a3e7808ef10dsewardj	return 1;
110b5f6f51ebcac183818061bf53427a3e7808ef10dsewardj}
111b5f6f51ebcac183818061bf53427a3e7808ef10dsewardj#endif
112