From owner-freebsd-hackers@FreeBSD.ORG Thu Jul 12 12:35:18 2012 Return-Path: Delivered-To: freebsd-hackers@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [69.147.83.52]) by hub.freebsd.org (Postfix) with ESMTP id AFBCF10657A8 for ; Thu, 12 Jul 2012 12:35:18 +0000 (UTC) (envelope-from jhb@freebsd.org) Received: from bigwig.baldwin.cx (bigknife-pt.tunnel.tserv9.chi1.ipv6.he.net [IPv6:2001:470:1f10:75::2]) by mx1.freebsd.org (Postfix) with ESMTP id 3178B8FC15 for ; Thu, 12 Jul 2012 12:35:11 +0000 (UTC) Received: from jhbbsd.localnet (unknown [209.249.190.124]) by bigwig.baldwin.cx (Postfix) with ESMTPSA id 7FD96B93A; Thu, 12 Jul 2012 08:35:10 -0400 (EDT) From: John Baldwin To: freebsd-hackers@freebsd.org Date: Thu, 12 Jul 2012 08:34:40 -0400 User-Agent: KMail/1.13.5 (FreeBSD/8.2-CBSD-20110714-p17; KDE/4.5.5; amd64; ; ) References: <1342036332.8313.8.camel@albrecht-desktop> <1342040447.1123.31.camel@revolution.hippie.lan> In-Reply-To: <1342040447.1123.31.camel@revolution.hippie.lan> MIME-Version: 1.0 Content-Type: Text/Plain; charset="iso-8859-1" Content-Transfer-Encoding: 7bit Message-Id: <201207120834.40745.jhb@freebsd.org> X-Greylist: Sender succeeded SMTP AUTH, not delayed by milter-greylist-4.2.7 (bigwig.baldwin.cx); Thu, 12 Jul 2012 08:35:10 -0400 (EDT) Cc: Ian Lepore , Paul Albrecht Subject: Re: kqueue periodic timer confusion X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 12 Jul 2012 12:35:18 -0000 On Wednesday, July 11, 2012 5:00:47 pm Ian Lepore wrote: > On Wed, 2012-07-11 at 14:52 -0500, Paul Albrecht wrote: > > Hi, > > > > Sorry about this repost but I'm confused about the responses I received > > in my last post so I'm looking for some clarification. > > > > Specifically, I though I could use the kqueue timer as essentially a > > "drop in" replacement for linuxfd_create/read, but was surprised that > > the accuracy of the kqueue timer is much less than what I need for my > > application. > > > > So my confusion at this point is whether this is consider to be a bug or > > "feature"? > > > > Here's some test code if you want to verify the problem: > > > > #include > > #include > > #include > > #include > > #include > > #include > > #include > > #include > > > > int > > main(void) > > { > > int i,msec; > > int kq,nev; > > struct kevent inqueue; > > struct kevent outqueue; > > struct timeval start,end; > > > > if ((kq = kqueue()) == -1) { > > fprintf(stderr, "kqueue error!? errno = %s", strerror(errno)); > > exit(EXIT_FAILURE); > > } > > EV_SET(&inqueue, 1, EVFILT_TIMER, EV_ADD | EV_ENABLE, 0, 20, 0); > > > > gettimeofday(&start, 0); > > for (i = 0; i < 50; i++) { > > if ((nev = kevent(kq, &inqueue, 1, &outqueue, 1, NULL)) == -1) { > > fprintf(stderr, "kevent error!? 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); > > } > > } > > gettimeofday(&end, 0); > > > > msec = ((end.tv_sec - start.tv_sec) * 1000) + (((1000000 + end.tv_usec - start.tv_usec) / 1000) - 1000); > > > > printf("msec = %d\n", msec); > > > > close(kq); > > return EXIT_SUCCESS; > > } > > > > > > What you are seeing is "just the way FreeBSD currently works." > > Sleeping (in most all of its various forms, and I've just looked at the > kevent code to verify this is true there) is handled by converting the > amount of time to sleep (usually specified in a timeval or timespec > struct) to a count of timer ticks, using an internal routine called > tvtohz() in kern/kern_time.c. That routine rounds up by one tick to > account for the current tick. Whether that's a good idea or not (it > probably was once, and probably not anymore) it's how things currently > work, and could explain the fairly consistant +1ms you're seeing. This is all true, but mostly irrelevant for his case. EVFILT_TIMER installs a periodic callout that executes KNOTE() and then resets itself (via callout_reset()) each time it runs. This should generally be closer to regulary spaced intervals than something that does: for (;;) { usleep(20 * 1000); } Which should be subject to the problem you are describing. It would be interesting to see if the callout routine itself is running at the right interval or if it is being delayed. If the latter, then that should be fixed if at all possible. You could investigate that by adding KTR traces to the relevant callout routine (so recording the TSC timestamp each time the callout runs), and then parsing the ktrdump output to compute TSC deltas and examining that distribution to see if it is noisy or incorrect, etc. -- John Baldwin