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 * The idea of this case comes from GNU C library NPTL test tst-barrier2.c.
80dc076565f772bb1953209fb69ea150b494aaa40robbiew *
92c28215423293e443469a07ae7011135d058b671Garrett Cooper * The process-shared attribute is set to PTHREAD_PROCESS_SHARED to permit
102c28215423293e443469a07ae7011135d058b671Garrett Cooper * a barrier to be operated upon by any thread that has access to the memory
112c28215423293e443469a07ae7011135d058b671Garrett Cooper * where the barrier is allocated. If the process-shared attribute
120dc076565f772bb1953209fb69ea150b494aaa40robbiew * is PTHREAD_PROCESS_PRIVATE, the barrier shall only be operated
132c28215423293e443469a07ae7011135d058b671Garrett Cooper * upon by threads created within the same process as the thread
142c28215423293e443469a07ae7011135d058b671Garrett Cooper * that initialized the barrier; if threads of different processes attempt
150dc076565f772bb1953209fb69ea150b494aaa40robbiew * to operate on such a barrier, the behavior is undefined.
160dc076565f772bb1953209fb69ea150b494aaa40robbiew * The default value of the attribute shall be PTHREAD_PROCESS_PRIVATE. Both constants
170dc076565f772bb1953209fb69ea150b494aaa40robbiew * PTHREAD_PROCESS_SHARED and PTHREAD_PROCESS_PRIVATE are defined in <pthread.h>.
180dc076565f772bb1953209fb69ea150b494aaa40robbiew *
190dc076565f772bb1953209fb69ea150b494aaa40robbiew * steps:
200dc076565f772bb1953209fb69ea150b494aaa40robbiew *	1. Create a piece of shared memory object, create pthread barrier object 'barrier'
210dc076565f772bb1953209fb69ea150b494aaa40robbiew *	   and set the PTHREAD_PROCESS_SHARED attribute.
220dc076565f772bb1953209fb69ea150b494aaa40robbiew *	2. Parent map the shared memory to its memory space, put 'barrier' into it;
230dc076565f772bb1953209fb69ea150b494aaa40robbiew *	3. Parent fork to create child process;
240dc076565f772bb1953209fb69ea150b494aaa40robbiew *	4. Child process map the 'barrier' to its memory space;
250dc076565f772bb1953209fb69ea150b494aaa40robbiew *	5. Parent and Child execute same code: loop N times, calling pthread_barrier_wait()
262c28215423293e443469a07ae7011135d058b671Garrett Cooper *	6. Parent and Child should not block on pthread_barrier_wait()
270dc076565f772bb1953209fb69ea150b494aaa40robbiew */
280dc076565f772bb1953209fb69ea150b494aaa40robbiew
290dc076565f772bb1953209fb69ea150b494aaa40robbiew#define _XOPEN_SOURCE 600
300dc076565f772bb1953209fb69ea150b494aaa40robbiew#include <pthread.h>
310dc076565f772bb1953209fb69ea150b494aaa40robbiew#include <stdio.h>
320dc076565f772bb1953209fb69ea150b494aaa40robbiew#include <stdlib.h>
330dc076565f772bb1953209fb69ea150b494aaa40robbiew#include <unistd.h>
340dc076565f772bb1953209fb69ea150b494aaa40robbiew#include <errno.h>
350dc076565f772bb1953209fb69ea150b494aaa40robbiew#include <sys/mman.h>
360dc076565f772bb1953209fb69ea150b494aaa40robbiew#include <fcntl.h>
370dc076565f772bb1953209fb69ea150b494aaa40robbiew#include <sys/wait.h>
380dc076565f772bb1953209fb69ea150b494aaa40robbiew#include <sys/stat.h>
390dc076565f772bb1953209fb69ea150b494aaa40robbiew#include <signal.h>
400dc076565f772bb1953209fb69ea150b494aaa40robbiew#include "posixtest.h"
410dc076565f772bb1953209fb69ea150b494aaa40robbiew
420dc076565f772bb1953209fb69ea150b494aaa40robbiew#define LOOP_NUM 10
430dc076565f772bb1953209fb69ea150b494aaa40robbiew
440dc076565f772bb1953209fb69ea150b494aaa40robbiewvoid sig_handler()
450dc076565f772bb1953209fb69ea150b494aaa40robbiew{
460dc076565f772bb1953209fb69ea150b494aaa40robbiew	printf("Interrupted by SIGALRM\n");
470dc076565f772bb1953209fb69ea150b494aaa40robbiew	printf("Test Fail: block on pthread_barrier_wait()\n");
480dc076565f772bb1953209fb69ea150b494aaa40robbiew	exit(PTS_FAIL);
490dc076565f772bb1953209fb69ea150b494aaa40robbiew}
500dc076565f772bb1953209fb69ea150b494aaa40robbiew
514ca2bbdcd3003f3c8df4e6129e9c7b2bd1514f87Cyril Hrubisint main(void)
520dc076565f772bb1953209fb69ea150b494aaa40robbiew{
532c28215423293e443469a07ae7011135d058b671Garrett Cooper
542c28215423293e443469a07ae7011135d058b671Garrett Cooper	/* Make sure there is process-shared capability. */
55354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#ifndef PTHREAD_PROCESS_SHARED
56354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	fprintf(stderr,
57354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		"process-shared attribute is not available for testing\n");
58354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	return PTS_UNSUPPORTED;
59354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#endif
600dc076565f772bb1953209fb69ea150b494aaa40robbiew
61354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	static pthread_barrier_t *barrier;
620dc076565f772bb1953209fb69ea150b494aaa40robbiew	pthread_barrierattr_t ba;
63354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	int pshared = PTHREAD_PROCESS_SHARED;
64354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao
65354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	char shm_name[] = "tmp_pthread_barrierattr_getpshared";
66354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	int shm_fd;
67354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	int pid;
68354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	int loop;
69354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	int serial = 0;
70354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	int rc;
71354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	int status = 0;
720dc076565f772bb1953209fb69ea150b494aaa40robbiew	struct sigaction act;
732c28215423293e443469a07ae7011135d058b671Garrett Cooper
740dc076565f772bb1953209fb69ea150b494aaa40robbiew	/* Set up parent to handle SIGALRM */
750dc076565f772bb1953209fb69ea150b494aaa40robbiew	act.sa_flags = 0;
760dc076565f772bb1953209fb69ea150b494aaa40robbiew	act.sa_handler = sig_handler;
770dc076565f772bb1953209fb69ea150b494aaa40robbiew	sigfillset(&act.sa_mask);
780dc076565f772bb1953209fb69ea150b494aaa40robbiew	sigaction(SIGALRM, &act, 0);
790dc076565f772bb1953209fb69ea150b494aaa40robbiew
800dc076565f772bb1953209fb69ea150b494aaa40robbiew	/* Initialize a barrier attributes object */
81354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	if (pthread_barrierattr_init(&ba) != 0) {
820dc076565f772bb1953209fb69ea150b494aaa40robbiew		printf("Error at pthread_barrierattr_init()\n");
830dc076565f772bb1953209fb69ea150b494aaa40robbiew		return PTS_UNRESOLVED;
840dc076565f772bb1953209fb69ea150b494aaa40robbiew	}
852c28215423293e443469a07ae7011135d058b671Garrett Cooper
860dc076565f772bb1953209fb69ea150b494aaa40robbiew	/* Set the pshard value to private to shared */
87354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	if (pthread_barrierattr_setpshared(&ba, pshared) != 0) {
880dc076565f772bb1953209fb69ea150b494aaa40robbiew		printf("Error at pthread_barrierattr_setpshared()\n");
890dc076565f772bb1953209fb69ea150b494aaa40robbiew		return PTS_UNRESOLVED;
900dc076565f772bb1953209fb69ea150b494aaa40robbiew	}
912c28215423293e443469a07ae7011135d058b671Garrett Cooper
92354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	if (pthread_barrierattr_getpshared(&ba, &pshared) != 0) {
93354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		printf
94354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		    ("Test FAILED: Error at pthread_barrierattr_getpshared()\n");
950dc076565f772bb1953209fb69ea150b494aaa40robbiew		return PTS_FAIL;
960dc076565f772bb1953209fb69ea150b494aaa40robbiew	}
972c28215423293e443469a07ae7011135d058b671Garrett Cooper
98354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	if (pshared != PTHREAD_PROCESS_SHARED) {
990dc076565f772bb1953209fb69ea150b494aaa40robbiew		printf("Test FAILED: Incorrect pshared value %d\n", pshared);
1000dc076565f772bb1953209fb69ea150b494aaa40robbiew		return PTS_FAIL;
1010dc076565f772bb1953209fb69ea150b494aaa40robbiew	}
1022c28215423293e443469a07ae7011135d058b671Garrett Cooper
1030dc076565f772bb1953209fb69ea150b494aaa40robbiew	/* Create shared object */
1040dc076565f772bb1953209fb69ea150b494aaa40robbiew	shm_unlink(shm_name);
105354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	shm_fd =
106354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	    shm_open(shm_name, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
107354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	if (shm_fd == -1) {
1080dc076565f772bb1953209fb69ea150b494aaa40robbiew		perror("Error at shm_open()");
1090dc076565f772bb1953209fb69ea150b494aaa40robbiew		return PTS_UNRESOLVED;
1100dc076565f772bb1953209fb69ea150b494aaa40robbiew	}
1112c28215423293e443469a07ae7011135d058b671Garrett Cooper
112354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	if (ftruncate(shm_fd, sizeof(pthread_barrier_t)) != 0) {
113354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		perror("Error at ftruncate()");
114354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		shm_unlink(shm_name);
115354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		return PTS_UNRESOLVED;
116354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	}
1172c28215423293e443469a07ae7011135d058b671Garrett Cooper
1180dc076565f772bb1953209fb69ea150b494aaa40robbiew	/* Map the shared memory object to my memory */
119354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	barrier = mmap(NULL, sizeof(pthread_barrier_t), PROT_READ | PROT_WRITE,
120354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		       MAP_SHARED, shm_fd, 0);
1210dc076565f772bb1953209fb69ea150b494aaa40robbiew
122354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	if (barrier == MAP_FAILED) {
1230dc076565f772bb1953209fb69ea150b494aaa40robbiew		perror("Error at first mmap()");
124354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		shm_unlink(shm_name);
1250dc076565f772bb1953209fb69ea150b494aaa40robbiew		return PTS_UNRESOLVED;
1260dc076565f772bb1953209fb69ea150b494aaa40robbiew	}
1272c28215423293e443469a07ae7011135d058b671Garrett Cooper
1280dc076565f772bb1953209fb69ea150b494aaa40robbiew	/* Initialize a barrier */
129354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	if ((pthread_barrier_init(barrier, &ba, 2)) != 0) {
1300dc076565f772bb1953209fb69ea150b494aaa40robbiew		printf("Error at pthread_barrier_init()\n");
1310dc076565f772bb1953209fb69ea150b494aaa40robbiew		return PTS_UNRESOLVED;
1320dc076565f772bb1953209fb69ea150b494aaa40robbiew	}
1330dc076565f772bb1953209fb69ea150b494aaa40robbiew
1342c28215423293e443469a07ae7011135d058b671Garrett Cooper	/* Cleanup */
135354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	if ((pthread_barrierattr_destroy(&ba)) != 0) {
1360dc076565f772bb1953209fb69ea150b494aaa40robbiew		printf("Error at pthread_barrierattr_destroy()\n");
1370dc076565f772bb1953209fb69ea150b494aaa40robbiew		return PTS_UNRESOLVED;
1380dc076565f772bb1953209fb69ea150b494aaa40robbiew	}
1390dc076565f772bb1953209fb69ea150b494aaa40robbiew
1400dc076565f772bb1953209fb69ea150b494aaa40robbiew	/* Fork a child process */
1410dc076565f772bb1953209fb69ea150b494aaa40robbiew	pid = fork();
142354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	if (pid == -1) {
1430dc076565f772bb1953209fb69ea150b494aaa40robbiew		perror("Error at fork()");
1440dc076565f772bb1953209fb69ea150b494aaa40robbiew		return PTS_UNRESOLVED;
145354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	} else if (pid == 0) {
1460dc076565f772bb1953209fb69ea150b494aaa40robbiew		/* Child */
1470dc076565f772bb1953209fb69ea150b494aaa40robbiew		/* Map the shared object to child's memory */
148354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		barrier =
149354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		    mmap(NULL, sizeof(pthread_barrier_t),
150354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			 PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0);
1510dc076565f772bb1953209fb69ea150b494aaa40robbiew
152354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		if (barrier == MAP_FAILED) {
1530dc076565f772bb1953209fb69ea150b494aaa40robbiew			perror("child: Error at first mmap()");
1540dc076565f772bb1953209fb69ea150b494aaa40robbiew			return PTS_UNRESOLVED;
1550dc076565f772bb1953209fb69ea150b494aaa40robbiew		}
156354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	} else {
1570dc076565f772bb1953209fb69ea150b494aaa40robbiew		printf("parent pid : %d, child pid : %d\n", getpid(), pid);
158354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		printf
159354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		    ("parent: send me SIGALRM 2 secs later in case I am blocked\n");
1600dc076565f772bb1953209fb69ea150b494aaa40robbiew		alarm(2);
1610dc076565f772bb1953209fb69ea150b494aaa40robbiew	}
1620dc076565f772bb1953209fb69ea150b494aaa40robbiew
163354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	for (loop = 0; loop < LOOP_NUM; loop++) {
1640dc076565f772bb1953209fb69ea150b494aaa40robbiew		rc = pthread_barrier_wait(barrier);
165354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		if (rc != 0 && rc != PTHREAD_BARRIER_SERIAL_THREAD) {
166354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			printf
167354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			    ("Test FAILED: %d: pthread_barrier_wait() got unexpected "
168354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			     "return code : %d\n", getpid(), rc);
1690dc076565f772bb1953209fb69ea150b494aaa40robbiew			exit(PTS_FAIL);
170354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		} else if (rc == PTHREAD_BARRIER_SERIAL_THREAD) {
1710dc076565f772bb1953209fb69ea150b494aaa40robbiew			serial++;
172354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			printf
173354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			    ("process %d: get PTHREAD_BARRIER_SERIAL_THREAD\n",
174354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			     getpid());
1750dc076565f772bb1953209fb69ea150b494aaa40robbiew		}
1762c28215423293e443469a07ae7011135d058b671Garrett Cooper
1770dc076565f772bb1953209fb69ea150b494aaa40robbiew	}
1780dc076565f772bb1953209fb69ea150b494aaa40robbiew
179354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	if (pid > 0) {
1800dc076565f772bb1953209fb69ea150b494aaa40robbiew		/* parent */
181354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		if (wait(&status) != pid) {
1820dc076565f772bb1953209fb69ea150b494aaa40robbiew			printf("parent: error at waitpid()\n");
1830dc076565f772bb1953209fb69ea150b494aaa40robbiew			return PTS_UNRESOLVED;
1840dc076565f772bb1953209fb69ea150b494aaa40robbiew		}
1852c28215423293e443469a07ae7011135d058b671Garrett Cooper
186354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		if (!WIFEXITED(status)) {
1870dc076565f772bb1953209fb69ea150b494aaa40robbiew			printf("Child exited abnormally\n");
1882c28215423293e443469a07ae7011135d058b671Garrett Cooper			return PTS_UNRESOLVED;
1892c28215423293e443469a07ae7011135d058b671Garrett Cooper		}
1900dc076565f772bb1953209fb69ea150b494aaa40robbiew
191354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		if ((WEXITSTATUS(status) + serial) != LOOP_NUM) {
1920dc076565f772bb1953209fb69ea150b494aaa40robbiew			printf("status = %d\n", status);
1930dc076565f772bb1953209fb69ea150b494aaa40robbiew			printf("serial = %d\n", serial);
194354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			printf
195354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			    ("Test FAILED: One of the two processes should get "
196354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			     "PTHREAD_BARRIER_SERIAL_THREAD\n");
1970dc076565f772bb1953209fb69ea150b494aaa40robbiew			return PTS_FAIL;
1980dc076565f772bb1953209fb69ea150b494aaa40robbiew		}
1992c28215423293e443469a07ae7011135d058b671Garrett Cooper
2000dc076565f772bb1953209fb69ea150b494aaa40robbiew		/* Cleanup */
201354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		if (pthread_barrier_destroy(barrier) != 0) {
2020dc076565f772bb1953209fb69ea150b494aaa40robbiew			printf("Error at pthread_barrier_destroy()");
2030dc076565f772bb1953209fb69ea150b494aaa40robbiew			return PTS_UNRESOLVED;
2042c28215423293e443469a07ae7011135d058b671Garrett Cooper		}
2052c28215423293e443469a07ae7011135d058b671Garrett Cooper
206354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		if ((shm_unlink(shm_name)) != 0) {
2070dc076565f772bb1953209fb69ea150b494aaa40robbiew			perror("Error at shm_unlink()");
2080dc076565f772bb1953209fb69ea150b494aaa40robbiew			return PTS_UNRESOLVED;
2092c28215423293e443469a07ae7011135d058b671Garrett Cooper		}
2102c28215423293e443469a07ae7011135d058b671Garrett Cooper
2110dc076565f772bb1953209fb69ea150b494aaa40robbiew		printf("Test PASSED\n");
2120dc076565f772bb1953209fb69ea150b494aaa40robbiew		return PTS_PASS;
2130dc076565f772bb1953209fb69ea150b494aaa40robbiew	}
2142c28215423293e443469a07ae7011135d058b671Garrett Cooper
215354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	if (pid == 0) {
2160dc076565f772bb1953209fb69ea150b494aaa40robbiew		exit(serial);
2170dc076565f772bb1953209fb69ea150b494aaa40robbiew	}
2182c28215423293e443469a07ae7011135d058b671Garrett Cooper
219ec6edca7aa42b6affd989ef91b5897f96795e40fChris Dearman}
220