Home | History | Annotate | Download | only in pthread_barrierattr_getpshared
      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  * The idea of this case comes from GNU C library NPTL test tst-barrier2.c.
      8  *
      9  * The process-shared attribute is set to PTHREAD_PROCESS_SHARED to permit
     10  * a barrier to be operated upon by any thread that has access to the memory
     11  * where the barrier is allocated. If the process-shared attribute
     12  * is PTHREAD_PROCESS_PRIVATE, the barrier shall only be operated
     13  * upon by threads created within the same process as the thread
     14  * that initialized the barrier; if threads of different processes attempt
     15  * to operate on such a barrier, the behavior is undefined.
     16  * The default value of the attribute shall be PTHREAD_PROCESS_PRIVATE. Both constants
     17  * PTHREAD_PROCESS_SHARED and PTHREAD_PROCESS_PRIVATE are defined in <pthread.h>.
     18  *
     19  * steps:
     20  *	1. Create a piece of shared memory object, create pthread barrier object 'barrier'
     21  *	   and set the PTHREAD_PROCESS_SHARED attribute.
     22  *	2. Parent map the shared memory to its memory space, put 'barrier' into it;
     23  *	3. Parent fork to create child process;
     24  *	4. Child process map the 'barrier' to its memory space;
     25  *	5. Parent and Child execute same code: loop N times, calling pthread_barrier_wait()
     26  *	6. Parent and Child should not block on pthread_barrier_wait()
     27  */
     28 
     29 #define _XOPEN_SOURCE 600
     30 #include <pthread.h>
     31 #include <stdio.h>
     32 #include <stdlib.h>
     33 #include <unistd.h>
     34 #include <errno.h>
     35 #include <sys/mman.h>
     36 #include <fcntl.h>
     37 #include <sys/wait.h>
     38 #include <sys/stat.h>
     39 #include <signal.h>
     40 #include "posixtest.h"
     41 
     42 #define LOOP_NUM 10
     43 
     44 void sig_handler()
     45 {
     46 	printf("Interrupted by SIGALRM\n");
     47 	printf("Test Fail: block on pthread_barrier_wait()\n");
     48 	exit(PTS_FAIL);
     49 }
     50 
     51 int main(void)
     52 {
     53 
     54 	/* Make sure there is process-shared capability. */
     55 #ifndef PTHREAD_PROCESS_SHARED
     56 	fprintf(stderr,
     57 		"process-shared attribute is not available for testing\n");
     58 	return PTS_UNSUPPORTED;
     59 #endif
     60 
     61 	static pthread_barrier_t *barrier;
     62 	pthread_barrierattr_t ba;
     63 	int pshared = PTHREAD_PROCESS_SHARED;
     64 
     65 	char shm_name[] = "tmp_pthread_barrierattr_getpshared";
     66 	int shm_fd;
     67 	int pid;
     68 	int loop;
     69 	int serial = 0;
     70 	int rc;
     71 	int status = 0;
     72 	struct sigaction act;
     73 
     74 	/* Set up parent to handle SIGALRM */
     75 	act.sa_flags = 0;
     76 	act.sa_handler = sig_handler;
     77 	sigfillset(&act.sa_mask);
     78 	sigaction(SIGALRM, &act, 0);
     79 
     80 	/* Initialize a barrier attributes object */
     81 	if (pthread_barrierattr_init(&ba) != 0) {
     82 		printf("Error at pthread_barrierattr_init()\n");
     83 		return PTS_UNRESOLVED;
     84 	}
     85 
     86 	/* Set the pshard value to private to shared */
     87 	if (pthread_barrierattr_setpshared(&ba, pshared) != 0) {
     88 		printf("Error at pthread_barrierattr_setpshared()\n");
     89 		return PTS_UNRESOLVED;
     90 	}
     91 
     92 	if (pthread_barrierattr_getpshared(&ba, &pshared) != 0) {
     93 		printf
     94 		    ("Test FAILED: Error at pthread_barrierattr_getpshared()\n");
     95 		return PTS_FAIL;
     96 	}
     97 
     98 	if (pshared != PTHREAD_PROCESS_SHARED) {
     99 		printf("Test FAILED: Incorrect pshared value %d\n", pshared);
    100 		return PTS_FAIL;
    101 	}
    102 
    103 	/* Create shared object */
    104 	shm_unlink(shm_name);
    105 	shm_fd =
    106 	    shm_open(shm_name, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
    107 	if (shm_fd == -1) {
    108 		perror("Error at shm_open()");
    109 		return PTS_UNRESOLVED;
    110 	}
    111 
    112 	if (ftruncate(shm_fd, sizeof(pthread_barrier_t)) != 0) {
    113 		perror("Error at ftruncate()");
    114 		shm_unlink(shm_name);
    115 		return PTS_UNRESOLVED;
    116 	}
    117 
    118 	/* Map the shared memory object to my memory */
    119 	barrier = mmap(NULL, sizeof(pthread_barrier_t), PROT_READ | PROT_WRITE,
    120 		       MAP_SHARED, shm_fd, 0);
    121 
    122 	if (barrier == MAP_FAILED) {
    123 		perror("Error at first mmap()");
    124 		shm_unlink(shm_name);
    125 		return PTS_UNRESOLVED;
    126 	}
    127 
    128 	/* Initialize a barrier */
    129 	if ((pthread_barrier_init(barrier, &ba, 2)) != 0) {
    130 		printf("Error at pthread_barrier_init()\n");
    131 		return PTS_UNRESOLVED;
    132 	}
    133 
    134 	/* Cleanup */
    135 	if ((pthread_barrierattr_destroy(&ba)) != 0) {
    136 		printf("Error at pthread_barrierattr_destroy()\n");
    137 		return PTS_UNRESOLVED;
    138 	}
    139 
    140 	/* Fork a child process */
    141 	pid = fork();
    142 	if (pid == -1) {
    143 		perror("Error at fork()");
    144 		return PTS_UNRESOLVED;
    145 	} else if (pid == 0) {
    146 		/* Child */
    147 		/* Map the shared object to child's memory */
    148 		barrier =
    149 		    mmap(NULL, sizeof(pthread_barrier_t),
    150 			 PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0);
    151 
    152 		if (barrier == MAP_FAILED) {
    153 			perror("child: Error at first mmap()");
    154 			return PTS_UNRESOLVED;
    155 		}
    156 	} else {
    157 		printf("parent pid : %d, child pid : %d\n", getpid(), pid);
    158 		printf
    159 		    ("parent: send me SIGALRM 2 secs later in case I am blocked\n");
    160 		alarm(2);
    161 	}
    162 
    163 	for (loop = 0; loop < LOOP_NUM; loop++) {
    164 		rc = pthread_barrier_wait(barrier);
    165 		if (rc != 0 && rc != PTHREAD_BARRIER_SERIAL_THREAD) {
    166 			printf
    167 			    ("Test FAILED: %d: pthread_barrier_wait() got unexpected "
    168 			     "return code : %d\n", getpid(), rc);
    169 			exit(PTS_FAIL);
    170 		} else if (rc == PTHREAD_BARRIER_SERIAL_THREAD) {
    171 			serial++;
    172 			printf
    173 			    ("process %d: get PTHREAD_BARRIER_SERIAL_THREAD\n",
    174 			     getpid());
    175 		}
    176 
    177 	}
    178 
    179 	if (pid > 0) {
    180 		/* parent */
    181 		if (wait(&status) != pid) {
    182 			printf("parent: error at waitpid()\n");
    183 			return PTS_UNRESOLVED;
    184 		}
    185 
    186 		if (!WIFEXITED(status)) {
    187 			printf("Child exited abnormally\n");
    188 			return PTS_UNRESOLVED;
    189 		}
    190 
    191 		if ((WEXITSTATUS(status) + serial) != LOOP_NUM) {
    192 			printf("status = %d\n", status);
    193 			printf("serial = %d\n", serial);
    194 			printf
    195 			    ("Test FAILED: One of the two processes should get "
    196 			     "PTHREAD_BARRIER_SERIAL_THREAD\n");
    197 			return PTS_FAIL;
    198 		}
    199 
    200 		/* Cleanup */
    201 		if (pthread_barrier_destroy(barrier) != 0) {
    202 			printf("Error at pthread_barrier_destroy()");
    203 			return PTS_UNRESOLVED;
    204 		}
    205 
    206 		if ((shm_unlink(shm_name)) != 0) {
    207 			perror("Error at shm_unlink()");
    208 			return PTS_UNRESOLVED;
    209 		}
    210 
    211 		printf("Test PASSED\n");
    212 		return PTS_PASS;
    213 	}
    214 
    215 	if (pid == 0) {
    216 		exit(serial);
    217 	}
    218 
    219 }
    220