tls.c 5.0 KB

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