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