Visa Hankala wrote (patch truncated):
> The kernel does not reschedule the timer when the user changes the
> timeout period. The new period will take effect only after the current
> period has expired. This is not explained in the manual page, though.
>
> With the recent kqueue changes, it is straightforward to make the kernel
> modify an existing timer. I think the clearest behaviour is to reset the
> timer completely when it is modified. If there are pending events, they
> should be cancelled because they do not necessarily correspond to the
> new settings.
>
> When f_modify and f_process are present in kqread_filtops, filt_timer
> is not used. filt_timerexpire() activates timer knotes directly using
> knote_activate() instead of KNOTE().
>
> However, the current behaviour has been around so long that one can
> argue that it is an actual feature. BSDs are not consistent with this,
> though. FreeBSD resets the timer immediately, whereas NetBSD and
> DragonFly BSD apply the new period after expiry.
>
> I guess the resetting is harmless in most cases but might wreak havoc
> at least with software that keeps poking its timers before expiry.
> ... PATCH TRUNCATED ...

Thank you very much for your response. I won't be of much help on this
tech mailing list as I've just started using OpenBSD as my daily OS.
Still, I tried to apply your patch yesterday but my issue is still there.
Maybe I did not apply it correctly? Or maybe I'm not understanding very
well how kqueue should work and I should revert to using EV_ONESHOT
when an EVFILT_TIMER is to be modified inside loop?

One other question (related) with modifying events inside main loop: If only ONE
monitored event is to be changed, it is NOT possible to ONLY register THAT ONE
event to the queue right?

For example:
.....
count=0;
TIMER1=201;
BATT1 = open("/dev/apm", O_RDONLY);

EV_SET(&ch[0], TIMER1, EVFILT_TIMER, EV_ADD | EV_ENABLE, 0, 5000, NULL);
EV_SET(&ch[1], BATT1, EVFILT_READ, EV_ADD | EV_ENABLE | EV_CLEAR, 0, 0, NULL);
kevent(kq, ch, 2, NULL, 0, NULL);

for (;;){
    nev = kevent(kq, NULL, 0, ev, 2, NULL);
    for (int i=0; i<nev;i++){
         if ( ev[i].ident == TIMER1 ){
             /* At one point, modify timer ONLY */
             if ( count%4==0 ) ch[0].data = 2500;
       } else if( ev[i].ident == BATT1 ) {
           printf( " Something happened on /dev/apm descriptor with code: %d\n",
                       APM_EVENT_TYPE( ev[i].data ) );
     }
     ...
     /* At the end, we MUST register the entire 'ch' array to the
kqueue right? */
    count++;
    kevent(kq, ch, 2, NULL, 0, NULL);
}
....

The issue with registering all the events again is that it seems to
reset also the
event in ch[1] even though nothing was changed. That behavior would not be
wanted right?

I came accross this issue when listening  on /dev/apm:
  --> you always get for the same very first event retrieved:
                  APM_EVENT_TYPE(ev[i].data) = 0
which according to source, is a NOT EVENT equivalent.
  --> After retrieving that first event, you should receive other events such as
POWER_CHANGE (and no more that very first one).

However, if using the example above, you will ONLY receive events of type
NO_EVENT as the monitored events seem to be reset with the last
example line (executed at every iteration), disregarding it it was modified or
not.

Any idea of how to solve both those issues (apart from using multiple kqueues
with threads)? Is there a way to only register changed events, leaving
the others
untouched? (I guess I would still have the same issues if using
libev / libevent / libuv, as the backend is kqueue right?)

Thank you very much

Reply via email to