1*b725ae77Skettenis /* BeginSourceFile tls.c
2*b725ae77Skettenis
3*b725ae77Skettenis This file creates and deletes threads. It uses thread local storage
4*b725ae77Skettenis variables too. */
5*b725ae77Skettenis
6*b725ae77Skettenis #include <unistd.h>
7*b725ae77Skettenis #include <stdlib.h>
8*b725ae77Skettenis #include <stdio.h>
9*b725ae77Skettenis #include <assert.h>
10*b725ae77Skettenis #include <pthread.h>
11*b725ae77Skettenis #include <semaphore.h>
12*b725ae77Skettenis #include <errno.h>
13*b725ae77Skettenis
14*b725ae77Skettenis #define N_THREADS 3
15*b725ae77Skettenis
16*b725ae77Skettenis /* Uncomment to turn on debugging output */
17*b725ae77Skettenis /*#define START_DEBUG*/
18*b725ae77Skettenis
19*b725ae77Skettenis /* Thread-local storage. */
20*b725ae77Skettenis __thread int a_thread_local;
21*b725ae77Skettenis __thread int another_thread_local;
22*b725ae77Skettenis
23*b725ae77Skettenis /* Global variable just for info addr in gdb. */
24*b725ae77Skettenis int a_global;
25*b725ae77Skettenis
26*b725ae77Skettenis /* Print the results of thread-local storage. */
27*b725ae77Skettenis int thread_local_val[ N_THREADS ];
28*b725ae77Skettenis int another_thread_local_val[ N_THREADS ];
29*b725ae77Skettenis
30*b725ae77Skettenis /* Semaphores to make sure the threads are alive when we print the TLS
31*b725ae77Skettenis variables from gdb. */
32*b725ae77Skettenis sem_t tell_main, tell_thread;
33*b725ae77Skettenis
34*b725ae77Skettenis
print_error()35*b725ae77Skettenis void print_error ()
36*b725ae77Skettenis {
37*b725ae77Skettenis switch (errno)
38*b725ae77Skettenis {
39*b725ae77Skettenis case EAGAIN:
40*b725ae77Skettenis fprintf (stderr, "EAGAIN\n");
41*b725ae77Skettenis break;
42*b725ae77Skettenis case EINTR:
43*b725ae77Skettenis fprintf (stderr, "EINTR\n");
44*b725ae77Skettenis break;
45*b725ae77Skettenis case EINVAL:
46*b725ae77Skettenis fprintf (stderr, "EINVAL\n");
47*b725ae77Skettenis break;
48*b725ae77Skettenis case ENOSYS:
49*b725ae77Skettenis fprintf (stderr, "ENOSYS\n");
50*b725ae77Skettenis break;
51*b725ae77Skettenis case ENOENT:
52*b725ae77Skettenis fprintf (stderr, "ENOENT\n");
53*b725ae77Skettenis break;
54*b725ae77Skettenis case EDEADLK:
55*b725ae77Skettenis fprintf (stderr, "EDEADLK\n");
56*b725ae77Skettenis break;
57*b725ae77Skettenis default:
58*b725ae77Skettenis fprintf (stderr, "Unknown error\n");
59*b725ae77Skettenis break;
60*b725ae77Skettenis }
61*b725ae77Skettenis }
62*b725ae77Skettenis
63*b725ae77Skettenis /* Routine for each thread to run, does nothing. */
spin(vp)64*b725ae77Skettenis void *spin( vp )
65*b725ae77Skettenis void * vp;
66*b725ae77Skettenis {
67*b725ae77Skettenis int me = (long) vp;
68*b725ae77Skettenis int i;
69*b725ae77Skettenis
70*b725ae77Skettenis /* Use a_global. */
71*b725ae77Skettenis a_global++;
72*b725ae77Skettenis
73*b725ae77Skettenis a_thread_local = 0;
74*b725ae77Skettenis another_thread_local = me;
75*b725ae77Skettenis for( i = 0; i <= me; i++ ) {
76*b725ae77Skettenis a_thread_local += i;
77*b725ae77Skettenis }
78*b725ae77Skettenis
79*b725ae77Skettenis another_thread_local_val[me] = another_thread_local;
80*b725ae77Skettenis thread_local_val[ me ] = a_thread_local; /* here we know tls value */
81*b725ae77Skettenis
82*b725ae77Skettenis if (sem_post (&tell_main) == -1)
83*b725ae77Skettenis {
84*b725ae77Skettenis fprintf (stderr, "th %d post on sem tell_main failed\n", me);
85*b725ae77Skettenis print_error ();
86*b725ae77Skettenis return;
87*b725ae77Skettenis }
88*b725ae77Skettenis #ifdef START_DEBUG
89*b725ae77Skettenis fprintf (stderr, "th %d post on tell main\n", me);
90*b725ae77Skettenis #endif
91*b725ae77Skettenis
92*b725ae77Skettenis while (1)
93*b725ae77Skettenis {
94*b725ae77Skettenis #ifdef START_DEBUG
95*b725ae77Skettenis fprintf (stderr, "th %d start wait on tell_thread\n", me);
96*b725ae77Skettenis #endif
97*b725ae77Skettenis if (sem_wait (&tell_thread) == 0)
98*b725ae77Skettenis break;
99*b725ae77Skettenis
100*b725ae77Skettenis if (errno == EINTR)
101*b725ae77Skettenis {
102*b725ae77Skettenis #ifdef START_DEBUG
103*b725ae77Skettenis fprintf (stderr, "th %d wait tell_thread got EINTR, rewaiting\n", me);
104*b725ae77Skettenis #endif
105*b725ae77Skettenis continue;
106*b725ae77Skettenis }
107*b725ae77Skettenis else
108*b725ae77Skettenis {
109*b725ae77Skettenis fprintf (stderr, "th %d wait on sem tell_thread failed\n", me);
110*b725ae77Skettenis print_error ();
111*b725ae77Skettenis return;
112*b725ae77Skettenis }
113*b725ae77Skettenis }
114*b725ae77Skettenis
115*b725ae77Skettenis #ifdef START_DEBUG
116*b725ae77Skettenis fprintf (stderr, "th %d Wait on tell_thread\n", me);
117*b725ae77Skettenis #endif
118*b725ae77Skettenis
119*b725ae77Skettenis }
120*b725ae77Skettenis
121*b725ae77Skettenis void
do_pass()122*b725ae77Skettenis do_pass()
123*b725ae77Skettenis {
124*b725ae77Skettenis int i;
125*b725ae77Skettenis pthread_t t[ N_THREADS ];
126*b725ae77Skettenis int err;
127*b725ae77Skettenis
128*b725ae77Skettenis for( i = 0; i < N_THREADS; i++)
129*b725ae77Skettenis {
130*b725ae77Skettenis thread_local_val[i] = 0;
131*b725ae77Skettenis another_thread_local_val[i] = 0;
132*b725ae77Skettenis }
133*b725ae77Skettenis
134*b725ae77Skettenis if (sem_init (&tell_main, 0, 0) == -1)
135*b725ae77Skettenis {
136*b725ae77Skettenis fprintf (stderr, "tell_main semaphore init failed\n");
137*b725ae77Skettenis return;
138*b725ae77Skettenis }
139*b725ae77Skettenis
140*b725ae77Skettenis if (sem_init (&tell_thread, 0, 0) == -1)
141*b725ae77Skettenis {
142*b725ae77Skettenis fprintf (stderr, "tell_thread semaphore init failed\n");
143*b725ae77Skettenis return;
144*b725ae77Skettenis }
145*b725ae77Skettenis
146*b725ae77Skettenis /* Start N_THREADS threads, then join them so that they are terminated. */
147*b725ae77Skettenis for( i = 0; i < N_THREADS; i++ )
148*b725ae77Skettenis {
149*b725ae77Skettenis err = pthread_create( &t[i], NULL, spin, (void *) (long) i );
150*b725ae77Skettenis if( err != 0 ) {
151*b725ae77Skettenis fprintf(stderr, "Error in thread %d create\n", i );
152*b725ae77Skettenis }
153*b725ae77Skettenis }
154*b725ae77Skettenis
155*b725ae77Skettenis for( i = 0; i < N_THREADS; i++ )
156*b725ae77Skettenis {
157*b725ae77Skettenis while (1)
158*b725ae77Skettenis {
159*b725ae77Skettenis #ifdef START_DEBUG
160*b725ae77Skettenis fprintf (stderr, "main %d start wait on tell_main\n", i);
161*b725ae77Skettenis #endif
162*b725ae77Skettenis if (sem_wait (&tell_main) == 0)
163*b725ae77Skettenis break;
164*b725ae77Skettenis
165*b725ae77Skettenis if (errno == EINTR)
166*b725ae77Skettenis {
167*b725ae77Skettenis #ifdef START_DEBUG
168*b725ae77Skettenis fprintf (stderr, "main %d wait tell_main got EINTR, rewaiting\n", i);
169*b725ae77Skettenis #endif
170*b725ae77Skettenis continue;
171*b725ae77Skettenis }
172*b725ae77Skettenis else
173*b725ae77Skettenis {
174*b725ae77Skettenis fprintf (stderr, "main %d wait on sem tell_main failed\n", i);
175*b725ae77Skettenis print_error ();
176*b725ae77Skettenis return;
177*b725ae77Skettenis }
178*b725ae77Skettenis }
179*b725ae77Skettenis }
180*b725ae77Skettenis
181*b725ae77Skettenis #ifdef START_DEBUG
182*b725ae77Skettenis fprintf (stderr, "main done waiting on tell_main\n");
183*b725ae77Skettenis #endif
184*b725ae77Skettenis
185*b725ae77Skettenis i = 10; /* Here all threads should be still alive. */
186*b725ae77Skettenis
187*b725ae77Skettenis for( i = 0; i < N_THREADS; i++ )
188*b725ae77Skettenis {
189*b725ae77Skettenis if (sem_post (&tell_thread) == -1)
190*b725ae77Skettenis {
191*b725ae77Skettenis fprintf (stderr, "main %d post on sem tell_thread failed\n", i);
192*b725ae77Skettenis print_error ();
193*b725ae77Skettenis return;
194*b725ae77Skettenis }
195*b725ae77Skettenis #ifdef START_DEBUG
196*b725ae77Skettenis fprintf (stderr, "main %d post on tell_thread\n", i);
197*b725ae77Skettenis #endif
198*b725ae77Skettenis }
199*b725ae77Skettenis
200*b725ae77Skettenis for( i = 0; i < N_THREADS; i++ )
201*b725ae77Skettenis {
202*b725ae77Skettenis err = pthread_join(t[i], NULL );
203*b725ae77Skettenis if( err != 0 )
204*b725ae77Skettenis {
205*b725ae77Skettenis fprintf (stderr, "error in thread %d join\n", i );
206*b725ae77Skettenis }
207*b725ae77Skettenis }
208*b725ae77Skettenis
209*b725ae77Skettenis i = 10; /* Null line for setting bpts on. */
210*b725ae77Skettenis
211*b725ae77Skettenis }
212*b725ae77Skettenis
213*b725ae77Skettenis int
main()214*b725ae77Skettenis main()
215*b725ae77Skettenis {
216*b725ae77Skettenis do_pass ();
217*b725ae77Skettenis
218*b725ae77Skettenis return 0; /* Set breakpoint here before exit. */
219*b725ae77Skettenis }
220*b725ae77Skettenis
221*b725ae77Skettenis /* EndSourceFile */
222