1/* 2 * Copyright © 2013 Keith Packard 3 * 4 * Permission to use, copy, modify, distribute, and sell this software and its 5 * documentation for any purpose is hereby granted without fee, provided that 6 * the above copyright notice appear in all copies and that both that copyright 7 * notice and this permission notice appear in supporting documentation, and 8 * that the name of the copyright holders not be used in advertising or 9 * publicity pertaining to distribution of the software without specific, 10 * written prior permission. The copyright holders make no representations 11 * about the suitability of this software for any purpose. It is provided "as 12 * is" without express or implied warranty. 13 * 14 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 16 * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR 17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 20 * OF THIS SOFTWARE. 21 */ 22 23#include <stdint.h> 24#include <stdio.h> 25#include <stddef.h> 26#include <stdlib.h> 27#include <xshmfence.h> 28#include <unistd.h> 29#include <signal.h> 30#include <sys/types.h> 31#include <sys/wait.h> 32 33#define NCHILD 5 /* number of child processes to fork */ 34#define NCHECK 10 /* number of times to signal the fence */ 35 36/* Catch an alarm and bail 37 */ 38static void 39sigalrm(int sig) 40{ 41 write(2, "caught alarm\n", 13); 42 exit(1); 43} 44 45int 46main(int argc, char **argv) 47{ 48 int fd; 49 struct xshmfence *x; 50 int i; 51 int c; 52 int pid; 53 int status; 54 int failed = 0; 55 56 /* Allocate a fence 57 */ 58 fd = xshmfence_alloc_shm(); 59 if (fd < 0) { 60 perror("xshmfence_alloc_shm"); 61 exit(1); 62 } 63 64 /* fork NCHILD processes to wait for the fence 65 */ 66 for (c = 0; c < NCHILD; c++) { 67 switch (fork()) { 68 case -1: 69 perror("fork"); 70 exit(1); 71 case 0: 72 73 /* Set an alarm to limit how long 74 * to wait 75 */ 76 signal(SIGALRM, sigalrm); 77 alarm(10); 78 79 /* Map the fence 80 */ 81 x = xshmfence_map_shm(fd); 82 if (!x) { 83 fprintf(stderr, "%6d: ", c); 84 perror("xshmfence_map_shm"); 85 exit(1); 86 } 87 88 for (i = 0; i < NCHECK; i++) { 89 90 /* Verify that the fence is currently reset 91 */ 92 if (xshmfence_query(x) != 0) { 93 fprintf(stderr, "%6d: query reset failed\n", c); 94 exit(1); 95 } 96 97 /* Wait for the fence 98 */ 99 fprintf(stderr, "%6d: waiting\n", c); 100 if (xshmfence_await(x) < 0) { 101 fprintf(stderr, "%6d: ", c); 102 perror("xshmfence_await"); 103 exit(1); 104 } 105 106 fprintf(stderr, "%6d: awoken\n", c); 107 108 /* Verify that the fence is currently triggered 109 */ 110 if (xshmfence_query(x) == 0) { 111 fprintf(stderr, "%6d: query triggered failed\n", c); 112 exit(1); 113 } 114 115 usleep(10 * 1000); 116 117 /* Reset the fence 118 */ 119 if (c == 0) 120 xshmfence_reset(x); 121 122 usleep(10 * 1000); 123 } 124 fprintf(stderr, "%6d: done\n", c); 125 exit(0); 126 } 127 } 128 129 /* Map the fence into the parent process 130 */ 131 x = xshmfence_map_shm(fd); 132 if (!x) { 133 perror("xshmfence_map_shm"); 134 exit(1); 135 } 136 137 for (i = 0; i < NCHECK; i++) { 138 usleep(100 * 1000); 139 fprintf(stderr, "trigger\n"); 140 141 /* Verify that the fence is reset 142 */ 143 if (xshmfence_query(x) != 0) { 144 fprintf(stderr, "query reset failed\n"); 145 exit(1); 146 } 147 148 /* Trigger the fence 149 */ 150 if (xshmfence_trigger(x) < 0) { 151 perror("xshmfence_trigger"); 152 exit(1); 153 } 154 155 /* Verify that the fence is triggered 156 */ 157 if (xshmfence_query(x) == 0) { 158 fprintf (stderr, "query triggered failed\n"); 159 exit(1); 160 } 161 162 fprintf(stderr, "trigger done\n"); 163 } 164 165 /* Reap all of the child processes 166 */ 167 for (c = 0; c < NCHILD; c++) { 168 pid = wait(&status); 169 if (pid < 0) { 170 perror("wait"); 171 exit(1); 172 } 173 fprintf(stderr, "child %d done %d\n", pid, status); 174 if (status) 175 failed++; 176 } 177 exit(failed); 178} 179