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  * When the required number of threads have called pthread_barrier_wait()
10  * specifying the barrier, the constant PTHREAD_BARRIER_SERIAL_THREAD shall
11  * be returned to one unspecified thread and zero shall be returned
12  * to each of the remaining threads. At this point, the barrier shall
13  * be reset to the state it had as a result of the most recent
14  * pthread_barrier_init() function that referenced it.
15  *
16  * Steps:
17  * 1. Main thread do the following for LOOP_NUM times
18  * 2. In each loop, Main thread initialize barrier, with count set to THREAD_NUM
19  * 3. Main create THREAD_NUM threads
20  * 4. Each thread will call pthread_barrier_wait()
21  * 5. When the last thread calls pthread_barrier_wait, only one thread will
22  *    get PTHREAD_BARRIER_SERIAL_THREAD, all the other threads should get zero
23  * 6. This holds true for every loop.
24  *
25  */
26 
27 #include <pthread.h>
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <unistd.h>
31 #include <signal.h>
32 #include "posixtest.h"
33 
34 #define THREAD_NUM 5
35 #define LOOP_NUM 3
36 
37 static pthread_barrier_t barrier;
38 static int serial;
39 static int normal_rt;
40 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
41 
fn_chld(void * arg)42 static void *fn_chld(void *arg)
43 {
44 	int rc = 0;
45 	int thread_num = *(int *)arg;
46 
47 	printf("child[%d]: barrier wait\n", thread_num);
48 	rc = pthread_barrier_wait(&barrier);
49 	if (rc != 0 && rc != PTHREAD_BARRIER_SERIAL_THREAD) {
50 		printf
51 		    ("Test FAILED: child[%d]: pthread_barrier_wait() get unexpected "
52 		     "return code : %d\n", thread_num, rc);
53 		exit(PTS_FAIL);
54 	} else if (rc == PTHREAD_BARRIER_SERIAL_THREAD) {
55 		serial++;
56 		printf("child[%d]: get PTHREAD_BARRIER_SERIAL_THREAD\n",
57 		       thread_num);
58 	} else {
59 		pthread_mutex_lock(&mutex);
60 		normal_rt++;
61 		pthread_mutex_unlock(&mutex);
62 	}
63 
64 	pthread_exit(0);
65 	return NULL;
66 }
67 
main(void)68 int main(void)
69 {
70 	pthread_t child_threads[THREAD_NUM];
71 	int cnt;
72 	int loop;
73 
74 	printf("Initialize barrier with count = %d\n", THREAD_NUM);
75 	if (pthread_barrier_init(&barrier, NULL, THREAD_NUM) != 0) {
76 		printf("main: Error at pthread_barrier_init()\n");
77 		return PTS_UNRESOLVED;
78 	}
79 
80 	for (loop = 0; loop < LOOP_NUM; loop++) {
81 		serial = 0;
82 		normal_rt = 0;
83 		printf("\n-Loop %d-\n", loop);
84 
85 		printf("main: create %d child threads\n", THREAD_NUM);
86 		for (cnt = 0; cnt < THREAD_NUM; cnt++) {
87 			if (pthread_create
88 			    (&child_threads[cnt], NULL, fn_chld, &cnt) != 0) {
89 				printf("main: Error at %dth pthread_create()\n",
90 				       cnt);
91 				return PTS_UNRESOLVED;
92 			}
93 
94 		}
95 		printf("main: wait for child threads to end\n");
96 		for (cnt = 0; cnt < THREAD_NUM; cnt++) {
97 			if (pthread_join(child_threads[cnt], NULL) != 0) {
98 				printf("main: Error at %dth pthread_join()\n",
99 				       cnt);
100 				exit(PTS_UNRESOLVED);
101 			}
102 		}
103 
104 		if (serial != 1 || (serial + normal_rt) != THREAD_NUM) {
105 			printf
106 			    ("Test FAILED: On %d loop, PTHREAD_BARRIER_SERIAL_THREAD "
107 			     "should be returned to one unspecified thread\n",
108 			     loop);
109 			return PTS_FAIL;
110 		}
111 
112 	}
113 
114 	if (pthread_barrier_destroy(&barrier) != 0) {
115 		printf("Error at pthread_barrier_destroy()\n");
116 		return PTS_UNRESOLVED;
117 	}
118 
119 	printf("\nTest PASSED\n");
120 	return PTS_PASS;
121 }
122