Current callout API complications ================================= o The callout_stop() function will not stop a callout that has been de-queued by softclock() but not yet run. It returns an integer to indicate whether it successfully cancelled the callout. The callout handler may in fact run after callout_stop() returns, so it is not safe to deallocate any resources that the handler may access. callout_stop() does not sleep. o The callout_drain() function guarantees that the callout handler will not run after callout_drain() has returned. However, the handler may be invoked during the operation of callout_drain(). callout_drain() may sleep, so it is not appropriate to call it from certain contexts such as interrupt service routines, or where a mutex is held. o When callout_reset() is used, it is possible that the old callout handler will be invoked soon afterwards because the previous timeout period expired before callout_reset() could stop it. The old handler could also stop the timer or reset it with a different timeout or handler. o There is a method for avoiding many of the inherent race conditions using the extra macros callout_pending(), callout_active() and callout_deactivete(). These cannout prevent the callout handler from running, but their use allows the handler to return without action if the timeout had been cancelled or reset since softclock() de-queued the callout. All the above complications are present whether or not the callout is marked as MP-safe. Note that even before SMPng it was possible for an ISR to run immediately after softclock() de-queued the timeout, so the complexity is not entirely new. However, prior to SMPng, code that executed in a process context and used spl protection was immune to these effects because softclock() cannot start while the cpl is raised to most usual levels. It is likely that a significant number of the new timeout races that were introded with SMPng have not yet been fixed.