To be precise, I am proposing to remove the functionality provided by ztimer_clock_t::adjust_set and ztimer_clock_t::adjust_sleep, I have not looked at ztimer_clock_t::adjust_clock_start, but it also might make since to remove.
I also propose to add some flavor of ztimer_set_absolute() (inspired by timer_set_absolute()), as a replacement solution to the problem, which the adjustment feature sought to solve. That is having timers fire too much later than expected. Callers anticipate some delay, but it should not be unbounded. Much of the latency of ztimer is that “now” is a moving target. If “now“ could be fixed at the time of call (example ztimer_set_absolute(ZTIMER_USEC, ztimer_now() + 100)), the delay could be accounted for in ztimer’s internals. Currently, all of the ztimer low level implementations only allow setting timers relative to now. This means that calculating a timer’s timeout time must deal with the fact that there is a finite difference between the time when a user calls ztimer_set() and the time the low level timer is set, and the time must be stable for the current adjustment feature to work well.
No in-tree board makes use of the ztimer_auto_adjust module. I don’t see CONFIG_ZTIMER_USEC_ADJUST_CLOCK_START used anywhere, and CONFIG_ZTIMER_USEC_ADJUST_CLOCK_START and CONFIG_ZTIMER_USEC_ADJUST_SLEEP are only used by a few boards.
The problem is that ztimer_periodic fails catastrophically if its callback fires early. It gets suck in its ISR chasing the next set point while repeatedly setting its internal timer with a value of 0. I suspect ztimer_periodic_wakeup() also would not tolerate an early wakeup. You could argue that the bug is in ztimer_periodic, however I bet I can find other ztimer users that also do not assume an early wakeup. I also bet that every application writer that makes use of ztimer, makes the assumptions that early callbacks won’t happen.
How does this early wakeup occur? There are two ways. One is through the use of theCONFIG_ZTIMER_ADJUST_* macros. If they are set and then forgotten, they may become overly aggressive and subtract too much time from timers, if ztimer (in all cases of ztimer use) or the scheduler’s (in the case of ztimer_sleep()) performance is improved. This is especially likely to happen to out-of-tree boards. The second way is as follows, and is the way I discovered this issue. I had the ztimer_auto_adjust module enabled. For reasons I don’t understand, it was setting the adjustment values to different values as my application’s code base changed. These changes should not have had any impact on the module which runs very early in the boot process. Further, I confirmed that regardless of the adjustment values determined at boot, calls to ztimer_periodic were firing 1 tick early sometimes. This implies that, after boot, sometimes the latency in setting timers was less than what ztimer_auto_adjust measured at boot.
Initially I sought to make ztimer_periodic more robust to handle early callbacks, but this turned out to be non-trivial, and only fixes the problem in this one place.