Subrata Modak <[EMAIL PROTECTED]> wrote:
> My observations/comments:
> 1) Get the latest source for the next patch. Some gave hunk failures,
> 2) Build, Install and Run is handled properly across all architectures
> and kernel versions. Go ahead and send the updated patch. I will merge
> them in increments. You can then go ahead and add more in the same
> category.
Hi Subrata,
thanks for the inputs. Here is the updated patch.
Changelog:
* Added basic testcases for eventfd.
Signed-off-by: Vijay Kumar <[EMAIL PROTECTED]>
runtest/syscalls | 2 +
testcases/kernel/include/i386.in | 1 +
testcases/kernel/include/ia64.in | 1 +
testcases/kernel/include/powerpc.in | 1 +
testcases/kernel/include/powerpc64.in | 1 +
testcases/kernel/include/s390.in | 1 +
testcases/kernel/include/s390x.in | 1 +
testcases/kernel/include/sparc.in | 1 +
testcases/kernel/include/sparc64.in | 1 +
testcases/kernel/include/stub-list | 1 +
testcases/kernel/include/x86_64.in | 1 +
testcases/kernel/syscalls/eventfd/Makefile | 32 ++
testcases/kernel/syscalls/eventfd/eventfd01.c | 582 +++++++++++++++++++++++++
13 files changed, 626 insertions(+), 0 deletions(-)
diff --git a/runtest/syscalls b/runtest/syscalls
index 40a6d36..234027c 100644
--- a/runtest/syscalls
+++ b/runtest/syscalls
@@ -101,6 +101,8 @@ dup203 dup203
dup204 dup204
dup205 dup205
+eventfd01 eventfd01
+
execl01 execl01
execle01 execle01
execlp01 execlp01
diff --git a/testcases/kernel/include/i386.in b/testcases/kernel/include/i386.in
index bd61303..df74b6b 100644
--- a/testcases/kernel/include/i386.in
+++ b/testcases/kernel/include/i386.in
@@ -22,6 +22,7 @@ __NR_tee 315
__NR_vmsplice 316
__NR_utimensat 320
__NR_timerfd_create 322
+__NR_eventfd 323
__NR_fallocate 324
__NR_timerfd_settime 325
__NR_timerfd_gettime 326
diff --git a/testcases/kernel/include/ia64.in b/testcases/kernel/include/ia64.in
index ea925b2..54c9910 100644
--- a/testcases/kernel/include/ia64.in
+++ b/testcases/kernel/include/ia64.in
@@ -17,6 +17,7 @@ __NR_tee 1301
__NR_vmsplice 1302
__NR_fallocate 1303
__NR_utimensat 1306
+__NR_eventfd 1309
__NR_timerfd_create 1310
__NR_timerfd_settime 1311
__NR_timerfd_gettime 1312
diff --git a/testcases/kernel/include/powerpc.in
b/testcases/kernel/include/powerpc.in
index 99055d3..4dbd734 100644
--- a/testcases/kernel/include/powerpc.in
+++ b/testcases/kernel/include/powerpc.in
@@ -20,4 +20,5 @@ __NR_symlinkat (__NR_openat + 9)
__NR_readlinkat (__NR_openat + 10)
__NR_fchmodat (__NR_openat + 11)
__NR_faccessat (__NR_openat + 12)
+__NR_eventfd 307
__NR_fallocate 309
diff --git a/testcases/kernel/include/powerpc64.in
b/testcases/kernel/include/powerpc64.in
index 99055d3..4dbd734 100644
--- a/testcases/kernel/include/powerpc64.in
+++ b/testcases/kernel/include/powerpc64.in
@@ -20,4 +20,5 @@ __NR_symlinkat (__NR_openat + 9)
__NR_readlinkat (__NR_openat + 10)
__NR_fchmodat (__NR_openat + 11)
__NR_faccessat (__NR_openat + 12)
+__NR_eventfd 307
__NR_fallocate 309
diff --git a/testcases/kernel/include/s390.in b/testcases/kernel/include/s390.in
index 5eb40e2..ef35cf0 100644
--- a/testcases/kernel/include/s390.in
+++ b/testcases/kernel/include/s390.in
@@ -15,4 +15,5 @@ __NR_faccessat (__NR_openat + 12)
__NR_splice 306
__NR_tee 308
__NR_vmsplice 309
+__NR_eventfd 318
__NR_fallocate 314
diff --git a/testcases/kernel/include/s390x.in
b/testcases/kernel/include/s390x.in
index 8040dd5..0a47f6a 100644
--- a/testcases/kernel/include/s390x.in
+++ b/testcases/kernel/include/s390x.in
@@ -12,4 +12,5 @@ __NR_symlinkat (__NR_openat + 9)
__NR_readlinkat (__NR_openat + 10)
__NR_fchmodat (__NR_openat + 11)
__NR_faccessat (__NR_openat + 12)
+__NR_eventfd 318
__NR_fallocate 314
diff --git a/testcases/kernel/include/sparc.in
b/testcases/kernel/include/sparc.in
index ad4e3ff..fc81530 100644
--- a/testcases/kernel/include/sparc.in
+++ b/testcases/kernel/include/sparc.in
@@ -15,4 +15,5 @@ __NR_symlinkat (__NR_openat + 9)
__NR_readlinkat (__NR_openat + 10)
__NR_fchmodat (__NR_openat + 11)
__NR_faccessat (__NR_openat + 12)
+__NR_eventfd 313
__NR_fallocate 314
diff --git a/testcases/kernel/include/sparc64.in
b/testcases/kernel/include/sparc64.in
index ad4e3ff..1ea80fa 100644
--- a/testcases/kernel/include/sparc64.in
+++ b/testcases/kernel/include/sparc64.in
@@ -15,4 +15,5 @@ __NR_symlinkat (__NR_openat + 9)
__NR_readlinkat (__NR_openat + 10)
__NR_fchmodat (__NR_openat + 11)
__NR_faccessat (__NR_openat + 12)
+__NR_eventd 313
__NR_fallocate 314
diff --git a/testcases/kernel/include/stub-list
b/testcases/kernel/include/stub-list
index 4dde44d..a6738a4 100644
--- a/testcases/kernel/include/stub-list
+++ b/testcases/kernel/include/stub-list
@@ -21,3 +21,4 @@ __NR_timer_delete
__NR_timer_settime
__NR_unlinkat
__NR_vmsplice
+__NR_eventfd
\ No newline at end of file
diff --git a/testcases/kernel/include/x86_64.in
b/testcases/kernel/include/x86_64.in
index 8a326ac..9606c98 100644
--- a/testcases/kernel/include/x86_64.in
+++ b/testcases/kernel/include/x86_64.in
@@ -22,6 +22,7 @@ __NR_tee 276
__NR_vmsplice 278
__NR_utimensat 296
__NR_timerfd_create 283
+__NR_eventfd 284
__NR_fallocate 285
__NR_timerfd_settime 286
__NR_timerfd_gettime 287
diff --git a/testcases/kernel/syscalls/eventfd/Makefile
b/testcases/kernel/syscalls/eventfd/Makefile
new file mode 100644
index 0000000..e2ebae8
--- /dev/null
+++ b/testcases/kernel/syscalls/eventfd/Makefile
@@ -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)
+
diff --git a/testcases/kernel/syscalls/eventfd/eventfd01.c
b/testcases/kernel/syscalls/eventfd/eventfd01.c
new file mode 100644
index 0000000..f099248
--- /dev/null
+++ b/testcases/kernel/syscalls/eventfd/eventfd01.c
@@ -0,0 +1,582 @@
+/*
+ * 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_brkm(TCONF, cleanup, "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*/
+}
-------------------------------------------------------------------------
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