xenocara/lib/libxshmfence/test/xshmfence_test.c
2018-06-07 21:57:28 +00:00

179 lines
4.8 KiB
C

/*
* Copyright © 2013 Keith Packard
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* the above copyright notice appear in all copies and that both that copyright
* notice and this permission notice appear in supporting documentation, and
* that the name of the copyright holders not be used in advertising or
* publicity pertaining to distribution of the software without specific,
* written prior permission. The copyright holders make no representations
* about the suitability of this software for any purpose. It is provided "as
* is" without express or implied warranty.
*
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
* OF THIS SOFTWARE.
*/
#include <stdint.h>
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
#include <xshmfence.h>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>
#define NCHILD 5 /* number of child processes to fork */
#define NCHECK 10 /* number of times to signal the fence */
/* Catch an alarm and bail
*/
static void
sigalrm(int sig)
{
write(2, "caught alarm\n", 13);
exit(1);
}
int
main(int argc, char **argv)
{
int fd;
struct xshmfence *x;
int i;
int c;
int pid;
int status;
int failed = 0;
/* Allocate a fence
*/
fd = xshmfence_alloc_shm();
if (fd < 0) {
perror("xshmfence_alloc_shm");
exit(1);
}
/* fork NCHILD processes to wait for the fence
*/
for (c = 0; c < NCHILD; c++) {
switch (fork()) {
case -1:
perror("fork");
exit(1);
case 0:
/* Set an alarm to limit how long
* to wait
*/
signal(SIGALRM, sigalrm);
alarm(10);
/* Map the fence
*/
x = xshmfence_map_shm(fd);
if (!x) {
fprintf(stderr, "%6d: ", c);
perror("xshmfence_map_shm");
exit(1);
}
for (i = 0; i < NCHECK; i++) {
/* Verify that the fence is currently reset
*/
if (xshmfence_query(x) != 0) {
fprintf(stderr, "%6d: query reset failed\n", c);
exit(1);
}
/* Wait for the fence
*/
fprintf(stderr, "%6d: waiting\n", c);
if (xshmfence_await(x) < 0) {
fprintf(stderr, "%6d: ", c);
perror("xshmfence_await");
exit(1);
}
fprintf(stderr, "%6d: awoken\n", c);
/* Verify that the fence is currently triggered
*/
if (xshmfence_query(x) == 0) {
fprintf(stderr, "%6d: query triggered failed\n", c);
exit(1);
}
usleep(10 * 1000);
/* Reset the fence
*/
if (c == 0)
xshmfence_reset(x);
usleep(10 * 1000);
}
fprintf(stderr, "%6d: done\n", c);
exit(0);
}
}
/* Map the fence into the parent process
*/
x = xshmfence_map_shm(fd);
if (!x) {
perror("xshmfence_map_shm");
exit(1);
}
for (i = 0; i < NCHECK; i++) {
usleep(100 * 1000);
fprintf(stderr, "trigger\n");
/* Verify that the fence is reset
*/
if (xshmfence_query(x) != 0) {
fprintf(stderr, "query reset failed\n");
exit(1);
}
/* Trigger the fence
*/
if (xshmfence_trigger(x) < 0) {
perror("xshmfence_trigger");
exit(1);
}
/* Verify that the fence is triggered
*/
if (xshmfence_query(x) == 0) {
fprintf (stderr, "query triggered failed\n");
exit(1);
}
fprintf(stderr, "trigger done\n");
}
/* Reap all of the child processes
*/
for (c = 0; c < NCHILD; c++) {
pid = wait(&status);
if (pid < 0) {
perror("wait");
exit(1);
}
fprintf(stderr, "child %d done %d\n", pid, status);
if (status)
failed++;
}
exit(failed);
}