We currently have false positives when using GCD barrier blocks with concurrent queues. The semantics of a submitted barrier block are:
- All previously submitted blocks are completely finished before the barrier block starts executing.
- The barrier block executed exclusively in the queue (as if the queue was serial for the duration of the block).
- All subsequently submitted blocks are only executed after the barrier block has completely finished.
TSan needs two more HB edges to cover these semantics: One edge from previous (regular) blocks to the barrier block and one edge from the barrier block to all subsequent (regular) blocks. Only applies to concurrent queues.
Shouldn't it be if (!queue_serial && !context->is_barrier_block). Because serial blocks and barriers blocks are already synchronized by other means.
It is very difficult to understand serial/concurrent/barrier/non-barrier synchronization now.
First observation is that serial queues are equivalent to concurrent queue with all blocks being barriers.
Second observation is that barrier/non-barrier blocks are equivalent to reader-writer mutexes with barriers being writers and non-barriers being readers.
Reader-writer synchronization is handled with 2 sync objects as:
This looks simpler than your new code. Please use it.