Index: head/tests/sys/kqueue/libkqueue/main.c =================================================================== --- head/tests/sys/kqueue/libkqueue/main.c (revision 341067) +++ head/tests/sys/kqueue/libkqueue/main.c (revision 341068) @@ -1,379 +1,379 @@ /* * Copyright (c) 2009 Mark Heily * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * * $FreeBSD$ */ #include #include "config.h" #include "common.h" int testnum = 1; char *cur_test_id = NULL; int kqfd; extern void test_evfilt_read(); extern void test_evfilt_signal(); extern void test_evfilt_vnode(); extern void test_evfilt_timer(); extern void test_evfilt_proc(); #if HAVE_EVFILT_USER extern void test_evfilt_user(); #endif /* Checks if any events are pending, which is an error. */ void test_no_kevents(void) { int nfds; struct timespec timeo; struct kevent kev; char *kev_str; puts("confirming that there are no events pending"); memset(&timeo, 0, sizeof(timeo)); nfds = kevent(kqfd, NULL, 0, &kev, 1, &timeo); if (nfds != 0) { puts("\nUnexpected event:"); kev_str = kevent_to_str(&kev); puts(kev_str); free(kev_str); errx(1, "%d event(s) pending, but none expected:", nfds); } } /* Checks if any events are pending, which is an error. Do not print * out anything unless events are found. */ void test_no_kevents_quietly(void) { int nfds; struct timespec timeo; struct kevent kev; char *kev_str; memset(&timeo, 0, sizeof(timeo)); nfds = kevent(kqfd, NULL, 0, &kev, 1, &timeo); if (nfds != 0) { puts("\nUnexpected event:"); kev_str = kevent_to_str(&kev); puts(kev_str); free(kev_str); errx(1, "%d event(s) pending, but none expected:", nfds); } } /* Retrieve a single kevent */ struct kevent * kevent_get(int kqfd) { int nfds; struct kevent *kev; if ((kev = calloc(1, sizeof(*kev))) == NULL) - err(1, "out of memory"); + err(1, "out of memory"); nfds = kevent(kqfd, NULL, 0, kev, 1, NULL); if (nfds < 1) err(1, "kevent(2)"); return (kev); } /* Retrieve a single kevent, specifying a maximum time to wait for it. */ struct kevent * kevent_get_timeout(int kqfd, int seconds) { int nfds; struct kevent *kev; struct timespec timeout = {seconds, 0}; if ((kev = calloc(1, sizeof(*kev))) == NULL) - err(1, "out of memory"); + err(1, "out of memory"); nfds = kevent(kqfd, NULL, 0, kev, 1, &timeout); if (nfds < 0) { err(1, "kevent(2)"); } else if (nfds == 0) { free(kev); kev = NULL; } return (kev); } char * kevent_fflags_dump(struct kevent *kev) { char *buf; #define KEVFFL_DUMP(attrib) \ if (kev->fflags & attrib) \ - strncat(buf, #attrib" ", 64); + strncat(buf, #attrib" ", 64); if ((buf = calloc(1, 1024)) == NULL) - abort(); + abort(); /* Not every filter has meaningful fflags */ if (kev->filter == EVFILT_PROC) { snprintf(buf, 1024, "fflags = %x (", kev->fflags); KEVFFL_DUMP(NOTE_EXIT); KEVFFL_DUMP(NOTE_FORK); KEVFFL_DUMP(NOTE_EXEC); KEVFFL_DUMP(NOTE_CHILD); KEVFFL_DUMP(NOTE_TRACKERR); KEVFFL_DUMP(NOTE_TRACK); buf[strlen(buf) - 1] = ')'; } else if (kev->filter == EVFILT_PROCDESC) { snprintf(buf, 1024, "fflags = %x (", kev->fflags); KEVFFL_DUMP(NOTE_EXIT); KEVFFL_DUMP(NOTE_FORK); KEVFFL_DUMP(NOTE_EXEC); buf[strlen(buf) - 1] = ')'; } else if (kev->filter == EVFILT_VNODE) { snprintf(buf, 1024, "fflags = %x (", kev->fflags); KEVFFL_DUMP(NOTE_DELETE); KEVFFL_DUMP(NOTE_WRITE); KEVFFL_DUMP(NOTE_EXTEND); #if HAVE_NOTE_TRUNCATE KEVFFL_DUMP(NOTE_TRUNCATE); #endif KEVFFL_DUMP(NOTE_ATTRIB); KEVFFL_DUMP(NOTE_LINK); KEVFFL_DUMP(NOTE_RENAME); #if HAVE_NOTE_REVOKE KEVFFL_DUMP(NOTE_REVOKE); #endif buf[strlen(buf) - 1] = ')'; } else { - snprintf(buf, 1024, "fflags = %x", kev->fflags); + snprintf(buf, 1024, "fflags = %x", kev->fflags); } return (buf); } char * kevent_flags_dump(struct kevent *kev) { char *buf; #define KEVFL_DUMP(attrib) \ if (kev->flags & attrib) \ - strncat(buf, #attrib" ", 64); + strncat(buf, #attrib" ", 64); if ((buf = calloc(1, 1024)) == NULL) - abort(); + abort(); snprintf(buf, 1024, "flags = %d (", kev->flags); KEVFL_DUMP(EV_ADD); KEVFL_DUMP(EV_ENABLE); KEVFL_DUMP(EV_DISABLE); KEVFL_DUMP(EV_DELETE); KEVFL_DUMP(EV_ONESHOT); KEVFL_DUMP(EV_CLEAR); KEVFL_DUMP(EV_EOF); KEVFL_DUMP(EV_ERROR); #if HAVE_EV_DISPATCH KEVFL_DUMP(EV_DISPATCH); #endif #if HAVE_EV_RECEIPT KEVFL_DUMP(EV_RECEIPT); #endif buf[strlen(buf) - 1] = ')'; return (buf); } /* Copied from ../kevent.c kevent_dump() and improved */ char * kevent_to_str(struct kevent *kev) { char buf[512]; char *flags_str = kevent_flags_dump(kev); char *fflags_str = kevent_fflags_dump(kev); snprintf(&buf[0], sizeof(buf), "[ident=%ju, filter=%d, %s, %s, data=%jd, udata=%p, " - "ext=[%jx %jx %jx %jx]", + "ext=[%jx %jx %jx %jx]", (uintmax_t) kev->ident, kev->filter, flags_str, fflags_str, (uintmax_t)kev->data, kev->udata, - (uintmax_t)kev->ext[0], - (uintmax_t)kev->ext[1], - (uintmax_t)kev->ext[2], - (uintmax_t)kev->ext[3]); + (uintmax_t)kev->ext[0], + (uintmax_t)kev->ext[1], + (uintmax_t)kev->ext[2], + (uintmax_t)kev->ext[3]); free(flags_str); free(fflags_str); return (strdup(buf)); } void kevent_add(int kqfd, struct kevent *kev, uintptr_t ident, short filter, u_short flags, u_int fflags, intptr_t data, void *udata) { char *kev_str; EV_SET(kev, ident, filter, flags, fflags, data, NULL); if (kevent(kqfd, kev, 1, NULL, 0, NULL) < 0) { - kev_str = kevent_to_str(kev); - printf("Unable to add the following kevent:\n%s\n", - kev_str); - free(kev_str); + kev_str = kevent_to_str(kev); + printf("Unable to add the following kevent:\n%s\n", + kev_str); + free(kev_str); err(1, "kevent(): %s", strerror(errno)); } } void kevent_cmp(struct kevent *k1, struct kevent *k2) { char *kev1_str; char *kev2_str; /* XXX- Workaround for inconsistent implementation of kevent(2) */ #ifdef __FreeBSD__ if (k1->flags & EV_ADD) k2->flags |= EV_ADD; #endif if (k1->ident != k2->ident || k1->filter != k2->filter || k1->flags != k2->flags || k1->fflags != k2->fflags || k1->data != k2->data || k1->udata != k2->udata || k1->ext[0] != k2->ext[0] || k1->ext[1] != k2->ext[1] || k1->ext[0] != k2->ext[2] || k1->ext[0] != k2->ext[3]) { - kev1_str = kevent_to_str(k1); - kev2_str = kevent_to_str(k2); - printf("kevent_cmp: mismatch:\n %s !=\n %s\n", - kev1_str, kev2_str); - free(kev1_str); - free(kev2_str); + kev1_str = kevent_to_str(k1); + kev2_str = kevent_to_str(k2); + printf("kevent_cmp: mismatch:\n %s !=\n %s\n", + kev1_str, kev2_str); + free(kev1_str); + free(kev2_str); abort(); } } void test_begin(const char *func) { if (cur_test_id) free(cur_test_id); cur_test_id = strdup(func); if (!cur_test_id) err(1, "strdup failed"); printf("\n\nTest %d: %s\n", testnum++, func); } void success(void) { printf("%-70s %s\n", cur_test_id, "passed"); free(cur_test_id); cur_test_id = NULL; } void test_kqueue(void) { test_begin("kqueue()"); if ((kqfd = kqueue()) < 0) err(1, "kqueue()"); test_no_kevents(); success(); } void test_kqueue_close(void) { test_begin("close(kq)"); if (close(kqfd) < 0) err(1, "close()"); success(); } int main(int argc, char **argv) { int test_proc = 1; int test_socket = 1; int test_signal = 1; int test_vnode = 1; int test_timer = 1; #ifdef __FreeBSD__ int test_user = 1; #else /* XXX-FIXME temporary */ int test_user = 0; #endif while (argc) { if (strcmp(argv[0], "--no-proc") == 0) test_proc = 0; if (strcmp(argv[0], "--no-socket") == 0) test_socket = 0; if (strcmp(argv[0], "--no-timer") == 0) test_timer = 0; if (strcmp(argv[0], "--no-signal") == 0) test_signal = 0; if (strcmp(argv[0], "--no-vnode") == 0) test_vnode = 0; if (strcmp(argv[0], "--no-user") == 0) test_user = 0; argv++; argc--; } /* * Some tests fork. If output is fully buffered, * the children inherit some buffered data and flush * it when they exit, causing some data to be printed twice. * Use line buffering to avoid this problem. */ setlinebuf(stdout); setlinebuf(stderr); test_kqueue(); test_kqueue_close(); if (test_socket) test_evfilt_read(); if (test_signal) test_evfilt_signal(); if (test_vnode) test_evfilt_vnode(); #if HAVE_EVFILT_USER if (test_user) test_evfilt_user(); #endif if (test_timer) test_evfilt_timer(); if (test_proc) test_evfilt_proc(); printf("\n---\n" "+OK All %d tests completed.\n", testnum - 1); return (0); } Index: head/tests/sys/kqueue/libkqueue/proc.c =================================================================== --- head/tests/sys/kqueue/libkqueue/proc.c (revision 341067) +++ head/tests/sys/kqueue/libkqueue/proc.c (revision 341068) @@ -1,426 +1,426 @@ /* * Copyright (c) 2009 Mark Heily * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * * $FreeBSD$ */ #include #include #include "config.h" #include "common.h" static int sigusr1_caught = 0; int kqfd; static void sig_handler(int signum) { sigusr1_caught = 1; } static void add_and_delete(void) { struct kevent kev; pid_t pid; /* Create a child that waits to be killed and then exits */ pid = fork(); if (pid == 0) { struct stat s; if (fstat(kqfd, &s) != -1) errx(1, "kqueue inherited across fork! (%s() at %s:%d)", - __func__, __FILE__, __LINE__); + __func__, __FILE__, __LINE__); pause(); exit(2); } printf(" -- child created (pid %d)\n", (int) pid); test_begin("kevent(EVFILT_PROC, EV_ADD)"); test_no_kevents(); kevent_add(kqfd, &kev, pid, EVFILT_PROC, EV_ADD, 0, 0, NULL); test_no_kevents(); success(); test_begin("kevent(EVFILT_PROC, EV_DELETE)"); sleep(1); test_no_kevents(); kevent_add(kqfd, &kev, pid, EVFILT_PROC, EV_DELETE, 0, 0, NULL); if (kill(pid, SIGKILL) < 0) err(1, "kill"); sleep(1); test_no_kevents(); success(); } static void proc_track(int sleep_time) { char test_id[64]; struct kevent kev; pid_t pid; int pipe_fd[2]; ssize_t result; snprintf(test_id, sizeof(test_id), "kevent(EVFILT_PROC, NOTE_TRACK); sleep %d", sleep_time); test_begin(test_id); test_no_kevents(); if (pipe(pipe_fd)) { err(1, "pipe (parent) failed! (%s() at %s:%d)", __func__, __FILE__, __LINE__); } /* Create a child to track. */ pid = fork(); if (pid == 0) { /* Child */ pid_t grandchild = -1; /* * Give the parent a chance to start tracking us. */ result = read(pipe_fd[1], test_id, 1); if (result != 1) { err(1, "read from pipe in child failed! (ret %zd) (%s() at %s:%d)", result, __func__, __FILE__, __LINE__); } /* * Spawn a grandchild that will immediately exit. If the kernel has bug * 180385, the parent will see a kevent with both NOTE_CHILD and * NOTE_EXIT. If that bug is fixed, it will see two separate kevents * for those notes. Note that this triggers the conditions for * detecting the bug quite reliably on a 1 CPU system (or if the test * process is restricted to a single CPU), but may not trigger it on a * multi-CPU system. */ grandchild = fork(); if (grandchild == 0) { /* Grandchild */ if (sleep_time) sleep(sleep_time); exit(1); } else if (grandchild == -1) { /* Error */ err(1, "fork (grandchild) failed! (%s() at %s:%d)", __func__, __FILE__, __LINE__); } else { /* Child (Grandchild Parent) */ printf(" -- grandchild created (pid %d)\n", (int) grandchild); } if (sleep_time) sleep(sleep_time); exit(0); } else if (pid == -1) { /* Error */ err(1, "fork (child) failed! (%s() at %s:%d)", __func__, __FILE__, __LINE__); } printf(" -- child created (pid %d)\n", (int) pid); kevent_add(kqfd, &kev, pid, EVFILT_PROC, EV_ADD | EV_ENABLE, NOTE_TRACK | NOTE_EXEC | NOTE_EXIT | NOTE_FORK, 0, NULL); printf(" -- tracking child (pid %d)\n", (int) pid); /* Now that we're tracking the child, tell it to proceed. */ result = write(pipe_fd[0], test_id, 1); if (result != 1) { err(1, "write to pipe in parent failed! (ret %zd) (%s() at %s:%d)", result, __func__, __FILE__, __LINE__); } /* * Several events should be received: * - NOTE_FORK (from child) * - NOTE_CHILD (from grandchild) * - NOTE_EXIT (from grandchild) * - NOTE_EXIT (from child) * * The NOTE_FORK and NOTE_EXIT from the child could be combined into a * single event, but the NOTE_CHILD and NOTE_EXIT from the grandchild must * not be combined. * * The loop continues until no events are received within a 5 second * period, at which point it is assumed that no more will be coming. The * loop is deliberately designed to attempt to get events even after all * the expected ones are received in case some spurious events are * generated as well as the expected ones. */ { int child_exit = 0; int child_fork = 0; int gchild_exit = 0; int gchild_note = 0; pid_t gchild_pid = -1; int done = 0; char *kev_str; while (!done) { int handled = 0; struct kevent *kevp; kevp = kevent_get_timeout(kqfd, 5); if (kevp == NULL) { done = 1; } else { kev_str = kevent_to_str(kevp); printf(" -- Received kevent: %s\n", kev_str); free(kev_str); if ((kevp->fflags & NOTE_CHILD) && (kevp->fflags & NOTE_EXIT)) { errx(1, "NOTE_CHILD and NOTE_EXIT in same kevent: %s", kevent_to_str(kevp)); } if (kevp->fflags & NOTE_CHILD) { if (kevp->data == pid) { if (!gchild_note) { ++gchild_note; gchild_pid = kevp->ident; ++handled; } else { errx(1, "Spurious NOTE_CHILD: %s", kevent_to_str(kevp)); } } } if (kevp->fflags & NOTE_EXIT) { if ((kevp->ident == pid) && (!child_exit)) { ++child_exit; ++handled; } else if ((kevp->ident == gchild_pid) && (!gchild_exit)) { ++gchild_exit; ++handled; } else { errx(1, "Spurious NOTE_EXIT: %s", kevent_to_str(kevp)); } } if (kevp->fflags & NOTE_FORK) { if ((kevp->ident == pid) && (!child_fork)) { ++child_fork; ++handled; } else { errx(1, "Spurious NOTE_FORK: %s", kevent_to_str(kevp)); } } if (!handled) { errx(1, "Spurious kevent: %s", kevent_to_str(kevp)); } free(kevp); } } /* Make sure all expected events were received. */ if (child_exit && child_fork && gchild_exit && gchild_note) { printf(" -- Received all expected events.\n"); } else { errx(1, "Did not receive all expected events."); } } success(); } #ifdef TODO static void event_trigger(void) { struct kevent kev; pid_t pid; test_begin("kevent(EVFILT_PROC, wait)"); /* Create a child that waits to be killed and then exits */ pid = fork(); if (pid == 0) { pause(); printf(" -- child caught signal, exiting\n"); exit(2); } printf(" -- child created (pid %d)\n", (int) pid); test_no_kevents(); kevent_add(kqfd, &kev, pid, EVFILT_PROC, EV_ADD, 0, 0, NULL); /* Cause the child to exit, then retrieve the event */ printf(" -- killing process %d\n", (int) pid); if (kill(pid, SIGUSR1) < 0) err(1, "kill"); kevent_cmp(&kev, kevent_get(kqfd)); test_no_kevents(); success(); } void test_kevent_signal_disable(void) { const char *test_id = "kevent(EVFILT_SIGNAL, EV_DISABLE)"; struct kevent kev; test_begin(test_id); EV_SET(&kev, SIGUSR1, EVFILT_SIGNAL, EV_DISABLE, 0, 0, NULL); if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) err(1, "%s", test_id); /* Block SIGUSR1, then send it to ourselves */ sigset_t mask; sigemptyset(&mask); sigaddset(&mask, SIGUSR1); if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1) err(1, "sigprocmask"); if (kill(getpid(), SIGKILL) < 0) err(1, "kill"); test_no_kevents(); success(); } void test_kevent_signal_enable(void) { const char *test_id = "kevent(EVFILT_SIGNAL, EV_ENABLE)"; struct kevent kev; test_begin(test_id); EV_SET(&kev, SIGUSR1, EVFILT_SIGNAL, EV_ENABLE, 0, 0, NULL); if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) err(1, "%s", test_id); /* Block SIGUSR1, then send it to ourselves */ sigset_t mask; sigemptyset(&mask); sigaddset(&mask, SIGUSR1); if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1) err(1, "sigprocmask"); if (kill(getpid(), SIGUSR1) < 0) err(1, "kill"); kev.flags = EV_ADD | EV_CLEAR; #if LIBKQUEUE kev.data = 1; /* WORKAROUND */ #else kev.data = 2; // one extra time from test_kevent_signal_disable() #endif kevent_cmp(&kev, kevent_get(kqfd)); /* Delete the watch */ kev.flags = EV_DELETE; if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) err(1, "%s", test_id); success(); } void test_kevent_signal_del(void) { const char *test_id = "kevent(EVFILT_SIGNAL, EV_DELETE)"; struct kevent kev; test_begin(test_id); /* Delete the kevent */ EV_SET(&kev, SIGUSR1, EVFILT_SIGNAL, EV_DELETE, 0, 0, NULL); if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) err(1, "%s", test_id); /* Block SIGUSR1, then send it to ourselves */ sigset_t mask; sigemptyset(&mask); sigaddset(&mask, SIGUSR1); if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1) err(1, "sigprocmask"); if (kill(getpid(), SIGUSR1) < 0) err(1, "kill"); test_no_kevents(); success(); } void test_kevent_signal_oneshot(void) { const char *test_id = "kevent(EVFILT_SIGNAL, EV_ONESHOT)"; struct kevent kev; test_begin(test_id); EV_SET(&kev, SIGUSR1, EVFILT_SIGNAL, EV_ADD | EV_ONESHOT, 0, 0, NULL); if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) err(1, "%s", test_id); /* Block SIGUSR1, then send it to ourselves */ sigset_t mask; sigemptyset(&mask); sigaddset(&mask, SIGUSR1); if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1) err(1, "sigprocmask"); if (kill(getpid(), SIGUSR1) < 0) err(1, "kill"); kev.flags |= EV_CLEAR; kev.data = 1; kevent_cmp(&kev, kevent_get(kqfd)); /* Send another one and make sure we get no events */ if (kill(getpid(), SIGUSR1) < 0) err(1, "kill"); test_no_kevents(); success(); } #endif void test_evfilt_proc() { kqfd = kqueue(); signal(SIGUSR1, sig_handler); add_and_delete(); proc_track(0); /* Run without sleeping before children exit. */ proc_track(1); /* Sleep a bit in the children before exiting. */ #if TODO event_trigger(); #endif signal(SIGUSR1, SIG_DFL); #if TODO test_kevent_signal_add(); test_kevent_signal_del(); test_kevent_signal_get(); test_kevent_signal_disable(); test_kevent_signal_enable(); test_kevent_signal_oneshot(); #endif close(kqfd); } Index: head/tests/sys/kqueue/libkqueue/signal.c =================================================================== --- head/tests/sys/kqueue/libkqueue/signal.c (revision 341067) +++ head/tests/sys/kqueue/libkqueue/signal.c (revision 341068) @@ -1,199 +1,199 @@ /* * Copyright (c) 2009 Mark Heily * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * * $FreeBSD$ */ #include "common.h" int kqfd; void test_kevent_signal_add(void) { const char *test_id = "kevent(EVFILT_SIGNAL, EV_ADD)"; struct kevent kev; test_begin(test_id); EV_SET(&kev, SIGUSR1, EVFILT_SIGNAL, EV_ADD, 0, 0, NULL); if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) err(1, "%s", test_id); success(); } void test_kevent_signal_get(void) { const char *test_id = "kevent(EVFILT_SIGNAL, wait)"; struct kevent kev; test_begin(test_id); EV_SET(&kev, SIGUSR1, EVFILT_SIGNAL, EV_ADD, 0, 0, NULL); if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) err(1, "%s", test_id); /* Block SIGUSR1, then send it to ourselves */ sigset_t mask; sigemptyset(&mask); sigaddset(&mask, SIGUSR1); if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1) err(1, "sigprocmask"); if (kill(getpid(), SIGUSR1) < 0) err(1, "kill"); kev.flags |= EV_CLEAR; kev.data = 1; kevent_cmp(&kev, kevent_get(kqfd)); success(); } void test_kevent_signal_disable(void) { const char *test_id = "kevent(EVFILT_SIGNAL, EV_DISABLE)"; struct kevent kev; test_begin(test_id); EV_SET(&kev, SIGUSR1, EVFILT_SIGNAL, EV_DISABLE, 0, 0, NULL); if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) err(1, "%s", test_id); /* Block SIGUSR1, then send it to ourselves */ sigset_t mask; sigemptyset(&mask); sigaddset(&mask, SIGUSR1); if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1) err(1, "sigprocmask"); if (kill(getpid(), SIGUSR1) < 0) err(1, "kill"); test_no_kevents(); success(); } void test_kevent_signal_enable(void) { const char *test_id = "kevent(EVFILT_SIGNAL, EV_ENABLE)"; struct kevent kev; test_begin(test_id); EV_SET(&kev, SIGUSR1, EVFILT_SIGNAL, EV_ENABLE, 0, 0, NULL); if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) err(1, "%s", test_id); /* Block SIGUSR1, then send it to ourselves */ sigset_t mask; sigemptyset(&mask); sigaddset(&mask, SIGUSR1); if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1) err(1, "sigprocmask"); if (kill(getpid(), SIGUSR1) < 0) err(1, "kill"); kev.flags = EV_ADD | EV_CLEAR; #if LIBKQUEUE kev.data = 1; /* WORKAROUND */ #else kev.data = 2; // one extra time from test_kevent_signal_disable() #endif kevent_cmp(&kev, kevent_get(kqfd)); /* Delete the watch */ kev.flags = EV_DELETE; if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) err(1, "%s", test_id); success(); } void test_kevent_signal_del(void) { const char *test_id = "kevent(EVFILT_SIGNAL, EV_DELETE)"; struct kevent kev; test_begin(test_id); /* Delete the kevent */ EV_SET(&kev, SIGUSR1, EVFILT_SIGNAL, EV_DELETE, 0, 0, NULL); if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) err(1, "%s", test_id); /* Block SIGUSR1, then send it to ourselves */ sigset_t mask; sigemptyset(&mask); sigaddset(&mask, SIGUSR1); if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1) err(1, "sigprocmask"); if (kill(getpid(), SIGUSR1) < 0) err(1, "kill"); test_no_kevents(); success(); } void test_kevent_signal_oneshot(void) { const char *test_id = "kevent(EVFILT_SIGNAL, EV_ONESHOT)"; struct kevent kev; test_begin(test_id); EV_SET(&kev, SIGUSR1, EVFILT_SIGNAL, EV_ADD | EV_ONESHOT, 0, 0, NULL); if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) err(1, "%s", test_id); /* Block SIGUSR1, then send it to ourselves */ sigset_t mask; sigemptyset(&mask); sigaddset(&mask, SIGUSR1); if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1) err(1, "sigprocmask"); if (kill(getpid(), SIGUSR1) < 0) err(1, "kill"); kev.flags |= EV_CLEAR; kev.data = 1; kevent_cmp(&kev, kevent_get(kqfd)); /* Send another one and make sure we get no events */ if (kill(getpid(), SIGUSR1) < 0) err(1, "kill"); test_no_kevents(); success(); } void test_evfilt_signal() { - kqfd = kqueue(); - test_kevent_signal_add(); - test_kevent_signal_del(); - test_kevent_signal_get(); - test_kevent_signal_disable(); - test_kevent_signal_enable(); - test_kevent_signal_oneshot(); - close(kqfd); + kqfd = kqueue(); + test_kevent_signal_add(); + test_kevent_signal_del(); + test_kevent_signal_get(); + test_kevent_signal_disable(); + test_kevent_signal_enable(); + test_kevent_signal_oneshot(); + close(kqfd); } Index: head/tests/sys/kqueue/libkqueue/timer.c =================================================================== --- head/tests/sys/kqueue/libkqueue/timer.c (revision 341067) +++ head/tests/sys/kqueue/libkqueue/timer.c (revision 341068) @@ -1,532 +1,529 @@ /* * Copyright (c) 2009 Mark Heily * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * * $FreeBSD$ */ #include "common.h" #include #define MILLION 1000000 #define THOUSAND 1000 #define SEC_TO_MS(t) ((t) * THOUSAND) /* Convert seconds to milliseconds. */ #define SEC_TO_US(t) ((t) * MILLION) /* Convert seconds to microseconds. */ #define MS_TO_US(t) ((t) * THOUSAND) /* Convert milliseconds to microseconds. */ #define US_TO_NS(t) ((t) * THOUSAND) /* Convert microseconds to nanoseconds. */ int kqfd; /* Get the current time with microsecond precision. Used for * sub-second timing to make some timer tests run faster. */ static long now(void) { - - struct timeval tv; + struct timeval tv; - gettimeofday(&tv, NULL); - return SEC_TO_US(tv.tv_sec) + tv.tv_usec; + gettimeofday(&tv, NULL); + return SEC_TO_US(tv.tv_sec) + tv.tv_usec; } /* Sleep for a given number of milliseconds. The timeout is assumed to * be less than 1 second. */ void mssleep(int t) { + struct timespec stime = { + .tv_sec = 0, + .tv_nsec = US_TO_NS(MS_TO_US(t)), + }; - struct timespec stime = { - .tv_sec = 0, - .tv_nsec = US_TO_NS(MS_TO_US(t)), - }; - - nanosleep(&stime, NULL); + nanosleep(&stime, NULL); } /* Sleep for a given number of microseconds. The timeout is assumed to * be less than 1 second. */ void ussleep(int t) { + struct timespec stime = { + .tv_sec = 0, + .tv_nsec = US_TO_NS(t), + }; - struct timespec stime = { - .tv_sec = 0, - .tv_nsec = US_TO_NS(t), - }; - - nanosleep(&stime, NULL); + nanosleep(&stime, NULL); } void test_kevent_timer_add(void) { const char *test_id = "kevent(EVFILT_TIMER, EV_ADD)"; struct kevent kev; test_begin(test_id); EV_SET(&kev, 1, EVFILT_TIMER, EV_ADD, 0, 1000, NULL); if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) err(1, "%s", test_id); success(); } void test_kevent_timer_del(void) { const char *test_id = "kevent(EVFILT_TIMER, EV_DELETE)"; struct kevent kev; test_begin(test_id); EV_SET(&kev, 1, EVFILT_TIMER, EV_DELETE, 0, 0, NULL); if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) err(1, "%s", test_id); test_no_kevents(); success(); } void test_kevent_timer_get(void) { const char *test_id = "kevent(EVFILT_TIMER, wait)"; struct kevent kev; test_begin(test_id); EV_SET(&kev, 1, EVFILT_TIMER, EV_ADD, 0, 1000, NULL); if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) err(1, "%s", test_id); kev.flags |= EV_CLEAR; kev.data = 1; kevent_cmp(&kev, kevent_get(kqfd)); EV_SET(&kev, 1, EVFILT_TIMER, EV_DELETE, 0, 0, NULL); if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) err(1, "%s", test_id); success(); } static void test_oneshot(void) { const char *test_id = "kevent(EVFILT_TIMER, EV_ONESHOT)"; struct kevent kev; test_begin(test_id); test_no_kevents(); EV_SET(&kev, vnode_fd, EVFILT_TIMER, EV_ADD | EV_ONESHOT, 0, 500,NULL); if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) err(1, "%s", test_id); /* Retrieve the event */ kev.flags = EV_ADD | EV_CLEAR | EV_ONESHOT; kev.data = 1; kevent_cmp(&kev, kevent_get(kqfd)); /* Check if the event occurs again */ sleep(3); test_no_kevents(); success(); } static void test_periodic(void) { const char *test_id = "kevent(EVFILT_TIMER, periodic)"; struct kevent kev; test_begin(test_id); test_no_kevents(); EV_SET(&kev, vnode_fd, EVFILT_TIMER, EV_ADD, 0, 1000,NULL); if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) err(1, "%s", test_id); /* Retrieve the event */ kev.flags = EV_ADD | EV_CLEAR; kev.data = 1; kevent_cmp(&kev, kevent_get(kqfd)); /* Check if the event occurs again */ sleep(1); kevent_cmp(&kev, kevent_get(kqfd)); /* Delete the event */ kev.flags = EV_DELETE; if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) err(1, "%s", test_id); success(); } static void disable_and_enable(void) { const char *test_id = "kevent(EVFILT_TIMER, EV_DISABLE and EV_ENABLE)"; struct kevent kev; test_begin(test_id); test_no_kevents(); /* Add the watch and immediately disable it */ EV_SET(&kev, vnode_fd, EVFILT_TIMER, EV_ADD | EV_ONESHOT, 0, 2000,NULL); if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) err(1, "%s", test_id); kev.flags = EV_DISABLE; if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) err(1, "%s", test_id); test_no_kevents(); /* Re-enable and check again */ kev.flags = EV_ENABLE; if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) err(1, "%s", test_id); kev.flags = EV_ADD | EV_CLEAR | EV_ONESHOT; kev.data = 1; kevent_cmp(&kev, kevent_get(kqfd)); success(); } static void test_abstime(void) { const char *test_id = "kevent(EVFILT_TIMER, EV_ONESHOT, NOTE_ABSTIME)"; struct kevent kev; time_t start; time_t stop; const int timeout = 3; test_begin(test_id); test_no_kevents(); start = time(NULL); EV_SET(&kev, vnode_fd, EVFILT_TIMER, EV_ADD | EV_ONESHOT, NOTE_ABSTIME | NOTE_SECONDS, start + timeout, NULL); if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) err(1, "%s", test_id); /* Retrieve the event */ kev.flags = EV_ADD | EV_ONESHOT; kev.data = 1; kev.fflags = 0; kevent_cmp(&kev, kevent_get(kqfd)); stop = time(NULL); if (stop < start + timeout) - err(1, "too early %jd %jd", (intmax_t)stop, (intmax_t)(start + timeout)); + err(1, "too early %jd %jd", (intmax_t)stop, (intmax_t)(start + timeout)); /* Check if the event occurs again */ sleep(3); test_no_kevents(); success(); } static void test_update(void) { const char *test_id = "kevent(EVFILT_TIMER (UPDATE), EV_ADD | EV_ONESHOT)"; struct kevent kev; long elapsed; long start; test_begin(test_id); test_no_kevents(); /* First set the timer to 1 second */ EV_SET(&kev, vnode_fd, EVFILT_TIMER, EV_ADD | EV_ONESHOT, - NOTE_USECONDS, SEC_TO_US(1), (void *)1); + NOTE_USECONDS, SEC_TO_US(1), (void *)1); start = now(); if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); + err(1, "%s", test_id); /* Now reduce the timer to 1 ms */ EV_SET(&kev, vnode_fd, EVFILT_TIMER, EV_ADD | EV_ONESHOT, - NOTE_USECONDS, MS_TO_US(1), (void *)2); + NOTE_USECONDS, MS_TO_US(1), (void *)2); if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); + err(1, "%s", test_id); /* Wait for the event */ kev.flags |= EV_CLEAR; kev.fflags &= ~NOTE_USECONDS; kev.data = 1; kevent_cmp(&kev, kevent_get(kqfd)); elapsed = now() - start; /* Check that the timer expired after at least 1 ms, but less than * 1 second. This check is to make sure that the original 1 second * timeout was not used. */ printf("timer expired after %ld us\n", elapsed); if (elapsed < MS_TO_US(1)) - errx(1, "early timer expiration: %ld us", elapsed); + errx(1, "early timer expiration: %ld us", elapsed); if (elapsed > SEC_TO_US(1)) - errx(1, "late timer expiration: %ld us", elapsed); + errx(1, "late timer expiration: %ld us", elapsed); success(); } static void test_update_equal(void) { const char *test_id = "kevent(EVFILT_TIMER (UPDATE=), EV_ADD | EV_ONESHOT)"; struct kevent kev; long elapsed; long start; test_begin(test_id); test_no_kevents(); /* First set the timer to 1 ms */ EV_SET(&kev, vnode_fd, EVFILT_TIMER, EV_ADD | EV_ONESHOT, - NOTE_USECONDS, MS_TO_US(1), NULL); + NOTE_USECONDS, MS_TO_US(1), NULL); if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); + err(1, "%s", test_id); /* Sleep for a significant fraction of the timeout. */ ussleep(600); /* Now re-add the timer with the same parameters */ start = now(); if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); + err(1, "%s", test_id); /* Wait for the event */ kev.flags |= EV_CLEAR; kev.fflags &= ~NOTE_USECONDS; kev.data = 1; kevent_cmp(&kev, kevent_get(kqfd)); elapsed = now() - start; /* Check that the timer expired after at least 1 ms. This check is * to make sure that the timer re-started and that the event is * not from the original add of the timer. */ printf("timer expired after %ld us\n", elapsed); if (elapsed < MS_TO_US(1)) - errx(1, "early timer expiration: %ld us", elapsed); + errx(1, "early timer expiration: %ld us", elapsed); success(); } static void test_update_expired(void) { const char *test_id = "kevent(EVFILT_TIMER (UPDATE EXP), EV_ADD | EV_ONESHOT)"; struct kevent kev; long elapsed; long start; test_begin(test_id); test_no_kevents(); /* Set the timer to 1ms */ EV_SET(&kev, vnode_fd, EVFILT_TIMER, EV_ADD | EV_ONESHOT, - NOTE_USECONDS, MS_TO_US(1), NULL); + NOTE_USECONDS, MS_TO_US(1), NULL); if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); + err(1, "%s", test_id); /* Wait for 2 ms to give the timer plenty of time to expire. */ mssleep(2); /* Now re-add the timer */ start = now(); if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); + err(1, "%s", test_id); /* Wait for the event */ kev.flags |= EV_CLEAR; kev.fflags &= ~NOTE_USECONDS; kev.data = 1; kevent_cmp(&kev, kevent_get(kqfd)); elapsed = now() - start; /* Check that the timer expired after at least 1 ms. This check * is to make sure that the timer re-started and that the event is * not from the original add (and expiration) of the timer. */ printf("timer expired after %ld us\n", elapsed); if (elapsed < MS_TO_US(1)) - errx(1, "early timer expiration: %ld us", elapsed); + errx(1, "early timer expiration: %ld us", elapsed); /* Make sure the re-added timer does not fire. In other words, * test that the event received above was the only event from the * add and re-add of the timer. */ mssleep(2); test_no_kevents(); success(); } static void test_update_periodic(void) { const char *test_id = "kevent(EVFILT_TIMER (UPDATE), periodic)"; struct kevent kev; long elapsed; long start; long stop; test_begin(test_id); test_no_kevents(); EV_SET(&kev, vnode_fd, EVFILT_TIMER, EV_ADD, 0, SEC_TO_MS(1), NULL); if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); + err(1, "%s", test_id); /* Retrieve the event */ kev.flags = EV_ADD | EV_CLEAR; kev.data = 1; kevent_cmp(&kev, kevent_get(kqfd)); /* Check if the event occurs again */ sleep(1); kevent_cmp(&kev, kevent_get(kqfd)); /* Re-add with new timeout. */ EV_SET(&kev, vnode_fd, EVFILT_TIMER, EV_ADD, 0, SEC_TO_MS(2), NULL); start = now(); if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); + err(1, "%s", test_id); /* Retrieve the event */ kev.flags = EV_ADD | EV_CLEAR; kev.data = 1; kevent_cmp(&kev, kevent_get(kqfd)); stop = now(); elapsed = stop - start; /* Check that the timer expired after at least 2 ms. */ printf("timer expired after %ld us\n", elapsed); if (elapsed < MS_TO_US(2)) - errx(1, "early timer expiration: %ld us", elapsed); + errx(1, "early timer expiration: %ld us", elapsed); /* Delete the event */ kev.flags = EV_DELETE; if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); + err(1, "%s", test_id); success(); } static void test_update_timing(void) { #define MIN_SLEEP 500 #define MAX_SLEEP 1500 const char *test_id = "kevent(EVFILT_TIMER (UPDATE TIMING), EV_ADD | EV_ONESHOT)"; struct kevent kev; int iteration; int sleeptime; long elapsed; long start; long stop; test_begin(test_id); test_no_kevents(); /* Re-try the update tests with a variety of delays between the * original timer activation and the update of the timer. The goal * is to show that in all cases the only timer event that is * received is from the update and not the original timer add. */ for (sleeptime = MIN_SLEEP, iteration = 1; - sleeptime < MAX_SLEEP; - ++sleeptime, ++iteration) { + sleeptime < MAX_SLEEP; + ++sleeptime, ++iteration) { - /* First set the timer to 1 ms */ - EV_SET(&kev, vnode_fd, EVFILT_TIMER, EV_ADD | EV_ONESHOT, - NOTE_USECONDS, MS_TO_US(1), NULL); - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); + /* First set the timer to 1 ms */ + EV_SET(&kev, vnode_fd, EVFILT_TIMER, EV_ADD | EV_ONESHOT, + NOTE_USECONDS, MS_TO_US(1), NULL); + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "%s", test_id); - /* Delay; the delay ranges from less than to greater than the - * timer period. - */ - ussleep(sleeptime); + /* Delay; the delay ranges from less than to greater than the + * timer period. + */ + ussleep(sleeptime); - /* Now re-add the timer with the same parameters */ - start = now(); - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); + /* Now re-add the timer with the same parameters */ + start = now(); + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "%s", test_id); - /* Wait for the event */ - kev.flags |= EV_CLEAR; - kev.fflags &= ~NOTE_USECONDS; - kev.data = 1; - kevent_cmp(&kev, kevent_get(kqfd)); - stop = now(); - elapsed = stop - start; + /* Wait for the event */ + kev.flags |= EV_CLEAR; + kev.fflags &= ~NOTE_USECONDS; + kev.data = 1; + kevent_cmp(&kev, kevent_get(kqfd)); + stop = now(); + elapsed = stop - start; - /* Check that the timer expired after at least 1 ms. This - * check is to make sure that the timer re-started and that - * the event is not from the original add of the timer. - */ - if (elapsed < MS_TO_US(1)) - errx(1, "early timer expiration: %ld us", elapsed); + /* Check that the timer expired after at least 1 ms. This + * check is to make sure that the timer re-started and that + * the event is not from the original add of the timer. + */ + if (elapsed < MS_TO_US(1)) + errx(1, "early timer expiration: %ld us", elapsed); - /* Make sure the re-added timer does not fire. In other words, - * test that the event received above was the only event from - * the add and re-add of the timer. - */ - mssleep(2); - test_no_kevents_quietly(); + /* Make sure the re-added timer does not fire. In other words, + * test that the event received above was the only event from + * the add and re-add of the timer. + */ + mssleep(2); + test_no_kevents_quietly(); } success(); } void test_evfilt_timer() { - kqfd = kqueue(); - test_kevent_timer_add(); - test_kevent_timer_del(); - test_kevent_timer_get(); - test_oneshot(); - test_periodic(); - test_abstime(); - test_update(); - test_update_equal(); - test_update_expired(); - test_update_timing(); - test_update_periodic(); - disable_and_enable(); - close(kqfd); + kqfd = kqueue(); + test_kevent_timer_add(); + test_kevent_timer_del(); + test_kevent_timer_get(); + test_oneshot(); + test_periodic(); + test_abstime(); + test_update(); + test_update_equal(); + test_update_expired(); + test_update_timing(); + test_update_periodic(); + disable_and_enable(); + close(kqfd); } Index: head/tests/sys/kqueue/libkqueue/user.c =================================================================== --- head/tests/sys/kqueue/libkqueue/user.c (revision 341067) +++ head/tests/sys/kqueue/libkqueue/user.c (revision 341068) @@ -1,129 +1,129 @@ /* * Copyright (c) 2009 Mark Heily * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * * $FreeBSD$ */ #include "common.h" int kqfd; static void add_and_delete(void) { const char *test_id = "kevent(EVFILT_USER, EV_ADD and EV_DELETE)"; struct kevent kev; test_begin(test_id); kevent_add(kqfd, &kev, 1, EVFILT_USER, EV_ADD, 0, 0, NULL); test_no_kevents(); kevent_add(kqfd, &kev, 1, EVFILT_USER, EV_DELETE, 0, 0, NULL); test_no_kevents(); success(); } static void event_wait(void) { const char *test_id = "kevent(EVFILT_USER, wait)"; struct kevent kev; test_begin(test_id); test_no_kevents(); /* Add the event, and then trigger it */ kevent_add(kqfd, &kev, 1, EVFILT_USER, EV_ADD | EV_CLEAR, 0, 0, NULL); kevent_add(kqfd, &kev, 1, EVFILT_USER, 0, NOTE_TRIGGER, 0, NULL); kev.fflags &= ~NOTE_FFCTRLMASK; kev.fflags &= ~NOTE_TRIGGER; kev.flags = EV_CLEAR; kevent_cmp(&kev, kevent_get(kqfd)); test_no_kevents(); success(); } static void disable_and_enable(void) { const char *test_id = "kevent(EVFILT_USER, EV_DISABLE and EV_ENABLE)"; struct kevent kev; test_begin(test_id); test_no_kevents(); kevent_add(kqfd, &kev, 1, EVFILT_USER, EV_ADD, 0, 0, NULL); kevent_add(kqfd, &kev, 1, EVFILT_USER, EV_DISABLE, 0, 0, NULL); /* Trigger the event, but since it is disabled, nothing will happen. */ kevent_add(kqfd, &kev, 1, EVFILT_USER, 0, NOTE_TRIGGER, 0, NULL); test_no_kevents(); kevent_add(kqfd, &kev, 1, EVFILT_USER, EV_ENABLE, 0, 0, NULL); kevent_add(kqfd, &kev, 1, EVFILT_USER, 0, NOTE_TRIGGER, 0, NULL); kev.flags = EV_CLEAR; kev.fflags &= ~NOTE_FFCTRLMASK; kev.fflags &= ~NOTE_TRIGGER; kevent_cmp(&kev, kevent_get(kqfd)); success(); } static void oneshot(void) { const char *test_id = "kevent(EVFILT_USER, EV_ONESHOT)"; struct kevent kev; test_begin(test_id); test_no_kevents(); kevent_add(kqfd, &kev, 2, EVFILT_USER, EV_ADD | EV_ONESHOT, 0, 0, NULL); puts(" -- event 1"); kevent_add(kqfd, &kev, 2, EVFILT_USER, 0, NOTE_TRIGGER, 0, NULL); kev.flags = EV_ONESHOT; kev.fflags &= ~NOTE_FFCTRLMASK; kev.fflags &= ~NOTE_TRIGGER; kevent_cmp(&kev, kevent_get(kqfd)); test_no_kevents(); success(); } void test_evfilt_user() { - kqfd = kqueue(); + kqfd = kqueue(); add_and_delete(); event_wait(); disable_and_enable(); oneshot(); /* TODO: try different fflags operations */ - close(kqfd); + close(kqfd); } Index: head/tests/sys/kqueue/libkqueue/vnode.c =================================================================== --- head/tests/sys/kqueue/libkqueue/vnode.c (revision 341067) +++ head/tests/sys/kqueue/libkqueue/vnode.c (revision 341068) @@ -1,266 +1,266 @@ /* * Copyright (c) 2009 Mark Heily * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * * $FreeBSD$ */ #include "common.h" int kqfd; int vnode_fd; void test_kevent_vnode_add(void) { const char *test_id = "kevent(EVFILT_VNODE, EV_ADD)"; const char *testfile = "./kqueue-test.tmp"; struct kevent kev; test_begin(test_id); system("touch ./kqueue-test.tmp"); vnode_fd = open(testfile, O_RDONLY); if (vnode_fd < 0) err(1, "open of %s", testfile); else printf("vnode_fd = %d\n", vnode_fd); EV_SET(&kev, vnode_fd, EVFILT_VNODE, EV_ADD, NOTE_WRITE | NOTE_ATTRIB | NOTE_RENAME | NOTE_DELETE, 0, NULL); if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) err(1, "%s", test_id); success(); } void test_kevent_vnode_note_delete(void) { const char *test_id = "kevent(EVFILT_VNODE, NOTE_DELETE)"; struct kevent kev; test_begin(test_id); EV_SET(&kev, vnode_fd, EVFILT_VNODE, EV_ADD | EV_ONESHOT, NOTE_DELETE, 0, NULL); if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) err(1, "%s", test_id); if (unlink("./kqueue-test.tmp") < 0) err(1, "unlink"); kevent_cmp(&kev, kevent_get(kqfd)); success(); } void test_kevent_vnode_note_write(void) { const char *test_id = "kevent(EVFILT_VNODE, NOTE_WRITE)"; struct kevent kev; test_begin(test_id); EV_SET(&kev, vnode_fd, EVFILT_VNODE, EV_ADD | EV_ONESHOT, NOTE_WRITE, 0, NULL); if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) err(1, "%s", test_id); if (system("echo hello >> ./kqueue-test.tmp") < 0) err(1, "system"); /* BSD kqueue adds NOTE_EXTEND even though it was not requested */ /* BSD kqueue removes EV_ENABLE */ kev.flags &= ~EV_ENABLE; // XXX-FIXME compatibility issue kev.fflags |= NOTE_EXTEND; // XXX-FIXME compatibility issue kevent_cmp(&kev, kevent_get(kqfd)); success(); } void test_kevent_vnode_note_attrib(void) { const char *test_id = "kevent(EVFILT_VNODE, NOTE_ATTRIB)"; struct kevent kev; int nfds; test_begin(test_id); EV_SET(&kev, vnode_fd, EVFILT_VNODE, EV_ADD | EV_ONESHOT, NOTE_ATTRIB, 0, NULL); if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) err(1, "%s", test_id); if (system("touch ./kqueue-test.tmp") < 0) err(1, "system"); nfds = kevent(kqfd, NULL, 0, &kev, 1, NULL); if (nfds < 1) err(1, "%s", test_id); if (kev.ident != vnode_fd || kev.filter != EVFILT_VNODE || kev.fflags != NOTE_ATTRIB) err(1, "%s - incorrect event (sig=%u; filt=%d; flags=%d)", test_id, (unsigned int)kev.ident, kev.filter, kev.flags); success(); } void test_kevent_vnode_note_rename(void) { const char *test_id = "kevent(EVFILT_VNODE, NOTE_RENAME)"; struct kevent kev; int nfds; test_begin(test_id); EV_SET(&kev, vnode_fd, EVFILT_VNODE, EV_ADD | EV_ONESHOT, NOTE_RENAME, 0, NULL); if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) err(1, "%s", test_id); if (system("mv ./kqueue-test.tmp ./kqueue-test2.tmp") < 0) err(1, "system"); nfds = kevent(kqfd, NULL, 0, &kev, 1, NULL); if (nfds < 1) err(1, "%s", test_id); if (kev.ident != vnode_fd || kev.filter != EVFILT_VNODE || kev.fflags != NOTE_RENAME) err(1, "%s - incorrect event (sig=%u; filt=%d; flags=%d)", test_id, (unsigned int)kev.ident, kev.filter, kev.flags); if (system("mv ./kqueue-test2.tmp ./kqueue-test.tmp") < 0) err(1, "system"); success(); } void test_kevent_vnode_del(void) { const char *test_id = "kevent(EVFILT_VNODE, EV_DELETE)"; struct kevent kev; test_begin(test_id); EV_SET(&kev, vnode_fd, EVFILT_VNODE, EV_DELETE, 0, 0, NULL); if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) err(1, "%s", test_id); success(); } void test_kevent_vnode_disable_and_enable(void) { const char *test_id = "kevent(EVFILT_VNODE, EV_DISABLE and EV_ENABLE)"; struct kevent kev; int nfds; test_begin(test_id); test_no_kevents(); /* Add the watch and immediately disable it */ EV_SET(&kev, vnode_fd, EVFILT_VNODE, EV_ADD | EV_ONESHOT, NOTE_ATTRIB, 0, NULL); if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) err(1, "%s", test_id); kev.flags = EV_DISABLE; if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) err(1, "%s", test_id); /* Confirm that the watch is disabled */ if (system("touch ./kqueue-test.tmp") < 0) err(1, "system"); test_no_kevents(); /* Re-enable and check again */ kev.flags = EV_ENABLE; if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) err(1, "%s", test_id); if (system("touch ./kqueue-test.tmp") < 0) err(1, "system"); nfds = kevent(kqfd, NULL, 0, &kev, 1, NULL); if (nfds < 1) err(1, "%s", test_id); if (kev.ident != vnode_fd || kev.filter != EVFILT_VNODE || kev.fflags != NOTE_ATTRIB) err(1, "%s - incorrect event (sig=%u; filt=%d; flags=%d)", test_id, (unsigned int)kev.ident, kev.filter, kev.flags); success(); } #if HAVE_EV_DISPATCH void test_kevent_vnode_dispatch(void) { const char *test_id = "kevent(EVFILT_VNODE, EV_DISPATCH)"; struct kevent kev; int nfds; test_begin(test_id); test_no_kevents(); EV_SET(&kev, vnode_fd, EVFILT_VNODE, EV_ADD | EV_DISPATCH, NOTE_ATTRIB, 0, NULL); if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) err(1, "%s", test_id); if (system("touch ./kqueue-test.tmp") < 0) err(1, "system"); nfds = kevent(kqfd, NULL, 0, &kev, 1, NULL); if (nfds < 1) err(1, "%s", test_id); if (kev.ident != vnode_fd || kev.filter != EVFILT_VNODE || kev.fflags != NOTE_ATTRIB) err(1, "%s - incorrect event (sig=%u; filt=%d; flags=%d)", test_id, (unsigned int)kev.ident, kev.filter, kev.flags); /* Confirm that the watch is disabled automatically */ puts("-- checking that watch is disabled"); if (system("touch ./kqueue-test.tmp") < 0) err(1, "system"); test_no_kevents(); /* Delete the watch */ EV_SET(&kev, vnode_fd, EVFILT_VNODE, EV_DELETE, NOTE_ATTRIB, 0, NULL); if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) err(1, "remove watch failed: %s", test_id); success(); } #endif /* HAVE_EV_DISPATCH */ void test_evfilt_vnode() { - kqfd = kqueue(); - test_kevent_vnode_add(); - test_kevent_vnode_del(); - test_kevent_vnode_disable_and_enable(); + kqfd = kqueue(); + test_kevent_vnode_add(); + test_kevent_vnode_del(); + test_kevent_vnode_disable_and_enable(); #if HAVE_EV_DISPATCH - test_kevent_vnode_dispatch(); + test_kevent_vnode_dispatch(); #endif - test_kevent_vnode_note_write(); - test_kevent_vnode_note_attrib(); - test_kevent_vnode_note_rename(); - test_kevent_vnode_note_delete(); - close(kqfd); + test_kevent_vnode_note_write(); + test_kevent_vnode_note_attrib(); + test_kevent_vnode_note_rename(); + test_kevent_vnode_note_delete(); + close(kqfd); }