1 /* 2 * This file and its contents are supplied under the terms of the 3 * Common Development and Distribution License ("CDDL"), version 1.0. 4 * You may only use this file in accordance with the terms of version 5 * 1.0 of the CDDL. 6 * 7 * A full copy of the text of the CDDL should have accompanied this 8 * source. A copy of the CDDL is also available via the Internet at 9 * http://www.illumos.org/license/CDDL. 10 */ 11 12 /* 13 * Copyright 2021 OmniOS Community Edition (OmniOSce) Association. 14 */ 15 16 #include <err.h> 17 #include <errno.h> 18 #include <limits.h> 19 #include <stdio.h> 20 #include <stdlib.h> 21 #include <sys/debug.h> 22 #include <sys/eventfd.h> 23 #include <unistd.h> 24 25 static int 26 readn(int fd, uint_t n) 27 { 28 uint_t i; 29 int failures = 0; 30 31 for (i = 0; i < n; i++) { 32 eventfd_t v = 0xdeadbeef; 33 int ret; 34 35 ret = eventfd_read(fd, &v); 36 if (ret != 0) { 37 warn("Reading %u/%u got ret %d (expected 0)", 38 i + 1, n, ret); 39 failures++; 40 } else if (v != 1) { 41 warnx("Reading %u/%u got value %"PRIu64" (expected 1)", 42 i + 1, n, v); 43 failures++; 44 } 45 } 46 47 return (failures); 48 } 49 50 static int 51 check_nosem(int fd) 52 { 53 eventfd_t v = 0xdeadbeef; 54 int failures = 0; 55 int ret; 56 57 ret = eventfd_read(fd, &v); 58 59 if (ret != -1) { 60 warnx("no semaphores read got ret %d (expected -1)", ret); 61 failures++; 62 } 63 64 if (errno != EAGAIN) { 65 warn("no semaphores read expected EAGAIN but got"); 66 failures++; 67 } 68 69 if (v != 0xdeadbeef) { 70 warnx("no semaphores read modified value to %"PRIx64, v); 71 failures++; 72 } 73 74 return (failures); 75 } 76 77 static int 78 check_badwrite(int fd) 79 { 80 int failures = 0; 81 int ret; 82 83 ret = eventfd_write(fd, ULLONG_MAX); 84 85 if (ret != -1) { 86 warnx("bad write got ret %d (expected -1)", ret); 87 failures++; 88 } 89 90 if (errno != EINVAL) { 91 warn("bad write expected EINVAL but got"); 92 failures++; 93 } 94 95 return (failures); 96 } 97 98 int 99 main(void) 100 { 101 int fd, failures = 0; 102 103 /* Test eventfd semaphore semantics */ 104 fd = eventfd(2, EFD_NONBLOCK | EFD_CLOEXEC | EFD_SEMAPHORE); 105 if (fd == -1) 106 err(EXIT_FAILURE, "Could not create eventfd semaphore"); 107 108 /* Consume the available semaphores */ 109 failures += readn(fd, 2); 110 111 /* The next read should return -1/EAGAIN */ 112 failures += check_nosem(fd); 113 114 /* Return two + three semaphores */ 115 if (eventfd_write(fd, 2) != 0) { 116 warn("Error while returning two semaphores"); 117 failures++; 118 } 119 if (eventfd_write(fd, 3) != 0) { 120 warn("Error while returning three semaphores"); 121 failures++; 122 } 123 124 /* Consume the available semaphores */ 125 failures += readn(fd, 5); 126 127 /* The next read should return -1/EAGAIN */ 128 failures += check_nosem(fd); 129 130 /* 131 * Check that a writing too large a value results in an error from 132 * eventfd_write() - testing that an error from the underlying write() 133 * is passed back. 134 */ 135 failures += check_badwrite(fd); 136 137 VERIFY0(close(fd)); 138 139 return (failures == 0 ? EXIT_SUCCESS : EXIT_FAILURE); 140 } 141