-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy patharray_spinlock.ml
32 lines (29 loc) · 953 Bytes
/
array_spinlock.ml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
type t = {
waiters : int Atomic.t array;
ticket : int Atomic.t;
owner : int ref;
mask : int;
size_exp : int;
}
let create ?(size_exp = 8) () =
let size = 1 lsl size_exp in
let waiters = Array.init size (fun _ -> Atomic.make (-1)) in
Atomic.set (Array.get waiters 0) 0;
let ticket = Atomic.make 0 in
let mask = size - 1 in
{ waiters; ticket; owner = ref 0; mask; size_exp }
let lock { waiters; ticket; owner; mask; size_exp } =
let my = Atomic.fetch_and_add ticket 1 in
let index = my land mask in
let round = my lsr size_exp in
let cell = Array.unsafe_get waiters index in
while Atomic.get cell != round do
Domain.cpu_relax ()
done;
owner := index
let unlock { waiters; owner; mask; _ } =
let index = (!owner + 1) land mask in
let round = Array.unsafe_get waiters index in
(* Need this to be atomic to force barrier. It'd be nice if
we could force it without doing an atomic. *)
Atomic.incr round