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