move migration counter reset to rendezvous interstice
OK, let's unpack that cryptic headline a little... When the seen set exceeds a certain capacity, it gets expanded. The new set is allocated by one thread and then all threads participate in the migration of the contents of the old set to the new one. To arbitrate which thread is operating on any particular chunk of the old set they use a shared counter, next_migration. Prior to this commit, the counter was reset immediately preceding a migration. Following this commit, we do the reset at the other end, after a migration. It should be clear that the reset has to happen some time (so the counter starts at zero the next time the set needs to be expanded) but it is valid to do it at either end. The motivation for moving it to the end, is that we can do it in a single-threaded context. This is during what I've referred to above as the "rendezvous interstice." All threads arrive at the post-migration rendezvous point and block on a condition variable. The last thread to arrive is designated the "leader" and allowed a window of single-threaded execution before unblocking all the "followers." By putting the reset in this window, we guarantee it gets done in a way that (a) will not affect any ongoing migrations and (b) will be observable by all other threads at the start of the next migration. "But why did it need to move?" I hear you ask. It was already in a location that was a single-threaded context enforced by the set expansion mutex. Well, we are about to introduce an optimisation based on double-checked locking that allows threads to observe a set expansion has already started without acquiring the set expansion mutex. That is, they will be able to enter set_migrate having never acquired the set expansion mutex. This means, if the counter reset was left where it was, they could start migration work before the counter had been reset. This could be resolved by moving the counter reset ahead of the write to next_global_seen (what the DCLP check looks at) and adding some memory barriers but it's simpler to just move the reset out of this path to a safer location altogether. Github: related to #104 "remove set_expand_lock?"
parent
022c3708
Please register or sign in to comment