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