1 -------------------------------------------------------------------------------
2 Release sequence support:
3 -------------------------------------------------------------------------------
5 *******************************
6 From the C++11 specification
7 *******************************
11 A release sequence from a release operation A on an atomic object M is a
12 maximal contiguous sub-sequence of side effects in the modification order of
13 M, where the first operation is A, and every subsequent operation
15 - is performed by the same thread that performed A, or
16 - is an atomic read-modify-write operation.
20 An atomic operation A that performs a release operation on an atomic object M
21 synchronizes with an atomic operation B that performs an acquire operation on
22 M and takes its value from any side effect in the release sequence headed by
25 *******************************
27 *******************************
29 The specification allows for a single acquire to synchronize with more than
30 one release operation, as its "reads from" value might be part of more than
33 *******************************
35 *******************************
37 Check read-write chain...
43 * rf is NULL: return uncertain
46 add rf to release heads
48 return certain [note: we don't need to extend release sequence
49 further because this acquire will have synchronized already]
51 return (recursively) "get release sequence head of rf"
53 add rf to release heads
55 * else, rf is relaxed write (NOT RMW)
58 *******************************
60 *******************************
62 let release = max{act in S | samethread(act, rf) && isrelease(act) && act <= rf}
63 let t = thread(rf) // == thread(release)
64 for all threads t_j != t
65 if exists c in S | c !--mo--> release, rf !--mo--> c, c is write, thread(c) == t_j then
67 [ note: need to check "future ordered" condition ]
68 add release to release heads
71 *******************************
73 *******************************
75 1. process action, find read_from
76 2. add initial mo_graph edges
77 3. assign read_from, calc initial "get_release_seq_heads()"
78 4. perform synchronization with all release heads
80 synchronization => check for new mo_graph edges
81 => check for resolved release sequences
82 => check for failed promises
83 mo_graph edges => check for resolved release sequences
85 *******************************
87 *******************************
89 "cannot determine" means we need to lazily check conditions in the future
90 - check when future writes satisfy "promises"
92 Read from future? We require that all release heads are "in the past", so that
93 we don't form synchronization against the ordering of the program trace. We
94 ensure that some execution is explored in which they are ordered the other way,
95 so we declare this execution "infeasible."
97 => If we *do* establish a synchronization after the fact:
98 - need to recurse through the execution trace and update clock vectors