__wt_gen_drain() is supposed to wait for any thread holding onto an older generation of a given resource, however my understanding is that the following interleaving could happen:
Initial state: -------------- c->generations[which] = 5 session[0]->generations[which] = 0 session[1]->generations[which] = 0 Thread 1 (session 0) Thread 2 (session 1) ---------------------------- ---------------------------- __wt_session_gen_enter() sessions[1]->generations[which] = __wt_gen(session, which); (5) WRITE BARRIER sessions[1]->generations[which] == __wt_gen(session, which) (true) __wt_gen_next_drain() __wt_atomic_add(c->generations[which], 1) (6) __wt_gen_drain() read session_cnt (2) READ BARRIER session[0]->generations[which] (0) session[1]->generations[which] (0) all good, drain complete oops, we've got generation 5, thread 1 should have waited for us
In this case Thread 1 believes no-one holds onto a generation 5 resource, however Thread 2 still does.