Skip to content

Commit c417954

Browse files
committed
Verify is only needed when a CMP is followed by a CAS
1 parent 0413e9b commit c417954

File tree

1 file changed

+15
-8
lines changed

1 file changed

+15
-8
lines changed

src/kcas/kcas.ml

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ let make_loc state id = { state = Atomic.make state; id } [@@inline]
106106
*)
107107

108108
let is_cmp casn state = state.casn != casn [@@inline]
109+
let is_cas casn state = state.casn == casn [@@inline]
109110

110111
module Mode = struct
111112
type t = determined
@@ -163,10 +164,9 @@ let finish casn (`Undetermined cass as undetermined) (status : determined) =
163164
then release casn cass status
164165
else fenceless_get casn == `After
165166

166-
let a_cas = 1
167-
and a_cmp = 2
168-
169-
let a_cas_and_a_cmp = a_cas lor a_cmp
167+
let a_cmp = 1
168+
let a_cas = 2
169+
let a_cmp_followed_by_a_cas = 4
170170

171171
let rec determine casn status = function
172172
| NIL -> status
@@ -176,7 +176,11 @@ let rec determine casn status = function
176176
else
177177
let current = Atomic.get (as_atomic loc) in
178178
if state == current then
179-
determine casn (status lor (1 + Bool.to_int (is_cmp casn state))) gt
179+
let a_cas_or_a_cmp = 1 + Bool.to_int (is_cas casn state) in
180+
let a_cmp_followed_by_a_cas = a_cas_or_a_cmp * 2 land (status * 4) in
181+
determine casn
182+
(status lor a_cas_or_a_cmp lor a_cmp_followed_by_a_cas)
183+
gt
180184
else
181185
let matches_expected () =
182186
let expected = state.before in
@@ -204,7 +208,10 @@ let rec determine casn status = function
204208
| [] -> ()
205209
| awaiters -> record.awaiters <- awaiters);
206210
if Atomic.compare_and_set (as_atomic loc) current state then
207-
determine casn (status lor a_cas) gt
211+
let a_cmp_followed_by_a_cas = a_cas * 2 land (status * 4) in
212+
determine casn
213+
(status lor a_cas lor a_cmp_followed_by_a_cas)
214+
gt
208215
else determine casn status eq
209216
| #determined -> raise Exit
210217
else -1
@@ -215,7 +222,7 @@ and is_after casn =
215222
match determine casn 0 cass with
216223
| status ->
217224
finish casn undetermined
218-
(if a_cas_and_a_cmp = status then verify casn cass
225+
(if a_cmp_followed_by_a_cas < status then verify casn cass
219226
else if 0 <= status then `After
220227
else `Before)
221228
| exception Exit -> fenceless_get casn == `After)
@@ -229,7 +236,7 @@ let determine_for_owner casn cass =
229236
fenceless_set casn undetermined;
230237
match determine casn 0 cass with
231238
| status ->
232-
if a_cas_and_a_cmp = status then
239+
if a_cmp_followed_by_a_cas < status then
233240
(* We only want to [raise Interference] in case it is the verify step
234241
that fails. The idea is that in [lock_free] mode the attempt might
235242
have succeeded as the compared locations would have been set in

0 commit comments

Comments
 (0)