tst-once4.c 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. /* Copyright (C) 2003, 2004 Free Software Foundation, Inc.
  2. This file is part of the GNU C Library.
  3. Contributed by Ulrich Drepper <drepper@redhat.com>, 2003.
  4. The GNU C Library is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU Lesser General Public
  6. License as published by the Free Software Foundation; either
  7. version 2.1 of the License, or (at your option) any later version.
  8. The GNU C Library is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. Lesser General Public License for more details.
  12. You should have received a copy of the GNU Lesser General Public
  13. License along with the GNU C Library; if not, see
  14. <http://www.gnu.org/licenses/>. */
  15. #include <pthread.h>
  16. #include <stdio.h>
  17. #include <stdlib.h>
  18. #include <time.h>
  19. #include <unistd.h>
  20. static pthread_once_t once = PTHREAD_ONCE_INIT;
  21. static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
  22. static pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;
  23. static pthread_barrier_t bar;
  24. static int global;
  25. static int cl_called;
  26. static void
  27. once_handler1 (void)
  28. {
  29. if (pthread_mutex_lock (&mut) != 0)
  30. {
  31. puts ("once_handler1: mutex_lock failed");
  32. exit (1);
  33. }
  34. int r = pthread_barrier_wait (&bar);
  35. if (r != 0 && r!= PTHREAD_BARRIER_SERIAL_THREAD)
  36. {
  37. puts ("once_handler1: barrier_wait failed");
  38. exit (1);
  39. }
  40. pthread_cond_wait (&cond, &mut);
  41. /* We should never get here. */
  42. }
  43. static void
  44. once_handler2 (void)
  45. {
  46. global = 1;
  47. }
  48. static void
  49. cl (void *arg)
  50. {
  51. ++cl_called;
  52. }
  53. static void *
  54. tf1 (void *arg)
  55. {
  56. pthread_cleanup_push (cl, NULL);
  57. pthread_once (&once, once_handler1);
  58. pthread_cleanup_pop (0);
  59. /* We should never get here. */
  60. puts ("pthread_once in tf returned");
  61. exit (1);
  62. }
  63. static void *
  64. tf2 (void *arg)
  65. {
  66. pthread_cleanup_push (cl, NULL);
  67. int r = pthread_barrier_wait (&bar);
  68. if (r != 0 && r!= PTHREAD_BARRIER_SERIAL_THREAD)
  69. {
  70. puts ("once_handler2: barrier_wait failed");
  71. exit (1);
  72. }
  73. pthread_cleanup_pop (0);
  74. pthread_once (&once, once_handler2);
  75. return NULL;
  76. }
  77. static int
  78. do_test (void)
  79. {
  80. pthread_t th[2];
  81. if (pthread_barrier_init (&bar, NULL, 2) != 0)
  82. {
  83. puts ("barrier_init failed");
  84. return 1;
  85. }
  86. if (pthread_create (&th[0], NULL, tf1, NULL) != 0)
  87. {
  88. puts ("first create failed");
  89. return 1;
  90. }
  91. int r = pthread_barrier_wait (&bar);
  92. if (r != 0 && r!= PTHREAD_BARRIER_SERIAL_THREAD)
  93. {
  94. puts ("first barrier_wait failed");
  95. return 1;
  96. }
  97. if (pthread_mutex_lock (&mut) != 0)
  98. {
  99. puts ("mutex_lock failed");
  100. return 1;
  101. }
  102. /* We unlock the mutex so that we catch the case where the pthread_cond_wait
  103. call incorrectly resumes and tries to get the mutex. */
  104. if (pthread_mutex_unlock (&mut) != 0)
  105. {
  106. puts ("mutex_unlock failed");
  107. return 1;
  108. }
  109. if (pthread_create (&th[1], NULL, tf2, NULL) != 0)
  110. {
  111. puts ("second create failed");
  112. return 1;
  113. }
  114. r = pthread_barrier_wait (&bar);
  115. if (r != 0 && r!= PTHREAD_BARRIER_SERIAL_THREAD)
  116. {
  117. puts ("second barrier_wait failed");
  118. return 1;
  119. }
  120. /* Give the second thread a chance to reach the pthread_once call. */
  121. sleep (2);
  122. /* Cancel the thread. */
  123. if (pthread_cancel (th[0]) != 0)
  124. {
  125. puts ("cancel failed");
  126. return 1;
  127. }
  128. void *result;
  129. pthread_join (th[0], &result);
  130. if (result != PTHREAD_CANCELED)
  131. {
  132. puts ("first join didn't return PTHREAD_CANCELED");
  133. return 1;
  134. }
  135. puts ("joined first thread");
  136. pthread_join (th[1], &result);
  137. if (result != NULL)
  138. {
  139. puts ("second join didn't return PTHREAD_CANCELED");
  140. return 1;
  141. }
  142. if (global != 1)
  143. {
  144. puts ("global still 0");
  145. return 1;
  146. }
  147. if (cl_called != 1)
  148. {
  149. printf ("cl_called = %d\n", cl_called);
  150. return 1;
  151. }
  152. return 0;
  153. }
  154. #define TEST_FUNCTION do_test ()
  155. #define TIMEOUT 4
  156. #include "../test-skeleton.c"