Duh: "remove()" is a POSIX symbol, and on at least some platforms
stdio.h can be included here out of platform headers causing a name
collision.
Fixes #10669's direct issue, though the broader issue of how to choose
names for statics remains controversial.
Signed-off-by: Andy Ross <andrew.j.ross@intel.com>
Our funny convention holds that passing ticks==1 to _add_timeout()
means "at the next tick". But that means that 1, 0, and all negative
numbers are expected to behave the same. In ticked mode, that's fine
because it will, after all, expire at the next tick.
But in tickless, the next announcement may be for several ticks, and
that zero will appear to expire "before" the next tick in the
consumption loop.
Make sure all "next tick" expirations look the same.
Signed-off-by: Andy Ross <andrew.j.ross@intel.com>
When fetching the next timeout to expire, the value is relative to the
last announced tick, so you subtract the timer-provided elapsed time
to get the true delta from "now". When adding a new timeout, you
*have* a value relative to now, so you compute the delta vs. the last
announced tick by adding the elapsed() time. Duh.
Signed-off-by: Andy Ross <andrew.j.ross@intel.com>
This was wrong in subtle ways. In tickless mode it's possible to get
an announcement for multiple ticks at a time and have multiple
callbacks to execute that were technically scheduled at different
times. We want to fix the current tick at the value represented by
the currently-executing callback's EXPIRATION (even if we missed it!),
so that any new timeouts it sets (c.f. a k_timer period) happen at the
right point, in phase with the expected series. In single-tick mode
the code ends up the same always, so the bug wasn't visible.
Signed-off-by: Andy Ross <andrew.j.ross@intel.com>
The previous comment correctly and carefully explained why the 64 bit
value in curr_tick doesn't require locking when reading only the low
32 bits.
It completely missed the fact that the calculation of elapsed time and
the read of curr_tick ABSOLUTELY DO require locking, because the
former is expressed in terms of the latter. This was always bug, even
in the old code, but never witnessed because we ran so little software
in tickless mode.
Signed-off-by: Andy Ross <andrew.j.ross@intel.com>
Now that the API has been fixed up, replace the existing timeout queue
with a much smaller version. The basic algorithm is unchanged:
timeouts are stored in a sorted dlist with each node nolding a delta
time from the previous node in the list; the announce call just walks
this list pulling off the heads as needed. Advantages:
* Properly spinlocked and SMP-aware. The earlier timer implementation
relied on only CPU 0 doing timeout work, and on an irq_lock() being
taken before entry (something that was violated in a few spots).
Now any CPU can wake up for an event (or all of them) and everything
works correctly.
* The *_thread_timeout() API is now expressible as a clean wrapping
(just one liners) around the lower-level interface based on function
pointer callbacks. As a result the timeout objects no longer need
to store backpointers to the thread and wait_q and have shrunk by
33%.
* MUCH smaller, to the tune of hundreds of lines of code removed.
* Future proof, in that all operations on the queue are now fronted by
just two entry points (_add_timeout() and z_clock_announce()) which
can easily be augmented with fancier data structures.
Signed-off-by: Andy Ross <andrew.j.ross@intel.com>