Port tests/timerfd.c
authorBarret Rhoden <brho@cs.berkeley.edu>
Fri, 8 Apr 2016 15:59:34 +0000 (11:59 -0400)
committerBarret Rhoden <brho@cs.berkeley.edu>
Fri, 15 Apr 2016 14:29:13 +0000 (10:29 -0400)
Removes the LTP integration, uses select instead of poll, adds more
thorough tests, and fixes some checkpatch complaints.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
tests/timerfd.c [new file with mode: 0644]
tests/timerfd.c.orig [deleted file]

diff --git a/tests/timerfd.c b/tests/timerfd.c
new file mode 100644 (file)
index 0000000..2974c7f
--- /dev/null
@@ -0,0 +1,296 @@
+/*
+ *  timerfd() test by Davide Libenzi (test app for timerfd)
+ *  Copyright (C) 2007  Davide Libenzi
+ *
+ *  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
+ *
+ *  Davide Libenzi <davidel@xmailserver.org>
+ *
+ *
+ *     $ gcc -o timerfd-test2 timerfd-test2.c -lrt
+ *
+ * NAME
+ *     timerfd01.c
+ * HISTORY
+ *     28/05/2008 Initial contribution by Davide Libenzi <davidel@xmailserver.org>
+ *     28/05/2008 Integrated to LTP by Subrata Modak <subrata@linux.vnet.ibm.com>
+ *     2016-04-08 Deintegrated from LTP by Barret Rhoden <brho@cs.berkeley.edu>
+ *             Ported to Akaros.  Added a few more tests.
+ */
+
+#define _GNU_SOURCE
+#include <sys/syscall.h>
+#include <sys/types.h>
+#include <sys/signal.h>
+#include <sys/time.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <signal.h>
+#include <poll.h>
+#include <fcntl.h>
+#include <time.h>
+#include <errno.h>
+
+#include <sys/timerfd.h>
+#include <sys/select.h>
+#include <benchutil/alarm.h>
+#include <parlib/uthread.h>
+
+struct tmr_type {
+       int id;
+       char const *name;
+};
+
+unsigned long long getustime(int clockid)
+{
+       struct timespec tp;
+
+       if (clock_gettime((clockid_t) clockid, &tp)) {
+               perror("clock_gettime");
+               return 0;
+       }
+
+       return 1000000ULL * tp.tv_sec + tp.tv_nsec / 1000;
+}
+
+void set_timespec(struct timespec *tmr, unsigned long long ustime)
+{
+
+       tmr->tv_sec = (time_t) (ustime / 1000000ULL);
+       tmr->tv_nsec = (long)(1000ULL * (ustime % 1000000ULL));
+}
+
+
+long waittmr(int tfd, int timeo)
+{
+       u_int64_t ticks;
+       fd_set rfds;
+       struct timeval tv, *timeout = 0;
+       int ret;
+
+       FD_ZERO(&rfds);
+       FD_SET(tfd, &rfds);
+       if (timeo != -1) {
+               tv.tv_sec = timeo / 1000;
+               tv.tv_usec = (timeo % 1000) * 1000;
+               timeout = &tv;
+       }
+       ret = select(tfd + 1, &rfds, 0, 0, timeout);
+       if (ret < 0) {
+               perror("select");
+               return -1;
+       }
+       if (ret == 0) {
+               fprintf(stdout, "no ticks happened\n");
+               return -1;
+       }
+       if (read(tfd, &ticks, sizeof(ticks)) != sizeof(ticks)) {
+               perror("timerfd read");
+               return -1;
+       }
+       return ticks;
+}
+
+int main(int ac, char **av)
+{
+       int i, tfd;
+       long ticks;
+       unsigned long long tnow, ttmr;
+       u_int64_t uticks;
+       struct itimerspec tmr;
+       struct tmr_type clks[] = {
+               {CLOCK_MONOTONIC, "CLOCK MONOTONIC"},
+               {CLOCK_REALTIME, "CLOCK REALTIME"},
+       };
+
+       for (i = 0; i < sizeof(clks) / sizeof(clks[0]); i++) {
+               fprintf(stdout,
+                       "\n\n---------------------------------------\n");
+               fprintf(stdout, "| testing %s\n", clks[i].name);
+               fprintf(stdout, "---------------------------------------\n\n");
+
+               fprintf(stdout, "relative timer test (at 500 ms) ...\n");
+               set_timespec(&tmr.it_value, 500 * 1000);
+               set_timespec(&tmr.it_interval, 0);
+               tnow = getustime(clks[i].id);
+               if ((tfd = timerfd_create(clks[i].id, 0)) == -1) {
+                       perror("timerfd");
+                       return 1;
+               }
+               fprintf(stdout, "timerfd = %d\n", tfd);
+
+               if (timerfd_settime(tfd, 0, &tmr, NULL)) {
+                       perror("timerfd_settime");
+                       return 1;
+               }
+
+               fprintf(stdout, "waiting timer ...\n");
+               ticks = waittmr(tfd, -1);
+               ttmr = getustime(clks[i].id);
+               if (ticks <= 0)
+                       fprintf(stdout, "whooops! no timer showed up!\n");
+               else
+                       fprintf(stdout, "got timer ticks (%ld) after %llu ms\n",
+                               ticks, (ttmr - tnow) / 1000);
+
+               fprintf(stdout, "absolute timer test (at 500 ms) ...\n");
+               tnow = getustime(clks[i].id);
+               set_timespec(&tmr.it_value, tnow + 500 * 1000);
+               set_timespec(&tmr.it_interval, 0);
+               if (timerfd_settime(tfd, TFD_TIMER_ABSTIME, &tmr, NULL)) {
+                       perror("timerfd_settime");
+                       return 1;
+               }
+
+               fprintf(stdout, "waiting timer ...\n");
+               ticks = waittmr(tfd, -1);
+               ttmr = getustime(clks[i].id);
+               if (ticks <= 0)
+                       fprintf(stdout, "whooops! no timer showed up!\n");
+               else
+                       fprintf(stdout, "got timer ticks (%ld) after %llu ms\n",
+                               ticks, (ttmr - tnow) / 1000);
+
+               fprintf(stdout, "sequential timer test (100 ms clock) ...\n");
+               tnow = getustime(clks[i].id);
+               set_timespec(&tmr.it_value, tnow + 100 * 1000);
+               set_timespec(&tmr.it_interval, 100 * 1000);
+               if (timerfd_settime(tfd, TFD_TIMER_ABSTIME, &tmr, NULL)) {
+                       perror("timerfd_settime");
+                       return 1;
+               }
+
+               fprintf(stdout, "sleeping 1 second ...\n");
+               sleep(1);
+               if (timerfd_gettime(tfd, &tmr)) {
+                       perror("timerfd_gettime");
+                       return 1;
+               }
+               fprintf(stdout, "timerfd_gettime returned:\n"
+                       "\tit_value = { %ld, %ld } it_interval = { %ld, %ld }\n",
+                       (long)tmr.it_value.tv_sec, (long)tmr.it_value.tv_nsec,
+                       (long)tmr.it_interval.tv_sec,
+                       (long)tmr.it_interval.tv_nsec);
+               fprintf(stdout, "sleeping 1 second ...\n");
+               sleep(1);
+
+               fprintf(stdout, "waiting timer ...\n");
+               ticks = waittmr(tfd, -1);
+               ttmr = getustime(clks[i].id);
+               if (ticks <= 0)
+                       fprintf(stdout, "whooops! no timer showed up!\n");
+               else
+                       fprintf(stdout, "got timer ticks (%ld) after %llu ms\n",
+                               ticks, (ttmr - tnow) / 1000);
+
+               fprintf(stdout, "O_NONBLOCK test ...\n");
+               tnow = getustime(clks[i].id);
+               set_timespec(&tmr.it_value, 100 * 1000);
+               set_timespec(&tmr.it_interval, 0);
+               if (timerfd_settime(tfd, 0, &tmr, NULL)) {
+                       perror("timerfd_settime");
+                       return 1;
+               }
+               fprintf(stdout, "timerfd = %d\n", tfd);
+
+               fprintf(stdout, "waiting timer (flush the single tick) ...\n");
+               ticks = waittmr(tfd, -1);
+               ttmr = getustime(clks[i].id);
+               if (ticks <= 0)
+                       fprintf(stdout, "whooops! no timer showed up!\n");
+               else
+                       fprintf(stdout, "got timer ticks (%ld) after %llu ms\n",
+                               ticks, (ttmr - tnow) / 1000);
+
+               fcntl(tfd, F_SETFL, fcntl(tfd, F_GETFL, 0) | O_NONBLOCK);
+
+               if (read(tfd, &uticks, sizeof(uticks)) > 0)
+                       fprintf(stdout,
+                               "whooops! timer ticks not zero when should have been\n");
+               else if (errno != EAGAIN)
+                       fprintf(stdout,
+                               "whooops! bad errno value (%d = '%s')!\n",
+                               errno, strerror(errno));
+               else
+                       fprintf(stdout, "success\n");
+
+               /* try a select loop with O_NONBLOCK */
+               fd_set rfds;
+               bool has_selected = FALSE;
+               int ret;
+
+               FD_ZERO(&rfds);
+               FD_SET(tfd, &rfds);
+               set_timespec(&tmr.it_value, 1000000);
+               set_timespec(&tmr.it_interval, 0);
+               if (timerfd_settime(tfd, 0, &tmr, NULL)) {
+                       perror("timerfd_settime");
+                       exit(-1);
+               }
+               while (1) {
+                       ret = read(tfd, &uticks, sizeof(uticks));
+                       if (ret < 0) {
+                               if (errno != EAGAIN) {
+                                       perror("select read");
+                                       exit(-1);
+                               }
+                       } else {
+                               if (ret != sizeof(uticks)) {
+                                       fprintf(stdout, "short read! (bad)\n");
+                                       exit(-1);
+                               }
+                               if (uticks)
+                                       break;
+                       }
+                       if (select(tfd + 1, &rfds, 0, 0, 0) < 0) {
+                               perror("select");
+                               return -1;
+                       }
+                       has_selected = TRUE;
+               }
+               if (!has_selected) {
+                       fprintf(stdout, "Failed to try to select!\n");
+                       exit(-1);
+               }
+               fprintf(stdout, "more success\n");
+               fcntl(tfd, F_SETFL, fcntl(tfd, F_GETFL, 0) & ~O_NONBLOCK);
+
+               /* let's make sure it actually blocks too. */
+               struct alarm_waiter waiter;
+
+               init_awaiter(&waiter, alarm_abort_sysc);
+               waiter.data = current_uthread;
+               set_awaiter_rel(&waiter, 1000000);
+
+               set_timespec(&tmr.it_value, 10000000);
+               set_timespec(&tmr.it_interval, 0);
+               if (timerfd_settime(tfd, 0, &tmr, NULL)) {
+                       perror("timerfd_settime");
+                       exit(-1);
+               }
+               set_alarm(&waiter);
+               ret = read(tfd, &uticks, sizeof(uticks));
+               unset_alarm(&waiter);
+               if (ret > 0) {
+                       fprintf(stdout, "Failed to block when we should have!\n");
+                       exit(-1);
+               }
+               fprintf(stdout, "done (still success)\n");
+
+               close(tfd);
+       }
+}
diff --git a/tests/timerfd.c.orig b/tests/timerfd.c.orig
deleted file mode 100644 (file)
index 00bae88..0000000
+++ /dev/null
@@ -1,279 +0,0 @@
-/*
- *  timerfd() test by Davide Libenzi (test app for timerfd)
- *  Copyright (C) 2007  Davide Libenzi
- *
- *  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
- *
- *  Davide Libenzi <davidel@xmailserver.org>
- *
- *
- *     $ gcc -o timerfd-test2 timerfd-test2.c -lrt
- *
- * NAME
- *     timerfd01.c
- * HISTORY
- *     28/05/2008 Initial contribution by Davide Libenzi <davidel@xmailserver.org>
- *      28/05/2008 Integrated to LTP by Subrata Modak <subrata@linux.vnet.ibm.com>
- */
-
-#define _GNU_SOURCE
-#include <sys/syscall.h>
-#include <sys/types.h>
-#include <sys/signal.h>
-#include <sys/time.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <signal.h>
-#include <poll.h>
-#include <fcntl.h>
-#include <time.h>
-#include <errno.h>
-#include "test.h"
-#include "linux_syscall_numbers.h"
-
-#define cleanup tst_exit
-
-char *TCID = "timerfd01";
-
-/*
- * This were good at the time of 2.6.23-rc7 ...
- *
- * #ifdef __NR_timerfd
- *
- * ... but is not now with 2.6.25
- */
-#ifdef __NR_timerfd_create
-
-/* Definitions from include/linux/timerfd.h */
-#define TFD_TIMER_ABSTIME (1 << 0)
-
-struct tmr_type {
-       int id;
-       char const *name;
-};
-
-unsigned long long getustime(int clockid)
-{
-       struct timespec tp;
-
-       if (clock_gettime((clockid_t) clockid, &tp)) {
-               perror("clock_gettime");
-               return 0;
-       }
-
-       return 1000000ULL * tp.tv_sec + tp.tv_nsec / 1000;
-}
-
-void set_timespec(struct timespec *tmr, unsigned long long ustime)
-{
-
-       tmr->tv_sec = (time_t) (ustime / 1000000ULL);
-       tmr->tv_nsec = (long)(1000ULL * (ustime % 1000000ULL));
-}
-
-int timerfd_create(int clockid, int flags)
-{
-
-       return ltp_syscall(__NR_timerfd_create, clockid, flags);
-}
-
-int timerfd_settime(int ufc, int flags, const struct itimerspec *utmr,
-                   struct itimerspec *otmr)
-{
-
-       return ltp_syscall(__NR_timerfd_settime, ufc, flags, utmr, otmr);
-}
-
-int timerfd_gettime(int ufc, struct itimerspec *otmr)
-{
-
-       return ltp_syscall(__NR_timerfd_gettime, ufc, otmr);
-}
-
-long waittmr(int tfd, int timeo)
-{
-       u_int64_t ticks;
-       struct pollfd pfd;
-
-       pfd.fd = tfd;
-       pfd.events = POLLIN;
-       pfd.revents = 0;
-       if (poll(&pfd, 1, timeo) < 0) {
-               perror("poll");
-               return -1;
-       }
-       if ((pfd.revents & POLLIN) == 0) {
-               fprintf(stdout, "no ticks happened\n");
-               return -1;
-       }
-       if (read(tfd, &ticks, sizeof(ticks)) != sizeof(ticks)) {
-               perror("timerfd read");
-               return -1;
-       }
-
-       return ticks;
-}
-
-int TST_TOTAL = 3;
-
-int main(int ac, char **av)
-{
-       int i, tfd;
-       long ticks;
-       unsigned long long tnow, ttmr;
-       u_int64_t uticks;
-       struct itimerspec tmr;
-       struct tmr_type clks[] = {
-               {CLOCK_MONOTONIC, "CLOCK MONOTONIC"},
-               {CLOCK_REALTIME, "CLOCK REALTIME"},
-       };
-
-       if ((tst_kvercmp(2, 6, 25)) < 0) {
-               tst_resm(TCONF, "This test can only run on kernels that are ");
-               tst_resm(TCONF, "2.6.25 and higher");
-               exit(0);
-       }
-
-       for (i = 0; i < sizeof(clks) / sizeof(clks[0]); i++) {
-               fprintf(stdout,
-                       "\n\n---------------------------------------\n");
-               fprintf(stdout, "| testing %s\n", clks[i].name);
-               fprintf(stdout, "---------------------------------------\n\n");
-
-               fprintf(stdout, "relative timer test (at 500 ms) ...\n");
-               set_timespec(&tmr.it_value, 500 * 1000);
-               set_timespec(&tmr.it_interval, 0);
-               tnow = getustime(clks[i].id);
-               if ((tfd = timerfd_create(clks[i].id, 0)) == -1) {
-                       perror("timerfd");
-                       return 1;
-               }
-               fprintf(stdout, "timerfd = %d\n", tfd);
-
-               if (timerfd_settime(tfd, 0, &tmr, NULL)) {
-                       perror("timerfd_settime");
-                       return 1;
-               }
-
-               fprintf(stdout, "wating timer ...\n");
-               ticks = waittmr(tfd, -1);
-               ttmr = getustime(clks[i].id);
-               if (ticks <= 0)
-                       fprintf(stdout, "whooops! no timer showed up!\n");
-               else
-                       fprintf(stdout, "got timer ticks (%ld) after %llu ms\n",
-                               ticks, (ttmr - tnow) / 1000);
-
-               fprintf(stdout, "absolute timer test (at 500 ms) ...\n");
-               tnow = getustime(clks[i].id);
-               set_timespec(&tmr.it_value, tnow + 500 * 1000);
-               set_timespec(&tmr.it_interval, 0);
-               if (timerfd_settime(tfd, TFD_TIMER_ABSTIME, &tmr, NULL)) {
-                       perror("timerfd_settime");
-                       return 1;
-               }
-
-               fprintf(stdout, "wating timer ...\n");
-               ticks = waittmr(tfd, -1);
-               ttmr = getustime(clks[i].id);
-               if (ticks <= 0)
-                       fprintf(stdout, "whooops! no timer showed up!\n");
-               else
-                       fprintf(stdout, "got timer ticks (%ld) after %llu ms\n",
-                               ticks, (ttmr - tnow) / 1000);
-
-               fprintf(stdout, "sequential timer test (100 ms clock) ...\n");
-               tnow = getustime(clks[i].id);
-               set_timespec(&tmr.it_value, tnow + 100 * 1000);
-               set_timespec(&tmr.it_interval, 100 * 1000);
-               if (timerfd_settime(tfd, TFD_TIMER_ABSTIME, &tmr, NULL)) {
-                       perror("timerfd_settime");
-                       return 1;
-               }
-
-               fprintf(stdout, "sleeping 1 second ...\n");
-               sleep(1);
-               if (timerfd_gettime(tfd, &tmr)) {
-                       perror("timerfd_gettime");
-                       return 1;
-               }
-               fprintf(stdout, "timerfd_gettime returned:\n"
-                       "\tit_value = { %ld, %ld } it_interval = { %ld, %ld }\n",
-                       (long)tmr.it_value.tv_sec, (long)tmr.it_value.tv_nsec,
-                       (long)tmr.it_interval.tv_sec,
-                       (long)tmr.it_interval.tv_nsec);
-               fprintf(stdout, "sleeping 1 second ...\n");
-               sleep(1);
-
-               fprintf(stdout, "wating timer ...\n");
-               ticks = waittmr(tfd, -1);
-               ttmr = getustime(clks[i].id);
-               if (ticks <= 0)
-                       fprintf(stdout, "whooops! no timer showed up!\n");
-               else
-                       fprintf(stdout, "got timer ticks (%ld) after %llu ms\n",
-                               ticks, (ttmr - tnow) / 1000);
-
-               fprintf(stdout, "O_NONBLOCK test ...\n");
-               tnow = getustime(clks[i].id);
-               set_timespec(&tmr.it_value, 100 * 1000);
-               set_timespec(&tmr.it_interval, 0);
-               if (timerfd_settime(tfd, 0, &tmr, NULL)) {
-                       perror("timerfd_settime");
-                       return 1;
-               }
-               fprintf(stdout, "timerfd = %d\n", tfd);
-
-               fprintf(stdout, "wating timer (flush the single tick) ...\n");
-               ticks = waittmr(tfd, -1);
-               ttmr = getustime(clks[i].id);
-               if (ticks <= 0)
-                       fprintf(stdout, "whooops! no timer showed up!\n");
-               else
-                       fprintf(stdout, "got timer ticks (%ld) after %llu ms\n",
-                               ticks, (ttmr - tnow) / 1000);
-
-               fcntl(tfd, F_SETFL, fcntl(tfd, F_GETFL, 0) | O_NONBLOCK);
-
-               if (read(tfd, &uticks, sizeof(uticks)) > 0)
-                       fprintf(stdout,
-                               "whooops! timer ticks not zero when should have been\n");
-               else if (errno != EAGAIN)
-                       fprintf(stdout,
-                               "whooops! bad errno value (%d = '%s')!\n",
-                               errno, strerror(errno));
-               else
-                       fprintf(stdout, "success\n");
-
-               fcntl(tfd, F_SETFL, fcntl(tfd, F_GETFL, 0) & ~O_NONBLOCK);
-
-               close(tfd);
-       }
-
-       tst_exit();
-}
-
-#else
-int TST_TOTAL = 0;
-
-int main(void)
-{
-
-       tst_brkm(TCONF, NULL,
-                "This test needs a kernel that has timerfd syscall.");
-}
-#endif