Hi Subrata and Michael,
I have include a patch for the basic eventfd() testcases. I am working
on the counter overflow and exec() related test cases suggested by
Michael. And since Michael wanted an early version, I am including the
patch.
BTW, the eventfd() syscall needs glibc 2.8. But the library itself
does not do much. So it is not really necessary to force the user to
install glibc 2.8 to test eventfd. I have directly invoked the syscall
using syscall(). For the syscall numbers, I have modified the .in
files under testcases/kernel/include. I am not sure if this is the
right approach. Please do send in your comments.
Signed-off-by: Vijay Kumar B. <[EMAIL PROTECTED]>
Index: ltp-mod/testcases/kernel/syscalls/eventfd/Makefile
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ ltp-mod/testcases/kernel/syscalls/eventfd/Makefile 2008-07-25
23:24:24.000000000 +0530
@@ -0,0 +1,32 @@
+#
+# Copyright (c) International Business Machines Corp., 2001
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
+# the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+#
+
+CFLAGS += -I../../../../include -Wall
+LDLIBS += -L../../../../lib -lltp
+
+SRCS = $(wildcard *.c)
+TARGETS = $(patsubst %.c, %, $(wildcard *.c))
+
+all: $(TARGETS)
+
+install:
+ @set -e; for i in $(TARGETS); do ln -f $$i ../../../bin/$$i ; done
+
+clean:
+ rm -f $(TARGETS)
+
Index: ltp-mod/testcases/kernel/syscalls/eventfd/eventfd01.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ ltp-mod/testcases/kernel/syscalls/eventfd/eventfd01.c 2008-07-28
22:56:33.000000000 +0530
@@ -0,0 +1,583 @@
+/*
+ * Copyright (c) 2008 Vijay Kumar B. <[EMAIL PROTECTED]>
+ *
+ * Based on testcases/kernel/syscalls/waitpid/waitpid01.c
+ * Original copyright message:
+ *
+ * Copyright (c) International Business Machines Corp., 2001
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
+ * the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/*
+ * NAME
+ * eventfd01.c
+ *
+ * DESCRIPTION
+ * Test cases for eventfd syscall.
+ *
+ * USAGE: <for command-line>
+ * eventfd01 [-c n] [-i n] [-I x] [-P x] [-t]
+ * where, -c n : Run n copies concurrently.
+ * -i n : Execute test n times.
+ * -I x : Execute test for x seconds.
+ * -P x : Pause for x seconds between iterations.
+ * -t : Turn on syscall timing.
+ *
+ * History
+ * 07/2008 Vijay Kumar
+ * Initial Version.
+ *
+ * Restrictions
+ * None
+ */
+
+#include <sys/select.h>
+#include <sys/signal.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <string.h>
+#include <stdint.h>
+
+#include <test.h>
+#include <usctest.h>
+#include <linux_syscall_numbers.h>
+
+static void setup(void);
+static void cleanup(void);
+
+char *TCID = "eventfd01";
+int TST_TOTAL = 12;
+extern int Tst_count;
+
+static int
+myeventfd(unsigned int initval, int flags)
+{
+ return syscall(__NR_eventfd, initval);
+}
+
+/*
+ * clear_counter() - clears the counter by performing a dummy read
+ * @fd: the eventfd
+ *
+ * RETURNS:
+ * 0 on success, and -1 on failure
+ */
+static int
+clear_counter(int fd)
+{
+ uint64_t dummy;
+ int ret;
+
+ ret = read(fd, &dummy, sizeof(dummy));
+ if (ret == -1) {
+ if (errno != EAGAIN) {
+ tst_resm(TBROK, "error clearing counter: %s",
+ strerror(errno));
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * set_counter() - sets the count to specified value
+ * @fd: the eventfd
+ * @val: the value to be set
+ *
+ * Clears the counter and sets the counter to @val.
+ *
+ * RETURNS:
+ * 0 on success, -1 on failure
+ */
+static int
+set_counter(int fd, uint64_t val)
+{
+ int ret;
+
+ ret = clear_counter(fd);
+ if (ret == -1) {
+ return -1;
+ }
+
+ ret = write(fd, &val, sizeof(val));
+ if (ret == -1) {
+ tst_resm(TBROK, "error setting counter value: %s",
+ strerror(errno));
+ return -1;
+ }
+
+ return 0;
+}
+
+/*
+ * Test whether the current value of the counter matches @required.
+ */
+static void
+read_test(int fd, uint64_t required)
+{
+ int ret;
+ uint64_t val;
+
+ ret = read(fd, &val, sizeof(val));
+ if (ret == -1) {
+ tst_resm(TBROK, "error reading eventfd: %s",
+ strerror(errno));
+ return;
+ }
+
+ if (val == required)
+ tst_resm(TPASS, "counter value matches required");
+ else
+ tst_resm(TFAIL, "counter value mismatch: "
+ "required: %llu, got: %llu", required, val);
+}
+
+/*
+ * Test whether read returns with error EAGAIN when counter is at 0.
+ */
+static void
+read_eagain_test(int fd)
+{
+ int ret;
+ uint64_t val;
+
+ ret = clear_counter(fd);
+ if (ret == -1)
+ return;
+
+ ret = read(fd, &val, sizeof(val));
+ if (ret == -1) {
+ if (errno == EAGAIN)
+ tst_resm(TPASS, "read failed with EAGAIN as expected");
+ else
+ tst_resm(TFAIL, "read failed with unexpected "
+ "error: %s", strerror(errno));
+ } else {
+ tst_resm(TFAIL, "read returned with %d");
+ }
+}
+
+/*
+ * Test whether writing to counter works.
+ */
+static void
+write_test(int fd)
+{
+ int ret;
+ uint64_t val;
+
+ val = 12;
+
+ ret = set_counter(fd, val);
+ if (ret == -1)
+ return;
+
+ read_test(fd, val);
+}
+
+/*
+ * Test whether write returns with error EAGAIN when counter is at
+ * (UINT64_MAX - 1).
+ */
+static void
+write_eagain_test(int fd)
+{
+ int ret;
+ uint64_t val;
+
+ ret = set_counter(fd, UINT64_MAX - 1);
+ if (ret == -1)
+ return;
+
+ val = 1;
+ ret = write(fd, &val, sizeof(val));
+ if (ret == -1) {
+ if (errno == EAGAIN)
+ tst_resm(TPASS, "write failed with EAGAIN as "
+ "expected");
+ else
+ tst_resm(TFAIL, "write returned with unexpected "
+ "error: %s", strerror(errno));
+ } else {
+ tst_resm(TFAIL, "write returned with %d", ret);
+ }
+}
+
+/*
+ * Test whether read returns with error EINVAL, if buffer size is less
+ * than 8 bytes.
+ */
+static void
+read_einval_test(int fd)
+{
+ uint32_t invalid;
+ int ret;
+
+ ret = read(fd, &invalid, sizeof(invalid));
+ if (ret == -1) {
+ if (errno == EINVAL) {
+ tst_resm(TPASS, "read failed with EINVAL as expected");
+ } else {
+ tst_resm(TFAIL, "read returned with unexpected "
+ "error: %s", strerror(errno));
+ }
+ } else {
+ tst_resm(TFAIL, "read returned with %d", ret);
+ }
+}
+
+/*
+ * Test whether write returns with error EINVAL, if buffer size is
+ * less than 8 bytes.
+ */
+static void
+write_einval_test(int fd)
+{
+ uint32_t invalid;
+ int ret;
+
+ ret = write(fd, &invalid, sizeof(invalid));
+ if (ret == -1) {
+ if (errno == EINVAL) {
+ tst_resm(TPASS, "write failed with EINVAL as "
+ "expected");
+ } else {
+ tst_resm(TFAIL, "write returned with unexpected "
+ "error: %s", strerror(errno));
+ }
+ } else {
+ tst_resm(TFAIL, "write returned with %d", ret);
+ }
+}
+
+/*
+ * Test wheter write returns with error EINVAL, when the written value
+ * is 0xFFFFFFFFFFFFFFFF.
+ */
+static void
+write_einval2_test(int fd)
+{
+ int ret;
+ uint64_t val;
+
+ ret = clear_counter(fd);
+ if (ret == -1)
+ return;
+
+ val = 0xffffffffffffffffLL;
+ ret = write(fd, &val, sizeof(val));
+ if (ret == -1) {
+ if (errno == EINVAL)
+ tst_resm(TPASS, "write failed with EINVAL as "
+ "expected");
+ else
+ tst_resm(TFAIL, "write returned with unexpected "
+ "error: %s", strerror(errno));
+ } else {
+ tst_resm(TFAIL, "write returned with %d", ret);
+ }
+}
+
+/*
+ * Test whether readfd is set by select when counter value is
+ * non-zero.
+ */
+static void
+readfd_set_test(int fd)
+{
+ int ret;
+ fd_set readfds;
+ struct timeval timeout = { 0, 0 };
+ uint64_t non_zero = 10;
+
+ FD_ZERO(&readfds);
+ FD_SET(fd, &readfds);
+
+ ret = set_counter(fd, non_zero);
+ if (ret == -1)
+ return;
+
+ ret = select(fd + 1, &readfds, NULL, NULL, &timeout);
+ if (ret == -1) {
+ /* EINTR cannot occur, since we don't block. */
+ tst_resm(TBROK, "select: error getting fd status: %s",
+ strerror(errno));
+ return;
+ }
+
+ if (FD_ISSET(fd, &readfds))
+ tst_resm(TPASS, "fd is set in readfds");
+ else
+ tst_resm(TFAIL, "fd is not set in readfds");
+}
+
+/*
+ * Test whether readfd is not set by select when counter value is
+ * zero.
+ */
+static void
+readfd_not_set_test(int fd)
+{
+ int ret;
+ fd_set readfds;
+ struct timeval timeout = { 0, 0 };
+
+ FD_ZERO(&readfds);
+ FD_SET(fd, &readfds);
+
+ ret = clear_counter(fd);
+ if (ret == -1)
+ return;
+
+ ret = select(fd + 1, &readfds, NULL, NULL, &timeout);
+ if (ret == -1) {
+ /* EINTR cannot occur, since we don't block. */
+ tst_resm(TBROK, "select: error getting fd status: %s",
+ strerror(errno));
+ return;
+ }
+
+ if (!FD_ISSET(fd, &readfds))
+ tst_resm(TPASS, "fd is not set in readfds");
+ else
+ tst_resm(TFAIL, "fd is set in readfds");
+}
+
+/*
+ * Test whether writefd is set by select when counter value is not the
+ * maximum counter value.
+ */
+static void
+writefd_set_test(int fd)
+{
+ int ret;
+ fd_set writefds;
+ struct timeval timeout = { 0, 0 };
+ uint64_t non_max = 10;
+
+ FD_ZERO(&writefds);
+ FD_SET(fd, &writefds);
+
+ ret = set_counter(fd, non_max);
+ if (ret == -1)
+ return;
+
+ ret = select(fd + 1, NULL, &writefds, NULL, &timeout);
+ if (ret == -1) {
+ /* EINTR cannot occur, since we don't block. */
+ tst_resm(TBROK, "select: error getting fd status: %s",
+ strerror(errno));
+ return;
+ }
+
+ if (FD_ISSET(fd, &writefds))
+ tst_resm(TPASS, "fd is set in writefds");
+ else
+ tst_resm(TFAIL, "fd is not set in writefds");
+}
+
+/*
+ * Test whether writefd is not set by select when counter value is at
+ * (UINT64_MAX - 1).
+ */
+static void
+writefd_not_set_test(int fd)
+{
+ int ret;
+ fd_set writefds;
+ struct timeval timeout = { 0, 0 };
+
+ FD_ZERO(&writefds);
+ FD_SET(fd, &writefds);
+
+ ret = set_counter(fd, UINT64_MAX - 1);
+ if (ret == -1)
+ return;
+
+ ret = select(fd + 1, NULL, &writefds, NULL, &timeout);
+ if (ret == -1) {
+ /* EINTR cannot occur, since we don't block. */
+ tst_resm(TBROK, "select: error getting fd status: %s",
+ strerror(errno));
+ return;
+ }
+
+ if (!FD_ISSET(fd, &writefds))
+ tst_resm(TPASS, "fd is not set in writefds");
+ else
+ tst_resm(TFAIL, "fd is set in writefds");
+}
+
+/*
+ * Test whether counter update in child is reflected in the parent.
+ */
+static void
+child_inherit_test(int fd)
+{
+ uint64_t val;
+ pid_t cpid;
+ int ret;
+ int status;
+ uint64_t to_parent = 0xdeadbeef;
+ uint64_t dummy;
+
+ cpid = fork();
+ if (cpid == -1)
+ tst_resm(TBROK, "error while forking child: %s",
+ strerror(errno));
+ if (cpid != 0) {
+ /* Parent */
+ ret = wait(&status);
+ if (ret == -1) {
+ tst_resm(TBROK, "error getting child exit status");
+ return;
+ }
+
+ if (WEXITSTATUS(status) == 1) {
+ tst_resm(TBROK, "counter value write not "
+ "succesful in child");
+ return;
+ }
+
+ ret = read(fd, &val, sizeof(val));
+ if (ret == -1) {
+ tst_resm(TBROK, "error reading eventfd: %s",
+ strerror(errno));
+ return;
+ }
+
+ if (val == to_parent)
+ tst_resm(TPASS, "counter value write from "
+ "child successful");
+ else
+ tst_resm(TFAIL, "counter value write in child "
+ "failed");
+ } else {
+ /* Child */
+ ret = read(fd, &dummy, sizeof(dummy));
+ if (ret == -1 && errno != EAGAIN) {
+ tst_resm(TWARN, "error clearing counter: %s",
+ strerror(errno));
+ exit(1);
+ }
+
+ ret = write(fd, &to_parent, sizeof(to_parent));
+ if (ret == -1) {
+ tst_resm(TWARN, "error writing eventfd: %s",
+ strerror(errno));
+ exit(1);
+ }
+
+ exit(0);
+ }
+}
+
+int
+main(int argc, char **argv)
+{
+ int lc; /* loop counter */
+ char *msg; /* message returned from parse_opts */
+ int fd;
+
+ /* parse standard options */
+ msg = parse_opts(argc, argv, (option_t *) NULL, NULL);
+ if (msg != NULL) {
+ tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg);
+ tst_exit();
+ /* NOTREACHED */
+ }
+
+ setup();
+
+ /* check for looping state if -i option is given */
+ for (lc = 0; TEST_LOOPING(lc); lc++) {
+ int ret;
+ uint64_t einit = 10;
+
+ /* reset Tst_count in case we are looping */
+ Tst_count = 0;
+
+ fd = myeventfd(einit, 0);
+ if (fd == -1)
+ tst_brkm(TBROK, cleanup, "error creating eventfd: %s",
+ strerror(errno));
+
+ ret = fcntl(fd, F_SETFL, O_NONBLOCK);
+ if (ret == -1)
+ tst_brkm(TBROK, cleanup,
+ "error setting non-block mode: %s", strerror);
+
+ read_test(fd, einit);
+ read_eagain_test(fd);
+ write_test(fd);
+ write_eagain_test(fd);
+ read_einval_test(fd);
+ write_einval_test(fd);
+ write_einval2_test(fd);
+ readfd_set_test(fd);
+ readfd_not_set_test(fd);
+ writefd_set_test(fd);
+ writefd_not_set_test(fd);
+ child_inherit_test(fd);
+
+ close(fd);
+ }
+
+ cleanup();
+ /* NOT REACHED */
+
+ return 0;
+}
+
+/*
+ * setup() - performs all ONE TIME setup for this test
+ */
+static void
+setup(void)
+{
+ /* capture signals */
+ tst_sig(FORK, DEF_HANDLER, cleanup);
+
+ if (tst_kvercmp(2, 6, 22) < 0) {
+ tst_resm(TCONF, "2.6.22 or greater kernel required");
+ }
+
+ /* Pause if that option was specified
+ * TEST_PAUSE contains the code to fork the test with the -c option.
+ */
+ TEST_PAUSE;
+}
+
+/*
+ * cleanup() - performs all ONE TIME cleanup for this test
+ */
+static void
+cleanup(void)
+{
+ /*
+ * print timing stats if that option was specified.
+ * print errno log if that option was specified.
+ */
+ TEST_CLEANUP;
+
+ /* exit with return code appropriate for results */
+ tst_exit();
+ /*NOTREACHED*/
+}
Index: ltp-mod/testcases/kernel/include/i386.in
===================================================================
--- ltp-mod.orig/testcases/kernel/include/i386.in 2008-07-25
23:55:11.000000000 +0530
+++ ltp-mod/testcases/kernel/include/i386.in 2008-07-26 00:16:54.000000000
+0530
@@ -21,6 +21,7 @@
__NR_tee 315
__NR_vmsplice 316
__NR_timerfd_create 322
+__NR_eventfd 323
__NR_fallocate 324
__NR_timerfd_settime 325
__NR_timerfd_gettime 326
Index: ltp-mod/testcases/kernel/include/ia64.in
===================================================================
--- ltp-mod.orig/testcases/kernel/include/ia64.in 2008-07-25
23:55:11.000000000 +0530
+++ ltp-mod/testcases/kernel/include/ia64.in 2008-07-26 00:21:45.000000000
+0530
@@ -16,3 +16,4 @@
__NR_tee 1301
__NR_vmsplice 1302
__NR_fallocate 1303
+__NR_eventfd 1309
\ No newline at end of file
Index: ltp-mod/testcases/kernel/include/stub-list
===================================================================
--- ltp-mod.orig/testcases/kernel/include/stub-list 2008-07-26
00:10:40.000000000 +0530
+++ ltp-mod/testcases/kernel/include/stub-list 2008-07-26 00:10:47.000000000
+0530
@@ -21,3 +21,4 @@
__NR_timer_settime
__NR_unlinkat
__NR_vmsplice
+__NR_eventfd
\ No newline at end of file
Index: ltp-mod/testcases/kernel/include/x86_64.in
===================================================================
--- ltp-mod.orig/testcases/kernel/include/x86_64.in 2008-07-25
23:55:11.000000000 +0530
+++ ltp-mod/testcases/kernel/include/x86_64.in 2008-07-26 00:22:31.000000000
+0530
@@ -21,6 +21,7 @@
__NR_tee 276
__NR_vmsplice 278
__NR_timerfd_create 283
+__NR_eventfd 284
__NR_fallocate 285
__NR_timerfd_settime 286
__NR_timerfd_gettime 287
Index: ltp-mod/testcases/kernel/include/powerpc.in
===================================================================
--- ltp-mod.orig/testcases/kernel/include/powerpc.in 2008-07-25
23:55:11.000000000 +0530
+++ ltp-mod/testcases/kernel/include/powerpc.in 2008-07-27 23:08:28.000000000
+0530
@@ -20,4 +20,5 @@
__NR_readlinkat (__NR_openat + 10)
__NR_fchmodat (__NR_openat + 11)
__NR_faccessat (__NR_openat + 12)
+__NR_eventfd 307
__NR_fallocate 309
Index: ltp-mod/testcases/kernel/include/powerpc64.in
===================================================================
--- ltp-mod.orig/testcases/kernel/include/powerpc64.in 2008-07-25
23:55:11.000000000 +0530
+++ ltp-mod/testcases/kernel/include/powerpc64.in 2008-07-27
23:08:43.000000000 +0530
@@ -20,4 +20,5 @@
__NR_readlinkat (__NR_openat + 10)
__NR_fchmodat (__NR_openat + 11)
__NR_faccessat (__NR_openat + 12)
+__NR_eventfd 307
__NR_fallocate 309
Index: ltp-mod/testcases/kernel/include/s390.in
===================================================================
--- ltp-mod.orig/testcases/kernel/include/s390.in 2008-07-25
23:55:11.000000000 +0530
+++ ltp-mod/testcases/kernel/include/s390.in 2008-07-27 23:09:12.000000000
+0530
@@ -15,4 +15,5 @@
__NR_splice 306
__NR_tee 308
__NR_vmsplice 309
+__NR_eventfd 318
__NR_fallocate 314
Index: ltp-mod/testcases/kernel/include/s390x.in
===================================================================
--- ltp-mod.orig/testcases/kernel/include/s390x.in 2008-07-25
23:55:11.000000000 +0530
+++ ltp-mod/testcases/kernel/include/s390x.in 2008-07-27 23:09:40.000000000
+0530
@@ -12,4 +12,5 @@
__NR_readlinkat (__NR_openat + 10)
__NR_fchmodat (__NR_openat + 11)
__NR_faccessat (__NR_openat + 12)
+__NR_eventfd 318
__NR_fallocate 314
Index: ltp-mod/testcases/kernel/include/sparc.in
===================================================================
--- ltp-mod.orig/testcases/kernel/include/sparc.in 2008-07-25
23:55:11.000000000 +0530
+++ ltp-mod/testcases/kernel/include/sparc.in 2008-07-27 23:10:11.000000000
+0530
@@ -15,4 +15,5 @@
__NR_readlinkat (__NR_openat + 10)
__NR_fchmodat (__NR_openat + 11)
__NR_faccessat (__NR_openat + 12)
+__NR_eventfd 313
__NR_fallocate 314
Index: ltp-mod/testcases/kernel/include/sparc64.in
===================================================================
--- ltp-mod.orig/testcases/kernel/include/sparc64.in 2008-07-25
23:55:11.000000000 +0530
+++ ltp-mod/testcases/kernel/include/sparc64.in 2008-07-27 23:10:28.000000000
+0530
@@ -15,4 +15,5 @@
__NR_readlinkat (__NR_openat + 10)
__NR_fchmodat (__NR_openat + 11)
__NR_faccessat (__NR_openat + 12)
+__NR_eventd 313
__NR_fallocate 314
Index: ltp-mod/runtest/syscalls
===================================================================
--- ltp-mod.orig/runtest/syscalls 2008-07-28 22:51:22.000000000 +0530
+++ ltp-mod/runtest/syscalls 2008-07-28 22:52:49.000000000 +0530
@@ -101,6 +101,8 @@
dup204 dup204
dup205 dup205
+eventfd01 eventfd01
+
execl01 execl01
execle01 execle01
execlp01 execlp01
-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
_______________________________________________
Ltp-list mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/ltp-list