This work is from Jonathan T. Looney from the FreeBSD project (jtl@). The return value of ck_epoch_poll has also changed. It returns false only if the epoch counter has not progressed, if no memory was reclaimed (in other words, no forward progress) and / or not all threads have been observed in a quiescent state (grace period). Below are his notes: Epoch calls are stored in a 4-bucket hash table. The 4-bucket hash table allows for calls to be stored for three epochs: the current epoch and two previous ones. The comments at the beginning of ck_epoch.c explain why this is necessary. When there are active threads, ck_epoch_poll_deferred() current runs the epoch calls for the current global epoch + 1. Because of modulo arithmetic, this is equivalent to running the calls for epoch - 3. However, this means that ck_epoch_poll_deferred() is waiting unnecessarily long to run epoch calls. Further, there could be races in incrementing the global epoch. Imagine all active threads have observed epoch n. CPU 0 sees this. It increments the global epoch to (n + 1). It runs the epoch calls for (n - 3). Now, CPU 1 checks. It sees that there are active threads which have not yet observed the new global epoch (n + 1). In this case, ck_epoch_poll_deferred() will return without running any epochs. In the worst case (CPU 1 continually losing the race), these epoch calls could be deferred indefinitely. To fix this, always run any epoch calls for global epoch - 2. Further, if all active threads have observed the global epoch, run epoch calls for global epoch - 1. The global epoch is only incremented when all active threads have observed it. Therefore, all active threads must always have observed global epoch - 1 or the current global epoch. Accordingly, it is safe to always run epoch calls for global epoch - 2. Further, if all active threads have observed the global epoch, it is safe to run epoch calls for global epoch - 1.awsm
parent
dbfe282866
commit
dac27da321
Loading…
Reference in new issue