]> sourceware.org Git - valgrind.git/commitdiff
FreeBSD: add wrapperd for timerfd_create timerfd_gettime and timerfd_settime for...
authorPaul Floyd <pjfloyd@wanadoo.fr>
Sat, 16 Sep 2023 14:06:12 +0000 (16:06 +0200)
committerPaul Floyd <pjfloyd@wanadoo.fr>
Sat, 16 Sep 2023 14:06:12 +0000 (16:06 +0200)
Mostly copied from the Linux implementation.
Add a testcase and a scalar for FreeBSD 15

13 files changed:
.gitignore
configure.ac
coregrind/m_syswrap/priv_syswrap-freebsd.h
coregrind/m_syswrap/syswrap-freebsd.c
include/vki/vki-scnums-freebsd.h
memcheck/tests/freebsd/Makefile.am
memcheck/tests/freebsd/scalar_15_plus.c [new file with mode: 0644]
memcheck/tests/freebsd/scalar_15_plus.stderr.exp [new file with mode: 0644]
memcheck/tests/freebsd/scalar_15_plus.vgtest [new file with mode: 0644]
memcheck/tests/freebsd/timerfd.c [new file with mode: 0644]
memcheck/tests/freebsd/timerfd.stderr.exp [new file with mode: 0644]
memcheck/tests/freebsd/timerfd.stdout.exp [new file with mode: 0644]
memcheck/tests/freebsd/timerfd.vgtest [new file with mode: 0644]

index 48730f21930d0c3a4bfaa65454c7dc11a8deb1fe..0a9f2d3f13ac32ed10db02e2565f4fa50d2e6a88 100644 (file)
 /memcheck/tests/freebsd/revoke
 /memcheck/tests/freebsd/scalar
 /memcheck/tests/freebsd/scalar_13_plus
+/memcheck/tests/freebsd/scalar_15_plus
 /memcheck/tests/freebsd/scalar_abort2
 /memcheck/tests/freebsd/scalar_fork
 /memcheck/tests/freebsd/scalar_pdfork
 /memcheck/tests/freebsd/stat
 /memcheck/tests/freebsd/statfs
 /memcheck/tests/freebsd/static_allocs
+/memcheck/tests/freebsd/timerfd
 /memcheck/tests/freebsd/utimens
 /memcheck/tests/freebsd/utimes
 
index d745497e80cb8d0c35f74c57064db3908f32444a..d1b82c05d28fb23f2ec3047eae66d03e20d1a58c 100755 (executable)
@@ -4778,17 +4778,19 @@ fi # test "$VGCONF_OS" = "solaris"
 #----------------------------------------------------------------------------
 
 # Rather than having a large number of feature test as above with Solaris
-# these tests are per-version. This may not be entirely relialable for
+# these tests are per-version. This may not be entirely reliable for
 # FreeBSD development branches (XX.Y-CURRENT) or pre-release branches
 # (XX.Y-STABLE) but it should work for XX-Y-RELEASE
 
 if test "$VGCONF_OS" = "freebsd" ; then
 
 AM_CONDITIONAL(FREEBSD_VERS_13_PLUS, test $freebsd_vers -ge $freebsd_13_0)
+AM_CONDITIONAL(FREEBSD_VERS_15_PLUS, test $freebsd_vers -ge $freebsd_15)
 
 else
 
 AM_CONDITIONAL(FREEBSD_VERS_13_PLUS, false)
+AM_CONDITIONAL(FREEBSD_VERS_15_PLUS, false)
 
 fi # test "$VGCONF_OS" = "freebsd"
 
index 844da82a458f43544db17011b2eac0924f31ed16..79e52b9fdfe50ac2a1a6ccd04c096f40a1593889 100644 (file)
@@ -556,11 +556,19 @@ DECL_TEMPLATE(freebsd, sys___specialfd) // 577
 
 #if (FREEBSD_VERS >= FREEBSD_13_1)
 
-// unimpl __NR_fspacectl   580
+// unimpl __NR_fspacectl           580
 // unimpl __NR_sched_getcpu        581
 DECL_TEMPLATE(freebsd, sys_swapoff) // 582
 #endif
 
+#if (FREEBSD_VERS >= FREEBSD_15)
+// unimpl __NR_kqueuex             583
+// unimpl __NR_membarrier          584
+DECL_TEMPLATE(freebsd, sys_timerfd_create); // 585
+DECL_TEMPLATE(freebsd, sys_timerfd_gettime); // 586
+DECL_TEMPLATE(freebsd, sys_timerfd_settime); // 587
+#endif
+
 DECL_TEMPLATE(freebsd, sys_fake_sigreturn)
 
 #endif   // PRIV_SYSWRAP_FREEBSD_H
index ae11d2a78cffb4051070e76683e8c1660fb154dc..ffe12ef7991799e8cdf21787eb4fb09a0acadaa7 100644 (file)
@@ -6776,6 +6776,86 @@ PRE(sys_swapoff)
 
 #endif
 
+#if (FREEBSD_VERS >= FREEBSD_15)
+
+// SYS_kqueuex 583 unimpl
+
+// SYS_membarrier 584 unimpl
+
+// SYS_timerfd_create 585
+// int timerfd_create(int clockid, int flags);
+PRE(sys_timerfd_create)
+{
+   PRINT("sys_timerfd_create (%ld, %ld )", SARG1, SARG2);
+   PRE_REG_READ2(int, "timerfd_create", int, clockid, int, flags);
+}
+
+POST(sys_timerfd_create)
+{
+   if (!ML_(fd_allowed)(RES, "timerfd_create", tid, True)) {
+      VG_(close)(RES);
+      SET_STATUS_Failure( VKI_EMFILE );
+   } else {
+      if (VG_(clo_track_fds))
+         ML_(record_fd_open_nameless) (tid, RES);
+   }
+}
+
+// SYS_timerfd_gettime 586
+// int timerfd_gettime(int fd, struct itimerspec *curr_value);
+PRE(sys_timerfd_gettime)
+{
+   PRINT("sys_timerfd_gettime ( %ld, %#" FMT_REGWORD "x )", SARG1, ARG2);
+   PRE_REG_READ2(int, "timerfd_gettime",
+                 int, fd,
+                 struct vki_itimerspec*, curr_value);
+   if (!ML_(fd_allowed)(ARG1, "timerfd_gettime", tid, False))
+      SET_STATUS_Failure(VKI_EBADF);
+   else
+      PRE_MEM_WRITE("timerfd_gettime(curr_value)",
+                    ARG2, sizeof(struct vki_itimerspec));
+}
+
+POST(sys_timerfd_gettime)
+{
+   if (RES == 0)
+      POST_MEM_WRITE(ARG2, sizeof(struct vki_itimerspec));
+}
+
+// SYS_timerfd_gettime 587
+// int timerfd_settime(int fd, int flags, const struct itimerspec *new_value,
+//                     struct itimerspec *old_value);
+PRE(sys_timerfd_settime)
+{
+   PRINT("sys_timerfd_settime(%" FMT_REGWORD "d, %" FMT_REGWORD "d, %#" FMT_REGWORD "x, %#"
+         FMT_REGWORD "x )", SARG1, SARG2, ARG3, ARG4);
+   PRE_REG_READ4(int, "timerfd_settime",
+                 int, fd,
+                 int, flags,
+                 const struct vki_itimerspec*, new_value,
+                 struct vki_itimerspec*, old_value);
+   if (!ML_(fd_allowed)(ARG1, "timerfd_settime", tid, False))
+      SET_STATUS_Failure(VKI_EBADF);
+   else
+   {
+      PRE_MEM_READ("timerfd_settime(new_value)",
+                   ARG3, sizeof(struct vki_itimerspec));
+      if (ARG4)
+      {
+         PRE_MEM_WRITE("timerfd_settime(old_value)",
+                       ARG4, sizeof(struct vki_itimerspec));
+      }
+   }
+}
+
+POST(sys_timerfd_settime)
+{
+   if (RES == 0 && ARG4 != 0) {
+      POST_MEM_WRITE(ARG4, sizeof(struct vki_itimerspec));
+   }
+}
+#endif
+
 #undef PRE
 #undef POST
 
@@ -7494,6 +7574,15 @@ const SyscallTableEntry ML_(syscall_table)[] = {
    BSDX_(__NR_swapoff,          sys_swapoff),           // 582
 #endif
 
+#if (FREEBSD_VERS >= FREEBSD_15)
+   // unimpl __NR_kqueuex             583
+   // unimpl __NR_kqueuex             584
+   BSDXY(__NR_timerfd_create,   sys_timerfd_create),    // 585
+   BSDXY(__NR_timerfd_settime,  sys_timerfd_settime),   // 586
+   BSDXY(__NR_timerfd_gettime,  sys_timerfd_gettime),   // 587
+#endif
+
+
    BSDX_(__NR_fake_sigreturn,   sys_fake_sigreturn),    // 1000, fake sigreturn
 
 };
index 12ce610007874e0645efe310700ca1df0386e035..9eb73591fa0f3fb37adbc91a7cc0a5138e0306c7 100644 (file)
 
 #endif
 
+#if (FREEBSD_VERS >= FREEBSD_15)
+
+#define __NR_kqueuex             583
+#define __NR_membarrier          584
+#define __NR_timerfd_create      585
+#define __NR_timerfd_gettime     586
+#define __NR_timerfd_settime     587
+
+#endif
+
 #define __NR_fake_sigreturn      1000
 
 #endif /* VKI_UNISTD_FREEBSD_H */
index ef6cedc03c1937093f153ac66a3c309b1ca0fe7e..f5b8386c67306c4ac9f6a0efb28408a601696222 100644 (file)
@@ -20,18 +20,33 @@ EXTRA_DIST = \
        chmod_chown.vgtest \
        chmod_chown.stderr.exp \
        close_range.vgtest close_range.stderr.exp \
+       errno_aligned_allocs.vgtest \
+       errno_aligned_allocs.stderr.exp \
        eventfd1.vgtest \
        eventfd1.stderr.exp eventfd1.stdout.exp \
        eventfd2.vgtest \
        eventfd2.stderr.exp \
        extattr.vgtest \
        extattr.stderr.exp \
+       fexecve.vgtest \
+       fexecve.stderr.exp \
+       file_locking_wait6.vgtest \
+       file_locking_wait6.stderr.exp \
+       get_set_context.vgtest \
+       get_set_context.stderr.exp \
+       get_set_context.stderr.exp-x86 \
        get_set_login.vgtest \
        get_set_login.stderr.exp \
+       getfh.vgtest \
+       getfh.stderr.exp \
        getfsstat.vgtest \
        getfsstat.stderr.exp \
        getfsstat.supp \
                getfsstat.stderr.exp-x86 \
+       linkat.vgtest \
+       linkat.stderr.exp \
+       misc.vgtest \
+       misc.stderr.exp \
        pdfork_pdkill.vgtest \
        pdfork_pdkill.stderr.exp \
        revoke.vgtest \
@@ -58,35 +73,25 @@ EXTRA_DIST = \
        supponlyobj.vgtest \
        supponlyobj.stderr.exp \
        supponlyobj.supp \
-       getfh.vgtest \
-       getfh.stderr.exp \
-       linkat.vgtest \
-       linkat.stderr.exp \
        stat.vgtest \
        stat.stderr.exp \
                stat.stderr.exp-x86 \
-       file_locking_wait6.vgtest \
-       file_locking_wait6.stderr.exp \
+       timerfd.vgtest \
+       timerfd.stderr.exp \
+       timerfd.stdout.exp \
        utimens.vgtest \
        utimens.stderr.exp \
-       misc.vgtest \
-       misc.stderr.exp \
-       get_set_context.vgtest \
-       get_set_context.stderr.exp \
-       get_set_context.stderr.exp-x86 \
        utimes.vgtest \
        utimes.stderr.exp-x86 \
        utimes.stderr.exp \
        static_allocs.vgtest \
        static_allocs.stderr.exp \
-       fexecve.vgtest \
-       fexecve.stderr.exp \
        realpathat.vgtest \
        realpathat.stderr.exp \
        scalar_13_plus.vgtest \
        scalar_13_plus.stderr.exp \
-       errno_aligned_allocs.vgtest \
-       errno_aligned_allocs.stderr.exp \
+       scalar_15_plus.vgtest \
+       scalar_15_plus.stderr.exp \
        setproctitle.vgtest \
        setproctitle.stderr.exp \
        setproctitle.stdout.exp \
@@ -140,10 +145,15 @@ bug470713_SOURCES = bug470713.cpp
 
 if FREEBSD_VERS_13_PLUS
 check_PROGRAMS += realpathat scalar_13_plus eventfd1 eventfd2
-
 scalar_13_plus_CFLAGS = ${AM_CFLAGS} -g
 endif
 
+if FREEBSD_VERS_15_PLUS
+check_PROGRAMS += scalar_15_plus timerfd
+scalar_15_plus_CFLAGS = ${AM_CFLAGS} -g
+timerfd_LDFLAGS = -lm
+endif
+
 if HAVE_CLOSE_RANGE
 check_PROGRAMS += close_range
 endif
diff --git a/memcheck/tests/freebsd/scalar_15_plus.c b/memcheck/tests/freebsd/scalar_15_plus.c
new file mode 100644 (file)
index 0000000..cd40a20
--- /dev/null
@@ -0,0 +1,29 @@
+#include "scalar.h"
+#include <sys/mman.h>
+
+int main(void)
+{
+   long *px = malloc(2*sizeof(long));
+   x0 = px[0];
+
+   /* SYS_kqueuex                        583 */
+   /* unimpl */
+
+   /* SYS_membarrier                     584 */
+   /* unimpl */
+
+   /* SYS_timerfd_create                 585 */
+   GO(SYS_timerfd_create, " 2s 0m");
+   SY(SYS_timerfd_create, x0+123, x0+23456); FAIL;
+
+   /* SYS_timerfd_gettime                586 */
+   GO(SYS_timerfd_gettime, " 2s 1m");
+   SY(SYS_timerfd_gettime, x0+100, x0); FAIL;
+
+   /* SYS_timerfd_settime                587 */
+   GO(SYS_timerfd_settime, "3s 2m");
+   SY(SYS_timerfd_settime, x0+321, x0, x0+10); FAIL;
+   
+   return(0);
+}
+
diff --git a/memcheck/tests/freebsd/scalar_15_plus.stderr.exp b/memcheck/tests/freebsd/scalar_15_plus.stderr.exp
new file mode 100644 (file)
index 0000000..6c2ef07
--- /dev/null
@@ -0,0 +1,43 @@
+---------------------------------------------------------
+585:      SYS_timerfd_create  2s 0m
+---------------------------------------------------------
+Syscall param timerfd_create(clockid) contains uninitialised byte(s)
+   ...
+
+Syscall param timerfd_create(flags) contains uninitialised byte(s)
+   ...
+
+---------------------------------------------------------
+586:     SYS_timerfd_gettime  2s 1m
+---------------------------------------------------------
+Syscall param timerfd_gettime(fd) contains uninitialised byte(s)
+   ...
+
+Syscall param timerfd_gettime(curr_value) contains uninitialised byte(s)
+   ...
+
+Syscall param timerfd_gettime(curr_value) points to unaddressable byte(s)
+   ...
+ Address 0x........ is not stack'd, malloc'd or (recently) free'd
+
+---------------------------------------------------------
+587:     SYS_timerfd_settime 3s 2m
+---------------------------------------------------------
+Syscall param timerfd_settime(fd) contains uninitialised byte(s)
+   ...
+
+Syscall param timerfd_settime(flags) contains uninitialised byte(s)
+   ...
+
+Syscall param timerfd_settime(new_value) contains uninitialised byte(s)
+   ...
+
+Syscall param timerfd_settime(new_value) points to unaddressable byte(s)
+   ...
+ Address 0x........ is not stack'd, malloc'd or (recently) free'd
+
+Syscall param timerfd_settime(old_value) points to unaddressable byte(s)
+   ...
+ Address 0x........ is on thread 1's stack
+ .... bytes below stack pointer
+
diff --git a/memcheck/tests/freebsd/scalar_15_plus.vgtest b/memcheck/tests/freebsd/scalar_15_plus.vgtest
new file mode 100644 (file)
index 0000000..fe40176
--- /dev/null
@@ -0,0 +1,12 @@
+prereq: test -e ./scalar_15_plus
+prog: scalar_15_plus
+vgopts: -q --error-limit=no
+stderr_filter: filter_scalar
+# Remove all frames from the stack trace except the first one.
+# This is important because syscall() function on x86 isn't ABI conformant
+# which confuses the Valgrind stack unwinder.
+# Therefore x86 and amd64 stack traces are unified so that they contain only
+# 'syscall (in libc)' stack frame and this is then filtered out completely.
+stderr_filter_args: libc
+args: < scalar_13_plus.c
+
diff --git a/memcheck/tests/freebsd/timerfd.c b/memcheck/tests/freebsd/timerfd.c
new file mode 100644 (file)
index 0000000..7ed964c
--- /dev/null
@@ -0,0 +1,150 @@
+/* Copied from the Linux manpage
+ * with the printed times rounded to
+ * seconds for reproducibility.
+ * And some errors added.
+ */
+
+#include <err.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/timerfd.h>
+#include <time.h>
+#include <unistd.h>
+#include <math.h>
+#include <errno.h>
+#include <assert.h>
+#include "../../memcheck.h"
+
+static void
+print_elapsed_time(void)
+{
+    int                     secs, nsecs;
+    static int              first_call = 1;
+    struct timespec         curr;
+    static struct timespec  start;
+    int                  round_secs;
+
+    if (first_call) {
+        first_call = 0;
+        if (clock_gettime(CLOCK_MONOTONIC, &start) == -1)
+            err(EXIT_FAILURE, "clock_gettime");
+    }
+
+    if (clock_gettime(CLOCK_MONOTONIC, &curr) == -1)
+        err(EXIT_FAILURE, "clock_gettime");
+
+    secs = curr.tv_sec - start.tv_sec;
+    nsecs = curr.tv_nsec - start.tv_nsec;
+    if (nsecs < 0) {
+        secs--;
+        nsecs += 1000000000;
+    }
+    round_secs = round((secs*1e9 + nsecs)/1e9);
+    printf("%d: ", round_secs);
+}
+
+int
+main(int argc, char *argv[])
+{
+    int                fd;
+    ssize_t            s;
+    uint64_t           exp, tot_exp, max_exp;
+    struct timespec    now;
+    struct itimerspec  new_value;
+
+    if (argc != 2 && argc != 4) {
+        fprintf(stderr, "%s init-secs [interval-secs max-exp]\n",
+                argv[0]);
+        exit(EXIT_FAILURE);
+    }
+
+    if (clock_gettime(CLOCK_REALTIME, &now) == -1)
+        err(EXIT_FAILURE, "clock_gettime");
+
+    /* Create a CLOCK_REALTIME absolute timer with initial
+       expiration and interval as specified in command line. */
+
+    new_value.it_value.tv_sec = now.tv_sec + atoi(argv[1]);
+    new_value.it_value.tv_nsec = now.tv_nsec;
+    if (argc == 2) {
+        new_value.it_interval.tv_sec = 0;
+        max_exp = 1;
+    } else {
+        new_value.it_interval.tv_sec = atoi(argv[2]);
+        max_exp = atoi(argv[3]);
+    }
+    new_value.it_interval.tv_nsec = 0;
+
+    fd = timerfd_create(CLOCK_REALTIME, 0);
+    if (fd == -1)
+        err(EXIT_FAILURE, "timerfd_create");
+
+    if (timerfd_settime(fd, TFD_TIMER_ABSTIME, &new_value, NULL) == -1)
+        err(EXIT_FAILURE, "timerfd_settime");
+
+    print_elapsed_time();
+    printf("timer started\n");
+
+    for (tot_exp = 0; tot_exp < max_exp;) {
+        s = read(fd, &exp, sizeof(uint64_t));
+        if (s != sizeof(uint64_t))
+            err(EXIT_FAILURE, "read");
+
+        tot_exp += exp;
+        print_elapsed_time();
+        printf("read: %" PRIu64 "; total=%" PRIu64 "\n", exp, tot_exp);
+    }
+
+    close(fd);
+
+    {
+        int a = CLOCK_REALTIME;
+        int b = TFD_CLOEXEC;
+        int c = TFD_TIMER_ABSTIME;
+        VALGRIND_MAKE_MEM_UNDEFINED(&a, sizeof(a));
+        VALGRIND_MAKE_MEM_UNDEFINED(&b, sizeof(b));
+        VALGRIND_MAKE_MEM_UNDEFINED(&c, sizeof(c));
+        struct itimerspec * get_ts = malloc(sizeof(*get_ts) - 2);
+        struct itimerspec * set_ts = malloc(sizeof(*set_ts) - 2);
+        struct itimerspec ts;
+        int retval;
+
+        errno = 0;
+        /* uninit clockid and flag but should work */
+        int fd2 = timerfd_create(a, b);
+        assert(fd2 != -1);
+        assert(errno == 0); 
+        /* bad flag should fail */
+        timerfd_create(CLOCK_REALTIME, 1000000);
+        /* bad clockid should fail */
+        timerfd_create(1000000, TFD_CLOEXEC);
+
+        /* memory too small for requested get */
+        timerfd_gettime(fd2, get_ts);
+        /* should succeed */
+        timerfd_gettime(fd2, &ts);
+        ts.it_interval.tv_nsec += 100000;
+
+        /* uninit flag */
+        timerfd_settime(fd2, c, &ts, NULL);
+        errno = 0;
+        ts.it_interval.tv_nsec += 100000;
+        /* memory too small for requested old value */
+        retval = timerfd_settime(fd2, TFD_TIMER_ABSTIME, &ts, set_ts);
+        assert(retval == 0);
+        assert(errno == 0);
+
+        VALGRIND_MAKE_MEM_UNDEFINED(&fd2, sizeof(fd2));
+        timerfd_gettime(fd2, &ts);
+        ts.it_interval.tv_nsec += 100000;
+        timerfd_settime(fd2, TFD_TIMER_ABSTIME, &ts, NULL);
+
+
+        free(get_ts); 
+        free(set_ts); 
+    }
+
+    exit(EXIT_SUCCESS);
+}
+
diff --git a/memcheck/tests/freebsd/timerfd.stderr.exp b/memcheck/tests/freebsd/timerfd.stderr.exp
new file mode 100644 (file)
index 0000000..4831ec8
--- /dev/null
@@ -0,0 +1,40 @@
+Syscall param timerfd_create(clockid) contains uninitialised byte(s)
+   at 0x........: timerfd_create (in /...libc...)
+   by 0x........: main (timerfd.c:115)
+
+Syscall param timerfd_create(flags) contains uninitialised byte(s)
+   at 0x........: timerfd_create (in /...libc...)
+   by 0x........: main (timerfd.c:115)
+
+Syscall param timerfd_gettime(curr_value) points to unaddressable byte(s)
+   at 0x........: timerfd_gettime (in /...libc...)
+   by 0x........: main (timerfd.c:124)
+ Address 0x........ is 0 bytes after a block of size 30 alloc'd
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (timerfd.c:108)
+
+Syscall param timerfd_settime(flags) contains uninitialised byte(s)
+   at 0x........: timerfd_settime (in /...libc...)
+   by 0x........: main (timerfd.c:130)
+
+Syscall param timerfd_settime(old_value) points to unaddressable byte(s)
+   at 0x........: timerfd_settime (in /...libc...)
+   by 0x........: main (timerfd.c:134)
+ Address 0x........ is 0 bytes after a block of size 30 alloc'd
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (timerfd.c:109)
+
+Syscall param timerfd_gettime(fd) contains uninitialised byte(s)
+   at 0x........: timerfd_gettime (in /...libc...)
+   by 0x........: main (timerfd.c:139)
+
+Syscall param timerfd_settime(fd) contains uninitialised byte(s)
+   at 0x........: timerfd_settime (in /...libc...)
+   by 0x........: main (timerfd.c:141)
+
+FILE DESCRIPTORS: 4 open (3 std) at exit.
+Open file descriptor 3:
+   at 0x........: timerfd_create (in /...libc...)
+   by 0x........: main (timerfd.c:115)
+
+
diff --git a/memcheck/tests/freebsd/timerfd.stdout.exp b/memcheck/tests/freebsd/timerfd.stdout.exp
new file mode 100644 (file)
index 0000000..30ee11e
--- /dev/null
@@ -0,0 +1,4 @@
+0: timer started
+1: read: 1; total=1
+2: read: 1; total=2
+3: read: 1; total=3
diff --git a/memcheck/tests/freebsd/timerfd.vgtest b/memcheck/tests/freebsd/timerfd.vgtest
new file mode 100644 (file)
index 0000000..b71f7b7
--- /dev/null
@@ -0,0 +1,4 @@
+prereq: test -e ./timerfd
+prog: timerfd
+args: 1 1 3
+vgopts: -q --track-fds=yes
This page took 0.053049 seconds and 5 git commands to generate.