Re: EVFILT_TIMER add support for different timer precisions NOTE_{,U,N,M}SECONDS

2023-08-08 Thread Claudio Jeker
On Tue, Aug 08, 2023 at 10:40:06AM -0500, Scott Cheloha wrote:
> On Sat, Aug 05, 2023 at 01:33:05AM -0400, A Tammy wrote:
> > 
> > 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=165715874509440=2
> 
> If nothing in ports is using this I am squeamish about adding it.
> Once we add it, we're stuck maintaining it, warts and all.
> 
> If www/workflow were in the tree I could see the upside.  Is it in
> ports?
> 
> It looks like workflow actually wants timerfd(2) from Linux and is
> simulating timerfd(2) with EVFILT_TIMER and NOTE_NSECONDS:
> 
> https://github.com/sogou/workflow/blob/80b3dfbad2264bcd79ba37811c66421490e337d2/src/kernel/poller.c#L227
> 
> I think timerfd(2) is the superior interface here.  It keeps the POSIX
> interval timer semantics without all the signal delivery baggage.  It
> also supports multiple clocks and starting a periodic timeout from an
> absolute starting time.
> 
> So, if the goal is "add www/workflow to ports", adding timerfd(2) might
> be the right thing.

I don't think that this is a good move. Adding timerfd(2) will result in
the need to add all those magic fd interfaces linux invents on a weekly
basis. I would not go down that rabbit-hole unless there is realy realy no
alternative.

-- 
:wq Claudio



Re: EVFILT_TIMER add support for different timer precisions NOTE_{,U,N,M}SECONDS

2023-08-08 Thread Scott Cheloha
On Sat, Aug 05, 2023 at 01:33:05AM -0400, A Tammy wrote:
> 
> 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=165715874509440=2

If nothing in ports is using this I am squeamish about adding it.
Once we add it, we're stuck maintaining it, warts and all.

If www/workflow were in the tree I could see the upside.  Is it in
ports?

It looks like workflow actually wants timerfd(2) from Linux and is
simulating timerfd(2) with EVFILT_TIMER and NOTE_NSECONDS:

https://github.com/sogou/workflow/blob/80b3dfbad2264bcd79ba37811c66421490e337d2/src/kernel/poller.c#L227

I think timerfd(2) is the superior interface here.  It keeps the POSIX
interval timer semantics without all the signal delivery baggage.  It
also supports multiple clocks and starting a periodic timeout from an
absolute starting time.

So, if the goal is "add www/workflow to ports", adding timerfd(2) might
be the right thing.

> 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.

Well, if we're going to add it (if), we should add all of it.  The
vast majority of the code is not conversion code: if we add support
for NOTE_NSECONDS, adding support for the other units is trivial, and
there is value in being fully compatible with other implementations.

> > 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();
> >>> - /* Remove extra tick from tvtohz() if timeout has fired before. */
> >>> + if (kn->kn_sfflags & NOTE_ABSTIME) {
> >>> + nanotime();
> >>> + if (timespeccmp(ts, , >)) {
> >>> + timespecsub(ts, , );
> >>> + /* XXX timeout_at_ts */
> >>> + timeout_add(to, tstohz());
> > 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 

Re: EVFILT_TIMER add support for different timer precisions NOTE_{,U,N,M}SECONDS

2023-08-04 Thread A Tammy


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=165715874509440=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();
>>> -   /* Remove extra tick from tvtohz() if timeout has fired before. */
>>> +   if (kn->kn_sfflags & NOTE_ABSTIME) {
>>> +   nanotime();
>>> +   if (timespeccmp(ts, , >)) {
>>> +   timespecsub(ts, , );
>>> +   /* XXX timeout_at_ts */
>>> +   timeout_add(to, tstohz());
> 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 = 1, hz = 100, profhz = 1000, stathz = 100

so presumably each tick is 1/1 of a second (is this right?), and
things are getting scheduled in terms of ticks, so how is it even
possible 

Re: EVFILT_TIMER add support for different timer precisions NOTE_{,U,N,M}SECONDS

2023-08-04 Thread Scott Cheloha
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.

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.

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();
> > -   /* Remove extra tick from tvtohz() if timeout has fired before. */
> > +   if (kn->kn_sfflags & NOTE_ABSTIME) {
> > +   nanotime();
> > +   if (timespeccmp(ts, , >)) {
> > +   timespecsub(ts, , );
> > +   /* XXX timeout_at_ts */
> > +   timeout_add(to, tstohz());

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.



Re: EVFILT_TIMER add support for different timer precisions NOTE_{,U,N,M}SECONDS

2023-08-04 Thread aisha
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.

OK aisha@

I had an unrelated question inlined.

> Index: lib/libc/sys/kqueue.2
> ===
> RCS file: src/lib/libc/sys/kqueue.2,v
> retrieving revision 1.46
> diff -u -p -r1.46 kqueue.2
> --- lib/libc/sys/kqueue.2 31 Mar 2022 17:27:16 -  1.46
> +++ lib/libc/sys/kqueue.2 10 Sep 2022 13:01:36 -
> @@ -457,17 +457,71 @@ Establishes an arbitrary timer identifie
>  .Fa ident .
>  When adding a timer,
>  .Fa data
> -specifies the timeout period in milliseconds.
> -The timer will be periodic unless
> +specifies the timeout period in units described below, or, if
> +.Dv NOTE_ABSTIME
> +is set in
> +.Va fflags ,
> +specifies the absolute time at which the timer should fire.
> +The timer will repeat unless
>  .Dv EV_ONESHOT
> -is specified.
> +is set in
> +.Va flags
> +or
> +.Dv NOTE_ABSTIME
> +is set in
> +.Va fflags .
>  On return,
>  .Fa data
>  contains the number of times the timeout has expired since the last call to
>  .Fn kevent .
> -This filter automatically sets the
> +This filter automatically sets
>  .Dv EV_CLEAR
> -flag internally.
> +in
> +.Va flags
> +for periodic timers.
> +Timers created with
> +.Dv NOTE_ABSTIME
> +remain activated on the kqueue once the absolute time has passed unless
> +.Dv EV_CLEAR
> +or
> +.Dv EV_ONESHOT
> +are also specified.
> +.Pp
> +The filter accepts the following flags in the
> +.Va fflags
> +argument:
> +.Bl -tag -width NOTE_MSECONDS
> +.It Dv NOTE_SECONDS
> +The timer value in
> +.Va data
> +is expressed in seconds.
> +.It Dv NOTE_MSECONDS
> +The timer value in
> +.Va data
> +is expressed in milliseconds.
> +.It Dv NOTE_USECONDS
> +The timer value in
> +.Va data
> +is expressed in microseconds.
> +.It Dv NOTE_NSECONDS
> +The timer value in
> +.Va data
> +is expressed in nanoseconds.
> +.It Dv NOTE_ABSTIME
> +The timer value is an absolute time with
> +.Dv CLOCK_REALTIME
> +as the reference clock.
> +.El
> +.Pp
> +Note that
> +.Dv NOTE_SECONDS ,
> +.Dv NOTE_MSECONDS ,
> +.Dv NOTE_USECONDS ,
> +and
> +.Dv NOTE_NSECONDS
> +are mutually exclusive; behavior is undefined if more than one are specified.
> +If a timer value unit is not specified, the default is
> +.Dv NOTE_MSECONDS .
>  .Pp
>  If an existing timer is re-added, the existing timer and related pending 
> events
>  will be cancelled.
> @@ -557,6 +611,7 @@ No memory was available to register the 
>  The specified process to attach to does not exist.
>  .El
>  .Sh SEE ALSO
> +.Xr clock_gettime 2 ,
>  .Xr poll 2 ,
>  .Xr read 2 ,
>  .Xr select 2 ,
> Index: regress/sys/kern/kqueue/kqueue-timer.c
> ===
> RCS file: src/regress/sys/kern/kqueue/kqueue-timer.c,v
> retrieving revision 1.4
> diff -u -p -r1.4 kqueue-timer.c
> --- regress/sys/kern/kqueue/kqueue-timer.c12 Jun 2021 13:30:14 -  
> 1.4
> +++ regress/sys/kern/kqueue/kqueue-timer.c10 Sep 2022 13:01:37 -
> @@ -22,6 +22,7 @@
>  #include 
>  #include 
>  #include 
> +#include 
>  #include 
>  #include 
>  #include 
> @@ -31,9 +32,13 @@
>  int
>  do_timer(void)
>  {
> - int kq, n;
> + static const int units[] = {
> + NOTE_SECONDS, NOTE_MSECONDS, NOTE_USECONDS, NOTE_NSECONDS
> + };
>   struct kevent ev;
> - struct timespec ts;
> + struct timespec ts, start, end, now;
> + int64_t usecs;
> + int i, kq, n;
>  
>   ASS((kq = kqueue()) >= 0,
>   warn("kqueue"));
> @@ -68,6 

Re: EVFILT_TIMER add support for different timer precisions NOTE_{,U,N,M}SECONDS

2022-09-10 Thread Visa Hankala
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.

Index: lib/libc/sys/kqueue.2
===
RCS file: src/lib/libc/sys/kqueue.2,v
retrieving revision 1.46
diff -u -p -r1.46 kqueue.2
--- lib/libc/sys/kqueue.2   31 Mar 2022 17:27:16 -  1.46
+++ lib/libc/sys/kqueue.2   10 Sep 2022 13:01:36 -
@@ -457,17 +457,71 @@ Establishes an arbitrary timer identifie
 .Fa ident .
 When adding a timer,
 .Fa data
-specifies the timeout period in milliseconds.
-The timer will be periodic unless
+specifies the timeout period in units described below, or, if
+.Dv NOTE_ABSTIME
+is set in
+.Va fflags ,
+specifies the absolute time at which the timer should fire.
+The timer will repeat unless
 .Dv EV_ONESHOT
-is specified.
+is set in
+.Va flags
+or
+.Dv NOTE_ABSTIME
+is set in
+.Va fflags .
 On return,
 .Fa data
 contains the number of times the timeout has expired since the last call to
 .Fn kevent .
-This filter automatically sets the
+This filter automatically sets
 .Dv EV_CLEAR
-flag internally.
+in
+.Va flags
+for periodic timers.
+Timers created with
+.Dv NOTE_ABSTIME
+remain activated on the kqueue once the absolute time has passed unless
+.Dv EV_CLEAR
+or
+.Dv EV_ONESHOT
+are also specified.
+.Pp
+The filter accepts the following flags in the
+.Va fflags
+argument:
+.Bl -tag -width NOTE_MSECONDS
+.It Dv NOTE_SECONDS
+The timer value in
+.Va data
+is expressed in seconds.
+.It Dv NOTE_MSECONDS
+The timer value in
+.Va data
+is expressed in milliseconds.
+.It Dv NOTE_USECONDS
+The timer value in
+.Va data
+is expressed in microseconds.
+.It Dv NOTE_NSECONDS
+The timer value in
+.Va data
+is expressed in nanoseconds.
+.It Dv NOTE_ABSTIME
+The timer value is an absolute time with
+.Dv CLOCK_REALTIME
+as the reference clock.
+.El
+.Pp
+Note that
+.Dv NOTE_SECONDS ,
+.Dv NOTE_MSECONDS ,
+.Dv NOTE_USECONDS ,
+and
+.Dv NOTE_NSECONDS
+are mutually exclusive; behavior is undefined if more than one are specified.
+If a timer value unit is not specified, the default is
+.Dv NOTE_MSECONDS .
 .Pp
 If an existing timer is re-added, the existing timer and related pending events
 will be cancelled.
@@ -557,6 +611,7 @@ No memory was available to register the 
 The specified process to attach to does not exist.
 .El
 .Sh SEE ALSO
+.Xr clock_gettime 2 ,
 .Xr poll 2 ,
 .Xr read 2 ,
 .Xr select 2 ,
Index: regress/sys/kern/kqueue/kqueue-timer.c
===
RCS file: src/regress/sys/kern/kqueue/kqueue-timer.c,v
retrieving revision 1.4
diff -u -p -r1.4 kqueue-timer.c
--- regress/sys/kern/kqueue/kqueue-timer.c  12 Jun 2021 13:30:14 -  
1.4
+++ regress/sys/kern/kqueue/kqueue-timer.c  10 Sep 2022 13:01:37 -
@@ -22,6 +22,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -31,9 +32,13 @@
 int
 do_timer(void)
 {
-   int kq, n;
+   static const int units[] = {
+   NOTE_SECONDS, NOTE_MSECONDS, NOTE_USECONDS, NOTE_NSECONDS
+   };
struct kevent ev;
-   struct timespec ts;
+   struct timespec ts, start, end, now;
+   int64_t usecs;
+   int i, kq, n;
 
ASS((kq = kqueue()) >= 0,
warn("kqueue"));
@@ -68,6 +73,125 @@ do_timer(void)
n = kevent(kq, NULL, 0, , 1, );
ASSX(n == 1);
 
+   /* Test with different time units */
+
+   for (i = 0; i < sizeof(units) / sizeof(units[0]); i++) {
+   memset(, 0, sizeof(ev));
+   ev.filter = EVFILT_TIMER;
+   ev.flags = EV_ADD | EV_ENABLE;
+   ev.fflags = units[i];
+   ev.data = 1;
+
+   n = kevent(kq, , 1, NULL, 0, NULL);
+   ASSX(n != -1);
+
+