kernel - Fix callout race and panic (2)
authorMatthew Dillon <dillon@apollo.backplane.com>
Tue, 22 Aug 2017 16:26:27 +0000 (09:26 -0700)
committerMatthew Dillon <dillon@apollo.backplane.com>
Tue, 22 Aug 2017 16:26:27 +0000 (09:26 -0700)
commit7b045ca837e37d7065b8971267d2c95362cd6276
tree55ea30561128d0e529e9746144f54cbbd1da4c39
parentf079a0a8bb6139863788e815c5d46221817e16e3
kernel - Fix callout race and panic (2)

* Previous fix couldn't handle a callout_stop() vs callout_reset() race
  on different cpus.  When this race occurred, the callout_stop() would
  get stuck waiting for the ARMED bit to clear, which it never would
  because a new callout_reset() re-armed it.

* Refactor the callout code to clean it up.  Remove the ARMED flag, instead
  a callout is considered ARMED if the IPI_MASK counter bits are not zero
  or PENDING is set.  Use these rules to lock-in the owning cpu with an
  atomic op

* Integrate all flags settings in IPIs with the atomic decrement of the
  IPI_MASK count, rather than as separate operations.

* callout_stop() now just waits for the IPI sequence to end.  callout_reset()
  now re-tests whether the callout is still armed or not after callout_stop()
  returns (since it needs to know for sure) before it tries to take over
  the callout.  This fixes the race.
sys/kern/kern_timeout.c
sys/sys/callout.h