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.. 10 * otherwise, the thread shall continue as normal from the completed barrier wait. Until 11 * the thread in the signal handler returns from it, it is unspecified whether other threads may 12 * proceed past the barrier once they have all reached it. 13 * 14 * Steps: 15 * 1. Main initialize barrier with count 2 16 * 2. Main create a child thread 17 * 3. Child thread call pthread_barrier_wait(), should block 18 * 4. While child thread is blocking, send SIGUSR1 to child 19 * 5. While child thread is in the signal handler, main thread call pthread_barrier_wait() 20 * 6. After return from the signal handler, the child thread should continue as normal 21 */ 22 23 #define _XOPEN_SOURCE 600 24 #include <pthread.h> 25 #include <stdio.h> 26 #include <stdlib.h> 27 #include <unistd.h> 28 #include <signal.h> 29 #include <string.h> 30 #include <time.h> 31 #include "posixtest.h" 32 33 static pthread_barrier_t barrier; 34 static int thread_state; 35 static int sig_rcvd; 36 static int barrier_waited; 37 38 #define NOT_CREATED_THREAD 1 39 #define ENTERED_THREAD 2 40 #define EXITING_THREAD 3 41 42 void sig_handler() 43 { 44 struct timespec ts; 45 sig_rcvd = 1; 46 printf("thread: interrupted by SIGUSR1\n"); 47 48 ts.tv_sec = 1; 49 ts.tv_nsec = 0; 50 while (barrier_waited != 1) { 51 nanosleep(&ts, NULL); 52 } 53 } 54 55 static void *fn_chld(void *arg) 56 { 57 int rc = 0; 58 struct sigaction act; 59 60 thread_state = ENTERED_THREAD; 61 62 /* Set up thread to handle SIGUSR1 */ 63 act.sa_flags = 0; 64 act.sa_handler = sig_handler; 65 sigfillset(&act.sa_mask); 66 sigaction(SIGUSR1, &act, 0); 67 68 printf("thread: call barrier wait\n"); 69 rc = pthread_barrier_wait(&barrier); 70 if (rc != 0 && rc != PTHREAD_BARRIER_SERIAL_THREAD) { 71 printf 72 ("Test FAILED: child: pthread_barrier_wait() got unexpected " 73 "return code : %d\n", rc); 74 exit(PTS_FAIL); 75 } else if (rc == PTHREAD_BARRIER_SERIAL_THREAD) 76 printf("thread: got PTHREAD_BARRIER_SERIAL_THREAD\n"); 77 78 thread_state = EXITING_THREAD; 79 pthread_exit(0); 80 return NULL; 81 } 82 83 int main(void) 84 { 85 int cnt = 0; 86 int rc; 87 pthread_t child_thread; 88 sig_rcvd = 0; 89 barrier_waited = 0; 90 91 printf("Initialize barrier with count = 2\n"); 92 if (pthread_barrier_init(&barrier, NULL, 2) != 0) { 93 printf("main: Error at pthread_barrier_init()\n"); 94 return PTS_UNRESOLVED; 95 } 96 97 printf("main: create child thread\n"); 98 thread_state = NOT_CREATED_THREAD; 99 if (pthread_create(&child_thread, NULL, fn_chld, NULL) != 0) { 100 printf("main: Error at pthread_create()\n"); 101 return PTS_UNRESOLVED; 102 } 103 104 /* Expect the child to block */ 105 cnt = 0; 106 do { 107 sleep(1); 108 } while (thread_state != EXITING_THREAD && cnt++ < 2); 109 110 if (thread_state == EXITING_THREAD) { 111 /* child thread did not block */ 112 printf("Test FAILED: child thread did not block on " 113 "pthread_barrier_wait()\n"); 114 exit(PTS_FAIL); 115 } else if (thread_state != ENTERED_THREAD) { 116 printf("Unexpected thread state\n"); 117 exit(PTS_UNRESOLVED); 118 } 119 120 printf("main: send SIGUSR1 to child thread\n"); 121 if (pthread_kill(child_thread, SIGUSR1) != 0) { 122 printf("main: Error at pthread_kill()\n"); 123 exit(PTS_UNRESOLVED); 124 } 125 126 /* Wait for thread to receive the signal */ 127 while (sig_rcvd != 1) { 128 sleep(1); 129 } 130 131 printf("main: call barrier wait\n"); 132 rc = pthread_barrier_wait(&barrier); 133 134 if (rc != 0 && rc != PTHREAD_BARRIER_SERIAL_THREAD) { 135 printf 136 ("Test FAILED: main: pthread_barrier_wait() got unexpected " 137 "return code : %d\n", rc); 138 exit(PTS_FAIL); 139 } else if (rc == PTHREAD_BARRIER_SERIAL_THREAD) 140 printf("main: got PTHREAD_BARRIER_SERIAL_THREAD\n"); 141 142 barrier_waited = 1; 143 144 /* We expected the child returned from barrier wait */ 145 cnt = 0; 146 do { 147 sleep(1); 148 } while (thread_state != EXITING_THREAD && cnt++ < 3); 149 150 if (thread_state == ENTERED_THREAD) { 151 printf("Test FAILED: child thread still blocked on " 152 "barrier wait\n"); 153 return PTS_FAIL; 154 } else if (thread_state != EXITING_THREAD) { 155 printf("main: Unexpected thread state\n"); 156 return PTS_UNRESOLVED; 157 } 158 159 if (pthread_join(child_thread, NULL) != 0) { 160 printf("main: Error at pthread_join()\n"); 161 exit(PTS_UNRESOLVED); 162 } 163 164 if (pthread_barrier_destroy(&barrier) != 0) { 165 printf("Error at pthread_barrier_destroy()"); 166 return PTS_UNRESOLVED; 167 } 168 169 printf("Test PASSED\n"); 170 return PTS_PASS; 171 } 172