1 /* 2 * Copyright (c) 2002, Intel Corporation. All rights reserved. 3 * This file is licensed under the GPL license. For the full content 4 * of this license, see the COPYING file at the top level of this 5 * source tree. 6 * 7 * pthread_barrier_wait() 8 * 9 * If a signal is delivered to a thread blocked on a barrier, upon return 10 * from the signal handler the thread shall resume waiting at the barrier 11 * if the barrier wait has not completed (that is, if the 12 * required number of threads have not arrived at the barrier 13 * during the execution of the signal handler); 14 * 15 * Steps: 16 * 1. Main initialize barrier with count 2 17 * 2. Main create a child thread 18 * 3. Child thread call pthread_barrier_wait(), should block 19 * 4. While child thread is blocking, send SIGUSR1 to child 20 * 5. The signal handler did nothing just print a messge 21 * 6. After return from the signal handler, child should resume blocking 22 * 7. Main call pthread_barrier_wait(), child and main should all return 23 * from pthread_barrier_wait() 24 */ 25 26 #define _XOPEN_SOURCE 600 27 #include <pthread.h> 28 #include <stdio.h> 29 #include <stdlib.h> 30 #include <unistd.h> 31 #include <signal.h> 32 #include <string.h> 33 #include "posixtest.h" 34 35 static pthread_barrier_t barrier; 36 static int thread_state; 37 static int sig_rcvd; 38 39 #define NOT_CREATED_THREAD 1 40 #define ENTERED_THREAD 2 41 #define EXITING_THREAD 3 42 43 void sig_handler() 44 { 45 sig_rcvd = 1; 46 printf("thread: interrupted by SIGUSR1\n"); 47 } 48 49 static void *fn_chld(void *arg) 50 { 51 int rc = 0; 52 struct sigaction act; 53 54 thread_state = ENTERED_THREAD; 55 56 /* Set up thread to handle SIGUSR1 */ 57 act.sa_flags = 0; 58 act.sa_handler = sig_handler; 59 sigfillset(&act.sa_mask); 60 sigaction(SIGUSR1, &act, 0); 61 62 printf("thread: call barrier wait\n"); 63 rc = pthread_barrier_wait(&barrier); 64 if (rc != 0 && rc != PTHREAD_BARRIER_SERIAL_THREAD) { 65 printf 66 ("Test FAILED: child: pthread_barrier_wait() got unexpected " 67 "return code : %d\n", rc); 68 exit(PTS_FAIL); 69 } else if (rc == PTHREAD_BARRIER_SERIAL_THREAD) 70 printf("thread: get PTHREAD_BARRIER_SERIAL_THREAD\n"); 71 72 thread_state = EXITING_THREAD; 73 pthread_exit(0); 74 return NULL; 75 } 76 77 int main(void) 78 { 79 int cnt = 0; 80 int rc; 81 pthread_t child_thread; 82 sig_rcvd = 0; 83 84 printf("Initialize barrier with count = 2\n"); 85 if (pthread_barrier_init(&barrier, NULL, 2) != 0) { 86 printf("main: Error at pthread_barrier_init()\n"); 87 return PTS_UNRESOLVED; 88 } 89 90 printf("main: create child thread\n"); 91 thread_state = NOT_CREATED_THREAD; 92 if (pthread_create(&child_thread, NULL, fn_chld, NULL) != 0) { 93 printf("main: Error at pthread_create()\n"); 94 return PTS_UNRESOLVED; 95 } 96 97 /* Expect the child to block */ 98 cnt = 0; 99 do { 100 sleep(1); 101 } while (thread_state != EXITING_THREAD && cnt++ < 2); 102 103 if (thread_state == EXITING_THREAD) { 104 /* child thread did not block */ 105 printf("Test FAILED: child thread did not block on " 106 "pthread_barrier_wait()\n"); 107 exit(PTS_FAIL); 108 } else if (thread_state != ENTERED_THREAD) { 109 printf("Unexpected thread state: %d\n", thread_state); 110 exit(PTS_UNRESOLVED); 111 } 112 113 printf("main: send SIGUSR1 to child thread\n"); 114 if (pthread_kill(child_thread, SIGUSR1) != 0) { 115 printf("main: Error at pthread_kill()\n"); 116 exit(PTS_UNRESOLVED); 117 } 118 119 /* Expect the child to continue blocking */ 120 cnt = 0; 121 do { 122 sleep(1); 123 } while (thread_state != EXITING_THREAD && cnt++ < 2); 124 125 if (sig_rcvd != 1) { 126 printf("child did not handle SIGUSR1\n"); 127 exit(PTS_UNRESOLVED); 128 } 129 130 if (thread_state == EXITING_THREAD) { 131 /* child thread did not block */ 132 printf("Test FAILED: child thread should still block on " 133 "pthread_barrier_wait() when interrupted by signal\n"); 134 exit(PTS_FAIL); 135 } else if (thread_state != ENTERED_THREAD) { 136 printf("Unexpected thread state: %d\n", thread_state); 137 exit(PTS_UNRESOLVED); 138 } 139 printf("main: thread continued blocking after handling SIGUSR1\n"); 140 141 printf("main: call barrier wait\n"); 142 rc = pthread_barrier_wait(&barrier); 143 144 if (rc != 0 && rc != PTHREAD_BARRIER_SERIAL_THREAD) { 145 printf 146 ("Test FAILED: main: pthread_barrier_wait() got unexpected " 147 "return code : %d\n", rc); 148 exit(PTS_FAIL); 149 } else if (rc == PTHREAD_BARRIER_SERIAL_THREAD) 150 printf("main: get PTHREAD_BARRIER_SERIAL_THREAD\n"); 151 152 /* We expected the child returned from barrier wait */ 153 cnt = 0; 154 do { 155 sleep(1); 156 } while (thread_state != EXITING_THREAD && cnt++ < 3); 157 158 if (thread_state == ENTERED_THREAD) { 159 printf("Test FAILED: child thread still blocked on " 160 "barrier wait\n"); 161 return PTS_FAIL; 162 } else if (thread_state != EXITING_THREAD) { 163 printf("main: Unexpected thread state: %d\n", thread_state); 164 return PTS_UNRESOLVED; 165 } 166 167 if (pthread_join(child_thread, NULL) != 0) { 168 printf("main: Error at pthread_join()\n"); 169 exit(PTS_UNRESOLVED); 170 } 171 172 if (pthread_barrier_destroy(&barrier) != 0) { 173 printf("Error at pthread_barrier_destroy()"); 174 return PTS_UNRESOLVED; 175 } 176 177 printf("Test PASSED\n"); 178 return PTS_PASS; 179 } 180