How to use sem_timedwait?
Kurt Lidl
lidl at pix.net
Thu Dec 15 16:47:34 UTC 2016
On 12/14/16 11:35 PM, Ian Lepore wrote:
> /*
> * This tests kevent timer events to make sure that they are properly
> * metronomic. That is, each event should occur at the requested
> * interval following the prior event, and in particular the phase of
> * event delivery should not drift because of the time it takes to
> * process the event and schedule the next one in the kernel. (i.e.,
> * this is a userland test of kernel kevent timer performance.)
> * Because it's hard to measure the tiny increments of time between
> * each sleep, we run a loop that takes several seconds and look for
> * the total elapsed time to be increment*loopcount plus a tiny bit of
> * overhead for getting the ending time.
> */
>
> #include <stdio.h>
> #include <stdlib.h>
> #include <string.h>
> #include <unistd.h>
> #include <errno.h>
> #include <sys/types.h>
> #include <sys/event.h>
> #include <sys/time.h>
>
> int
> main(int argc, char ** argv)
> {
> int i, interval;
> int64_t nsec;
> int kq,num_events;
> struct kevent inqueue;
> struct kevent outqueue;
> struct timespec start,end;
>
> // argument is timer interval in nanoseconds.
> if (argc > 1)
> interval = strtoul(argv[1], NULL, 0);
> else
> interval = 1000000;
>
> if ((kq = kqueue()) == -1) {
> fprintf(stderr, "kqueue errno = %s", strerror(errno));
> exit(EXIT_FAILURE);
> }
> EV_SET(&inqueue, 1, EVFILT_TIMER, EV_ADD | EV_ENABLE,
> NOTE_NSECONDS, interval, 0);
>
> clock_gettime(CLOCK_MONOTONIC_PRECISE, &start);
>
> for (i = 0; i < 10000000000 / interval; i++) {
> num_events = kevent(kq, &inqueue, 1, &outqueue, 1, NULL);
> if (num_events == -1) {
> fprintf(stderr, "kevent errno = %s", strerror(errno));
> exit(EXIT_FAILURE);
> } else if (outqueue.flags & EV_ERROR) {
> fprintf(stderr, "EV_ERROR: %s\n", strerror(outqueue.data));
> exit(EXIT_FAILURE);
> }
> if (num_events != 1)
> printf("num_events %d at i %d\n", num_events, i);
> }
> clock_gettime(CLOCK_MONOTONIC_PRECISE, &end);
>
> nsec = (end.tv_sec * 1000000000LL + end.tv_nsec) -
> (start.tv_sec * 1000000000LL + start.tv_nsec);
> printf("nsec = %jd for %d loops of %d nsec\n",
> (intmax_t)nsec, i, interval);
>
> close(kq);
> return EXIT_SUCCESS;
> }
When I run this code on a sparc64, it panics the machine!
lidl at ton-148: ./x
panic: trap: fast data access mmu miss (kernel)
KDB: stack backtrace:
vpanic() at vpanic+0xfc
panic() at panic+0x20
trap() at trap+0x554
-- fast data access mmu miss tar=0xc09eda8f %o7=0xc039b344 --
userland() at filt_timerattach+0x78
user trace: trap %o7=0xc039b344
pc 0xc039b378, sp 0xedebe761
done
KDB: enter: panic
[ thread pid 1263 tid 100583 ]
Stopped at kdb_enter+0x80: ta %xcc, 1
db>
Oops.
-Kurt
More information about the freebsd-hackers
mailing list