On 8/5/23 00:49, Scott Cheloha wrote:
> On Sat, Aug 05, 2023 at 12:17:48AM -0400, aisha wrote:
>> On 22/09/10 01:53PM, Visa Hankala wrote:
>>> On Wed, Aug 31, 2022 at 04:48:37PM -0400, aisha wrote:
>>>> I've added a patch which adds support for NOTE_{,U,M,N}SECONDS for
>>>> EVFILT_TIMER in the kqueue interface.
>>> It sort of makes sense to add an option to specify timeouts in
>>> sub-millisecond precision. It feels complete overengineering to add
>>> multiple time units on the level of the kernel interface. However,
>>> it looks that FreeBSD and NetBSD have already done this following
>>> macOS' lead...
>>>
>>>> I've also added the NOTE_ABSTIME but haven't done any actual implementation
>>>> there as I am not sure how the `data` field should be interpreted (is it
>>>> absolute time in seconds since epoch?).
>>> I think FreeBSD and NetBSD take NOTE_ABSTIME as time since the epoch.
>>>
>>> Below is a revised patch that takes into account some corner cases.
>>> It tries to be API-compatible with FreeBSD and NetBSD. I have adjusted
>>> the NOTE_{,M,U,N}SECONDS flags so that they are enum-like.
>>>
>>> The manual page bits are from NetBSD.
>>>
>>> It is quite late to introduce a feature like this within this release
>>> cycle. Until now, the timer code has ignored the fflags field. There
>>> might be pieces of software that are careless with struct kevent and
>>> that would break as a result of this patch. Programs that are widely
>>> used on different BSDs are probably fine already, though.
>> Sorry, I had forgotten this patch for a long time!!! I've been running with
>> this for a while now and it's been working nicely.
> Where is this being used in ports? I think having "one of each" for
> seconds, milliseconds, microseconds, and nanoseconds is (as visa
> noted) way, way over-the-top.
I was using it with a port that I sent out a while ago but never got
into tree (was before I joined the project) -
https://marc.info/?l=openbsd-ports&m=165715874509440&w=2
I also agree with it being over the top but that's the way it is in
net/freebsd, I'm also fine with breaking compatibility and only keeping
nano, no preferences either way.
> The original EVFILT_TIMER supported only milliseconds, yes. Given
> that it debuted in the late 90s, I think that was a bad choice. But
> when milliseconds were insufficiently precise, the obvious thing would
> be to add support for nanoseconds... and then stop.
>
> The decision to use the UTC clock with no option to select a different
> clockid_t for NOTE_ABSTIME is also unfortunate.
Yes, furthermore this was very unclear as I couldn't find this in the
man pages for either of net/freebsd.
>
> Grumble.
>
>> I had an unrelated question inlined.
>>
>> [...]
>>> static void
>>> -filt_timer_timeout_add(struct knote *kn)
>>> +filt_timeradd(struct knote *kn, struct timespec *ts)
>>> {
>>> - struct timeval tv;
>>> + struct timespec expiry, now;
>>> struct timeout *to = kn->kn_hook;
>>> int tticks;
>>>
>>> - tv.tv_sec = kn->kn_sdata / 1000;
>>> - tv.tv_usec = (kn->kn_sdata % 1000) * 1000;
>>> - tticks = tvtohz(&tv);
>>> - /* Remove extra tick from tvtohz() if timeout has fired before. */
>>> + if (kn->kn_sfflags & NOTE_ABSTIME) {
>>> + nanotime(&now);
>>> + if (timespeccmp(ts, &now, >)) {
>>> + timespecsub(ts, &now, &expiry);
>>> + /* XXX timeout_at_ts */
>>> + timeout_add(to, tstohz(&expiry));
> visa:
>
> we should use timeout_abs_ts() here. I need to adjust it, though.
>
>>> + } else {
>>> + /* Expire immediately. */
>>> + filt_timerexpire(kn);
>>> + }
>>> + return;
>>> + }
>>> +
>>> + tticks = tstohz(ts);
>>> + /* Remove extra tick from tstohz() if timeout has fired before. */
>>> if (timeout_triggered(to))
>>> tticks--;
>> I always wondered why one tick was removed, is one tick really
>> that important? And does a timeout firing only cost one tick?
> When you convert a duration to a count of ticks with tstohz(), it adds
> an extra tick to the result to keep you from undershooting your
> timeout. You start counting your timeout at the start of the *next*
> tick, otherwise the timeout might fire early. However, after the
> timeout has expired once, you no longer need the extra tick because
> you can (more or less) assume that the timeout is running at the start
> of the new tick.
>
> I know that sounds a little fuzzy, but in practice it works.
Haha, these are the kind of weird idiosyncrasies that are fun to know
about. Thank you very much for the explanation! :D
So I went around looking at how large a tick really is and seems like we
get it through kern.clockrate (from man tick)
aisha@fwall ~ $ sysctl kern.clockrate
kern.clockrate=tick = 10000, hz = 100, profhz = 1000, stathz = 100
so presumably each tick is 1/10000 of a second (is this right?), and
things are getting scheduled in terms of ticks, so how is it even
possible to get nanosecond level accuracy there?
>From more looking around it seems like atleast x86 has TSC which
provides better resolution (presumably similar things exist for other
archs) but I don't see it being used anywhere here in an obvious
fashion. man pctr doesn't mention it being used for time measurement.