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