Home | History | Annotate | Download | only in pthread_barrier_wait
      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  * The pthread_barrier_wait() function shall synchronize participating threads
     10  * at the barrier referenced by barrier. The calling thread shall block
     11  * until the required number of threads have called pthread_barrier_wait()
     12  * specifying the barrier.
     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. Main call pthread_barrier_wait(), child and main should all return
     19  *    from pthread_barrier_wait()
     20  */
     21 #define _XOPEN_SOURCE 600
     22 #include <pthread.h>
     23 #include <stdio.h>
     24 #include <stdlib.h>
     25 #include <unistd.h>
     26 #include <signal.h>
     27 #include <string.h>
     28 #include "posixtest.h"
     29 
     30 static pthread_barrier_t barrier;
     31 static int thread_state;
     32 #define NOT_CREATED_THREAD 1
     33 #define ENTERED_THREAD 2
     34 #define EXITING_THREAD 3
     35 
     36 static void *fn_chld(void *arg)
     37 {
     38 	int rc = 0;
     39 	thread_state = ENTERED_THREAD;
     40 
     41 	printf("child: barrier wait\n");
     42 	rc = pthread_barrier_wait(&barrier);
     43 	if (rc != 0 && rc != PTHREAD_BARRIER_SERIAL_THREAD) {
     44 		printf
     45 		    ("Test FAILED: child: pthread_barrier_wait() got unexpected "
     46 		     "return code : %d\n", rc);
     47 		exit(PTS_FAIL);
     48 	} else if (rc == PTHREAD_BARRIER_SERIAL_THREAD) {
     49 		printf("child: get PTHREAD_BARRIER_SERIAL_THREAD\n");
     50 	}
     51 
     52 	thread_state = EXITING_THREAD;
     53 	pthread_exit(0);
     54 	return NULL;
     55 }
     56 
     57 void sig_handler()
     58 {
     59 	printf("Interrupted by SIGALRM\n");
     60 	printf("Test FAILED: main blocked on barrier wait\n");
     61 	exit(PTS_FAIL);
     62 }
     63 
     64 int main(void)
     65 {
     66 	int cnt = 0;
     67 	int rc;
     68 	pthread_t child_thread;
     69 	struct sigaction act;
     70 
     71 	/* Set up main thread to handle SIGALRM */
     72 	act.sa_flags = 0;
     73 	act.sa_handler = sig_handler;
     74 	sigfillset(&act.sa_mask);
     75 	sigaction(SIGALRM, &act, 0);
     76 
     77 	printf("Initialize barrier with count = 2\n");
     78 	if (pthread_barrier_init(&barrier, NULL, 2) != 0) {
     79 		printf("main: Error at pthread_barrier_init()\n");
     80 		return PTS_UNRESOLVED;
     81 	}
     82 
     83 	printf("main: create child thread\n");
     84 	thread_state = NOT_CREATED_THREAD;
     85 	if (pthread_create(&child_thread, NULL, fn_chld, NULL) != 0) {
     86 		printf("main: Error at pthread_create()\n");
     87 		return PTS_UNRESOLVED;
     88 	}
     89 
     90 	/* Expect the child to block */
     91 	cnt = 0;
     92 	do {
     93 		sleep(1);
     94 	} while (thread_state != EXITING_THREAD && cnt++ < 2);
     95 
     96 	if (thread_state == EXITING_THREAD) {
     97 		/* child thread did not block */
     98 		printf("Test FAILED: child thread did not block on "
     99 		       "pthread_barrier_wait()\n");
    100 		exit(PTS_FAIL);
    101 	} else if (thread_state != ENTERED_THREAD) {
    102 		printf("Unexpected thread state: %d\n", thread_state);
    103 		exit(PTS_UNRESOLVED);
    104 	}
    105 
    106 	printf("main: call barrier wait\n");
    107 
    108 	/* we should not block here, but just in case we do */
    109 	alarm(2);
    110 
    111 	rc = pthread_barrier_wait(&barrier);
    112 
    113 	if (rc != 0 && rc != PTHREAD_BARRIER_SERIAL_THREAD) {
    114 		printf
    115 		    ("Test FAILED: main: pthread_barrier_wait() get unexpected "
    116 		     "return code : %d\n", rc);
    117 		exit(PTS_FAIL);
    118 	} else if (rc == PTHREAD_BARRIER_SERIAL_THREAD) {
    119 		printf("main: got PTHREAD_BARRIER_SERIAL_THREAD\n");
    120 	}
    121 
    122 	/* We expected the child returned from barrier wait */
    123 	cnt = 1;
    124 	do {
    125 		sleep(1);
    126 	} while (thread_state != EXITING_THREAD && cnt++ < 3);
    127 
    128 	if (thread_state == ENTERED_THREAD) {
    129 		printf("Test FAILED: child thread still blocked on "
    130 		       "barrier wait\n");
    131 		return PTS_FAIL;
    132 	} else if (thread_state != EXITING_THREAD) {
    133 		printf("main: Unexpected thread state: %d\n", thread_state);
    134 		return PTS_UNRESOLVED;
    135 	}
    136 
    137 	if (pthread_join(child_thread, NULL) != 0) {
    138 		printf("main: Error at pthread_join()\n");
    139 		exit(PTS_UNRESOLVED);
    140 	}
    141 
    142 	if (pthread_barrier_destroy(&barrier) != 0) {
    143 		printf("Error at pthread_barrier_destroy()");
    144 		return PTS_UNRESOLVED;
    145 	}
    146 
    147 	printf("Test PASSED\n");
    148 	return PTS_PASS;
    149 }
    150