123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236 |
- /* BeginSourceFile tls.c
- This file creates and deletes threads. It uses thread local storage
- variables too. */
- #include <unistd.h>
- #include <stdlib.h>
- #include <stdio.h>
- #include <assert.h>
- #include <pthread.h>
- #include <semaphore.h>
- #include <errno.h>
- #define N_THREADS 3
- /* Uncomment to turn on debugging output */
- /*#define START_DEBUG*/
- /* Thread-local storage. */
- __thread int a_thread_local;
- class K {
- public:
- static __thread int another_thread_local;
- };
- __thread int K::another_thread_local;
- /* psymtabs->symtabs resolving check. */
- extern __thread int file2_thread_local;
- /* Global variable just for info addr in gdb. */
- int a_global;
- /* Print the results of thread-local storage. */
- int thread_local_val[ N_THREADS ];
- int another_thread_local_val[ N_THREADS ];
- /* Semaphores to make sure the threads are alive when we print the TLS
- variables from gdb. */
- sem_t tell_main, tell_thread;
- void print_error ()
- {
- switch (errno)
- {
- case EAGAIN:
- fprintf (stderr, "EAGAIN\n");
- break;
- case EINTR:
- fprintf (stderr, "EINTR\n");
- break;
- case EINVAL:
- fprintf (stderr, "EINVAL\n");
- break;
- case ENOSYS:
- fprintf (stderr, "ENOSYS\n");
- break;
- case ENOENT:
- fprintf (stderr, "ENOENT\n");
- break;
- case EDEADLK:
- fprintf (stderr, "EDEADLK\n");
- break;
- default:
- fprintf (stderr, "Unknown error\n");
- break;
- }
- }
- /* Routine for each thread to run, does nothing. */
- void *spin( void *vp )
- {
- int me = (long) vp;
- int i;
-
- /* Use a_global. */
- a_global++;
- a_thread_local = 0;
- K::another_thread_local = me;
- for( i = 0; i <= me; i++ ) {
- a_thread_local += i;
- }
- another_thread_local_val[me] = K::another_thread_local;
- thread_local_val[ me ] = a_thread_local; /* here we know tls value */
- if (sem_post (&tell_main) == -1)
- {
- fprintf (stderr, "th %d post on sem tell_main failed\n", me);
- print_error ();
- return NULL;
- }
- #ifdef START_DEBUG
- fprintf (stderr, "th %d post on tell main\n", me);
- #endif
- while (1)
- {
- #ifdef START_DEBUG
- fprintf (stderr, "th %d start wait on tell_thread\n", me);
- #endif
- if (sem_wait (&tell_thread) == 0)
- break;
- if (errno == EINTR)
- {
- #ifdef START_DEBUG
- fprintf (stderr, "th %d wait tell_thread got EINTR, rewaiting\n", me);
- #endif
- continue;
- }
- else
- {
- fprintf (stderr, "th %d wait on sem tell_thread failed\n", me);
- print_error ();
- return NULL;
- }
- }
- #ifdef START_DEBUG
- fprintf (stderr, "th %d Wait on tell_thread\n", me);
- #endif
- return NULL;
- }
- void
- function_referencing_file2_thread_local (void)
- {
- file2_thread_local = file2_thread_local;
- }
- void
- do_pass()
- {
- int i;
- pthread_t t[ N_THREADS ];
- int err;
- for( i = 0; i < N_THREADS; i++)
- {
- thread_local_val[i] = 0;
- another_thread_local_val[i] = 0;
- }
-
- if (sem_init (&tell_main, 0, 0) == -1)
- {
- fprintf (stderr, "tell_main semaphore init failed\n");
- return;
- }
- if (sem_init (&tell_thread, 0, 0) == -1)
- {
- fprintf (stderr, "tell_thread semaphore init failed\n");
- return;
- }
- /* Start N_THREADS threads, then join them so that they are terminated. */
- for( i = 0; i < N_THREADS; i++ )
- {
- err = pthread_create( &t[i], NULL, spin, (void *) (long) i );
- if( err != 0 ) {
- fprintf(stderr, "Error in thread %d create\n", i );
- }
- }
- for( i = 0; i < N_THREADS; i++ )
- {
- while (1)
- {
- #ifdef START_DEBUG
- fprintf (stderr, "main %d start wait on tell_main\n", i);
- #endif
- if (sem_wait (&tell_main) == 0)
- break;
- if (errno == EINTR)
- {
- #ifdef START_DEBUG
- fprintf (stderr, "main %d wait tell_main got EINTR, rewaiting\n", i);
- #endif
- continue;
- }
- else
- {
- fprintf (stderr, "main %d wait on sem tell_main failed\n", i);
- print_error ();
- return;
- }
- }
- }
- #ifdef START_DEBUG
- fprintf (stderr, "main done waiting on tell_main\n");
- #endif
- i = 10; /* Here all threads should be still alive. */
- for( i = 0; i < N_THREADS; i++ )
- {
- if (sem_post (&tell_thread) == -1)
- {
- fprintf (stderr, "main %d post on sem tell_thread failed\n", i);
- print_error ();
- return;
- }
- #ifdef START_DEBUG
- fprintf (stderr, "main %d post on tell_thread\n", i);
- #endif
- }
- for( i = 0; i < N_THREADS; i++ )
- {
- err = pthread_join(t[i], NULL );
- if( err != 0 )
- {
- fprintf (stderr, "error in thread %d join\n", i );
- }
- }
- i = 10; /* Null line for setting bpts on. */
-
- }
- int
- main()
- {
- do_pass ();
- return 0; /* Set breakpoint here before exit. */
- }
- /* EndSourceFile */
|