the system maintains a global counter called an epoch which increments over time. Threads track which epoch they have observed for a given object, and when all threads have sufficiently progressed, copies of the object from older epochs can be freed (as no threads can possibly be referencing them anymore). You can think of the epoch as a kind of “version number” for an object.
This is very much like the way the LMDB database manages pages, with its “epoch” being a transaction count. I implemented this algorithm in an experimental database a few years ago.
This is a good writeup, but I’m a bit surprised at it being described as “This is the craziest kernel bug I have ever reported”. The cause is very simple (nonatomic write where an atomic write was needed), it’s hard to trigger, even harder to exploit.
This is very much like the way the LMDB database manages pages, with its “epoch” being a transaction count. I implemented this algorithm in an experimental database a few years ago.
This is also basically how MVCC works.
You can see more details about the four state process here in libdispatch:
https://github.com/swiftlang/swift-corelibs-libdispatch/blob/58fc9c59a7e0be92696850dd2fb9bd539bbc2de4/src/shims/lock.h#L458-L612
This is a good writeup, but I’m a bit surprised at it being described as “This is the craziest kernel bug I have ever reported”. The cause is very simple (nonatomic write where an atomic write was needed), it’s hard to trigger, even harder to exploit.