xref: /openbsd-src/gnu/usr.bin/binutils/gdb/testsuite/gdb.threads/tls.c (revision b725ae7711052a2233e31a66fefb8a752c388d7a)
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