1 /* 2 * eventfd-sem by Davide Libenzi (Simple test for eventfd sempahore) 3 * Copyright (C) 2009 Davide Libenzi 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation; either version 2 of the License, or 8 * (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program; if not, write to the Free Software 17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 * 19 * Davide Libenzi <davidel (at) xmailserver.org> 20 * Reference: http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commitdiff;h=bcd0b235bf3808dec5115c381cd55568f63b85f0 21 * Reference: http://www.xmailserver.org/eventfd-sem.c 22 * eventfd: testing improved support for semaphore-like behavior in linux-2.6.30 23 * 24 */ 25 26 #include <sys/types.h> 27 #include <sys/syscall.h> 28 #include <sys/stat.h> 29 #include <sys/wait.h> 30 #include <fcntl.h> 31 #include <stdlib.h> 32 #include <stdio.h> 33 #include <string.h> 34 #include <unistd.h> 35 #include <errno.h> 36 #include <inttypes.h> 37 38 #include "test.h" 39 #include "lapi/syscalls.h" 40 41 char *TCID = "eventfd2_03"; 42 int TST_TOTAL = 1; 43 44 #ifndef EFD_SEMLIKE 45 #define EFD_SEMLIKE (1 << 0) 46 #endif 47 48 /* Dummy function as syscall from linux_syscall_numbers.h uses cleanup(). */ 49 void cleanup(void) 50 { 51 } 52 53 static int eventfd2(int count, int flags) 54 { 55 return ltp_syscall(__NR_eventfd2, count, flags); 56 } 57 58 static void xsem_wait(int fd) 59 { 60 u_int64_t cntr; 61 62 if (read(fd, &cntr, sizeof(cntr)) != sizeof(cntr)) { 63 perror("reading eventfd"); 64 exit(1); 65 } 66 fprintf(stdout, "[%u] wait completed on %d: count=%" PRIu64 "\n", 67 getpid(), fd, cntr); 68 } 69 70 static void xsem_post(int fd, int count) 71 { 72 u_int64_t cntr = count; 73 74 if (write(fd, &cntr, sizeof(cntr)) != sizeof(cntr)) { 75 perror("writing eventfd"); 76 exit(1); 77 } 78 } 79 80 static void sem_player(int fd1, int fd2) 81 { 82 fprintf(stdout, "[%u] posting 1 on %d\n", getpid(), fd1); 83 xsem_post(fd1, 1); 84 85 fprintf(stdout, "[%u] waiting on %d\n", getpid(), fd2); 86 xsem_wait(fd2); 87 88 fprintf(stdout, "[%u] posting 1 on %d\n", getpid(), fd1); 89 xsem_post(fd1, 1); 90 91 fprintf(stdout, "[%u] waiting on %d\n", getpid(), fd2); 92 xsem_wait(fd2); 93 94 fprintf(stdout, "[%u] posting 5 on %d\n", getpid(), fd1); 95 xsem_post(fd1, 5); 96 97 fprintf(stdout, "[%u] waiting 5 times on %d\n", getpid(), fd2); 98 xsem_wait(fd2); 99 xsem_wait(fd2); 100 xsem_wait(fd2); 101 xsem_wait(fd2); 102 xsem_wait(fd2); 103 } 104 105 static void usage(char const *prg) 106 { 107 fprintf(stderr, "use: %s [-h]\n", prg); 108 } 109 110 int main(int argc, char **argv) 111 { 112 int c, fd1, fd2, status; 113 pid_t cpid_poster, cpid_waiter; 114 115 while ((c = getopt(argc, argv, "h")) != -1) { 116 switch (c) { 117 default: 118 usage(argv[0]); 119 return 1; 120 } 121 } 122 if ((tst_kvercmp(2, 6, 27)) < 0) { 123 tst_brkm(TCONF, 124 NULL, 125 "This test can only run on kernels that are 2.6.27 and higher"); 126 } 127 if ((fd1 = eventfd2(0, EFD_SEMLIKE)) == -1 || 128 (fd2 = eventfd2(0, EFD_SEMLIKE)) == -1) { 129 perror("eventfd2"); 130 return 1; 131 } 132 if ((cpid_poster = fork()) == 0) { 133 sem_player(fd1, fd2); 134 exit(0); 135 } 136 if ((cpid_waiter = fork()) == 0) { 137 sem_player(fd2, fd1); 138 exit(0); 139 } 140 waitpid(cpid_poster, &status, 0); 141 waitpid(cpid_waiter, &status, 0); 142 143 tst_exit(); 144 } 145