12c28215423293e443469a07ae7011135d058b671Garrett Cooper/*
20dc076565f772bb1953209fb69ea150b494aaa40robbiew * Copyright (c) 2002, Intel Corporation. All rights reserved.
30dc076565f772bb1953209fb69ea150b494aaa40robbiew * This file is licensed under the GPL license.  For the full content
42c28215423293e443469a07ae7011135d058b671Garrett Cooper * of this license, see the COPYING file at the top level of this
50dc076565f772bb1953209fb69ea150b494aaa40robbiew * source tree.
60dc076565f772bb1953209fb69ea150b494aaa40robbiew *
70dc076565f772bb1953209fb69ea150b494aaa40robbiew * pthread_barrier_wait()
80dc076565f772bb1953209fb69ea150b494aaa40robbiew *
92c28215423293e443469a07ae7011135d058b671Garrett Cooper * When the required number of threads have called pthread_barrier_wait()
102c28215423293e443469a07ae7011135d058b671Garrett Cooper * specifying the barrier, the constant PTHREAD_BARRIER_SERIAL_THREAD shall
112c28215423293e443469a07ae7011135d058b671Garrett Cooper * be returned to one unspecified thread and zero shall be returned
120dc076565f772bb1953209fb69ea150b494aaa40robbiew * to each of the remaining threads. At this point, the barrier shall
132c28215423293e443469a07ae7011135d058b671Garrett Cooper * be reset to the state it had as a result of the most recent
14e9410dfd93b8e415ecbe3f7e09a085462b27836eGarrett Cooper * pthread_barrier_init() function that referenced it.
152c28215423293e443469a07ae7011135d058b671Garrett Cooper *
160dc076565f772bb1953209fb69ea150b494aaa40robbiew * Steps:
170dc076565f772bb1953209fb69ea150b494aaa40robbiew * 1. Main thread do the following for LOOP_NUM times
180dc076565f772bb1953209fb69ea150b494aaa40robbiew * 2. In each loop, Main thread initialize barrier, with count set to THREAD_NUM
190dc076565f772bb1953209fb69ea150b494aaa40robbiew * 3. Main create THREAD_NUM threads
200dc076565f772bb1953209fb69ea150b494aaa40robbiew * 4. Each thread will call pthread_barrier_wait()
212c28215423293e443469a07ae7011135d058b671Garrett Cooper * 5. When the last thread calls pthread_barrier_wait, only one thread will
220dc076565f772bb1953209fb69ea150b494aaa40robbiew *    get PTHREAD_BARRIER_SERIAL_THREAD, all the other threads should get zero
230dc076565f772bb1953209fb69ea150b494aaa40robbiew * 6. This holds true for every loop.
242c28215423293e443469a07ae7011135d058b671Garrett Cooper *
250dc076565f772bb1953209fb69ea150b494aaa40robbiew */
260dc076565f772bb1953209fb69ea150b494aaa40robbiew
270dc076565f772bb1953209fb69ea150b494aaa40robbiew#define _XOPEN_SOURCE 600
280dc076565f772bb1953209fb69ea150b494aaa40robbiew#include <pthread.h>
290dc076565f772bb1953209fb69ea150b494aaa40robbiew#include <stdio.h>
300dc076565f772bb1953209fb69ea150b494aaa40robbiew#include <stdlib.h>
310dc076565f772bb1953209fb69ea150b494aaa40robbiew#include <unistd.h>
320dc076565f772bb1953209fb69ea150b494aaa40robbiew#include <signal.h>
330dc076565f772bb1953209fb69ea150b494aaa40robbiew#include "posixtest.h"
340dc076565f772bb1953209fb69ea150b494aaa40robbiew
352c28215423293e443469a07ae7011135d058b671Garrett Cooper#define THREAD_NUM 5
362c28215423293e443469a07ae7011135d058b671Garrett Cooper#define LOOP_NUM 3
370dc076565f772bb1953209fb69ea150b494aaa40robbiew
380dc076565f772bb1953209fb69ea150b494aaa40robbiewstatic pthread_barrier_t barrier;
390dc076565f772bb1953209fb69ea150b494aaa40robbiewstatic int serial;
400dc076565f772bb1953209fb69ea150b494aaa40robbiewstatic int normal_rt;
4104c9398977a261ffca56f61196439a6af4e8922cWei Yangstatic pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
420dc076565f772bb1953209fb69ea150b494aaa40robbiew
43354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gaostatic void *fn_chld(void *arg)
442c28215423293e443469a07ae7011135d058b671Garrett Cooper{
450dc076565f772bb1953209fb69ea150b494aaa40robbiew	int rc = 0;
46354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	int thread_num = *(int *)arg;
472c28215423293e443469a07ae7011135d058b671Garrett Cooper
480dc076565f772bb1953209fb69ea150b494aaa40robbiew	printf("child[%d]: barrier wait\n", thread_num);
490dc076565f772bb1953209fb69ea150b494aaa40robbiew	rc = pthread_barrier_wait(&barrier);
50354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	if (rc != 0 && rc != PTHREAD_BARRIER_SERIAL_THREAD) {
51354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		printf
52354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		    ("Test FAILED: child[%d]: pthread_barrier_wait() get unexpected "
53354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		     "return code : %d\n", thread_num, rc);
540dc076565f772bb1953209fb69ea150b494aaa40robbiew		exit(PTS_FAIL);
55354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	} else if (rc == PTHREAD_BARRIER_SERIAL_THREAD) {
560dc076565f772bb1953209fb69ea150b494aaa40robbiew		serial++;
57354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		printf("child[%d]: get PTHREAD_BARRIER_SERIAL_THREAD\n",
58354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		       thread_num);
59354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	} else {
6004c9398977a261ffca56f61196439a6af4e8922cWei Yang		pthread_mutex_lock(&mutex);
610dc076565f772bb1953209fb69ea150b494aaa40robbiew		normal_rt++;
6204c9398977a261ffca56f61196439a6af4e8922cWei Yang		pthread_mutex_unlock(&mutex);
630dc076565f772bb1953209fb69ea150b494aaa40robbiew	}
642c28215423293e443469a07ae7011135d058b671Garrett Cooper
650dc076565f772bb1953209fb69ea150b494aaa40robbiew	pthread_exit(0);
660dc076565f772bb1953209fb69ea150b494aaa40robbiew	return NULL;
670dc076565f772bb1953209fb69ea150b494aaa40robbiew}
682c28215423293e443469a07ae7011135d058b671Garrett Cooper
694ca2bbdcd3003f3c8df4e6129e9c7b2bd1514f87Cyril Hrubisint main(void)
700dc076565f772bb1953209fb69ea150b494aaa40robbiew{
710dc076565f772bb1953209fb69ea150b494aaa40robbiew	pthread_t child_threads[THREAD_NUM];
720dc076565f772bb1953209fb69ea150b494aaa40robbiew	int cnt;
730dc076565f772bb1953209fb69ea150b494aaa40robbiew	int loop;
740dc076565f772bb1953209fb69ea150b494aaa40robbiew
750dc076565f772bb1953209fb69ea150b494aaa40robbiew	printf("Initialize barrier with count = %d\n", THREAD_NUM);
76354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	if (pthread_barrier_init(&barrier, NULL, THREAD_NUM) != 0) {
770dc076565f772bb1953209fb69ea150b494aaa40robbiew		printf("main: Error at pthread_barrier_init()\n");
780dc076565f772bb1953209fb69ea150b494aaa40robbiew		return PTS_UNRESOLVED;
790dc076565f772bb1953209fb69ea150b494aaa40robbiew	}
800dc076565f772bb1953209fb69ea150b494aaa40robbiew
81354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	for (loop = 0; loop < LOOP_NUM; loop++) {
820dc076565f772bb1953209fb69ea150b494aaa40robbiew		serial = 0;
830dc076565f772bb1953209fb69ea150b494aaa40robbiew		normal_rt = 0;
840dc076565f772bb1953209fb69ea150b494aaa40robbiew		printf("\n-Loop %d-\n", loop);
850dc076565f772bb1953209fb69ea150b494aaa40robbiew
860dc076565f772bb1953209fb69ea150b494aaa40robbiew		printf("main: create %d child threads\n", THREAD_NUM);
87354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		for (cnt = 0; cnt < THREAD_NUM; cnt++) {
88354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			if (pthread_create
89354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			    (&child_threads[cnt], NULL, fn_chld, &cnt) != 0) {
90354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao				printf("main: Error at %dth pthread_create()\n",
91354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao				       cnt);
920dc076565f772bb1953209fb69ea150b494aaa40robbiew				return PTS_UNRESOLVED;
930dc076565f772bb1953209fb69ea150b494aaa40robbiew			}
942c28215423293e443469a07ae7011135d058b671Garrett Cooper
950dc076565f772bb1953209fb69ea150b494aaa40robbiew		}
960dc076565f772bb1953209fb69ea150b494aaa40robbiew		printf("main: wait for child threads to end\n");
97354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		for (cnt = 0; cnt < THREAD_NUM; cnt++) {
98354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			if (pthread_join(child_threads[cnt], NULL) != 0) {
99354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao				printf("main: Error at %dth pthread_join()\n",
100354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao				       cnt);
1010dc076565f772bb1953209fb69ea150b494aaa40robbiew				exit(PTS_UNRESOLVED);
1020dc076565f772bb1953209fb69ea150b494aaa40robbiew			}
1030dc076565f772bb1953209fb69ea150b494aaa40robbiew		}
1042c28215423293e443469a07ae7011135d058b671Garrett Cooper
105354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		if (serial != 1 || (serial + normal_rt) != THREAD_NUM) {
106354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			printf
107354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			    ("Test FAILED: On %d loop, PTHREAD_BARRIER_SERIAL_THREAD "
108354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			     "should be returned to one unspecified thread\n",
109354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			     loop);
1100dc076565f772bb1953209fb69ea150b494aaa40robbiew			return PTS_FAIL;
1110dc076565f772bb1953209fb69ea150b494aaa40robbiew		}
1122c28215423293e443469a07ae7011135d058b671Garrett Cooper
1130dc076565f772bb1953209fb69ea150b494aaa40robbiew	}
1140dc076565f772bb1953209fb69ea150b494aaa40robbiew
115354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	if (pthread_barrier_destroy(&barrier) != 0) {
1160dc076565f772bb1953209fb69ea150b494aaa40robbiew		printf("Error at pthread_barrier_destroy()");
1170dc076565f772bb1953209fb69ea150b494aaa40robbiew		return PTS_UNRESOLVED;
1182c28215423293e443469a07ae7011135d058b671Garrett Cooper	}
1190dc076565f772bb1953209fb69ea150b494aaa40robbiew
1200dc076565f772bb1953209fb69ea150b494aaa40robbiew	printf("\nTest PASSED\n");
1210dc076565f772bb1953209fb69ea150b494aaa40robbiew	return PTS_PASS;
12204c9398977a261ffca56f61196439a6af4e8922cWei Yang}
123