Skip to content

Commit 34ddbe7

Browse files
committed
Complete redesign of the kcas library API
1 parent 44939c1 commit 34ddbe7

18 files changed

+870
-322
lines changed

LICENSE.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
Copyright (c) 2016, KC Sivaramakrishnan <kc@kcsrk.info>
22
Copyright (c) 2017, Nicolas ASSOUAD <nicolas.assouad@ens.fr>
33
Copyright (c) 2018, Sadiq Jaffer
4+
Copyright (c) 2023, Vesa Karvonen <vesa.a.j.k@gmail.com>
45

56
Permission to use, copy, modify, and/or distribute this software for any
67
purpose with or without fee is hereby granted, provided that the above

src/backoff.ml

Lines changed: 32 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
* Copyright (c) 2015, Théo Laurent <theo.laurent@ens.fr>
33
* Copyright (c) 2015, KC Sivaramakrishnan <sk826@cl.cam.ac.uk>
44
* Copyright (c) 2021, Sudha Parimala <sudharg247@gmail.com>
5+
* Copyright (c) 2023, Vesa Karvonen <vesa.a.j.k@gmail.com>
56
*
67
* Permission to use, copy, modify, and/or distribute this software for any
78
* purpose with or without fee is hereby granted, provided that the above
@@ -16,28 +17,39 @@
1617
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1718
*)
1819

19-
module type S = sig
20-
type t
20+
type t = int
2121

22-
val create : ?max:int -> unit -> t
23-
val once : t -> unit
24-
val reset : t -> unit
25-
end
22+
let bits = 5
23+
let max_wait_log = 30 (* [Random.bits] returns 30 random bits. *)
24+
let mask = (1 lsl bits) - 1
2625

27-
module M : S = struct
28-
type t = int * int ref
26+
let create ?(lower_wait_log = 4) ?(upper_wait_log = 17) () =
27+
assert (
28+
0 <= lower_wait_log
29+
&& lower_wait_log <= upper_wait_log
30+
&& upper_wait_log <= max_wait_log);
31+
(upper_wait_log lsl (bits * 2))
32+
lor (lower_wait_log lsl bits) lor lower_wait_log
2933

30-
let _ = Random.self_init ()
31-
let create ?(max = 32) () = (max, ref 1)
34+
let get_upper_wait_log backoff = backoff lsr (bits * 2)
35+
let get_lower_wait_log backoff = (backoff lsr bits) land mask
36+
let get_wait_log backoff = backoff land mask
3237

33-
let once (maxv, r) =
34-
let t = Random.int !r in
35-
r := min (2 * !r) maxv;
36-
if t = 0 then ()
37-
else
38-
for _ = 1 to 2048 * t do
39-
Domain.cpu_relax ()
40-
done
38+
let reset backoff =
39+
let lower_wait_log = get_lower_wait_log backoff in
40+
backoff land lnot mask lor lower_wait_log
4141

42-
let reset (_, r) = r := 1
43-
end
42+
let k = Domain.DLS.new_key Random.State.make_self_init
43+
44+
let once backoff =
45+
let wait_log = get_wait_log backoff in
46+
let wait_mask = (1 lsl wait_log) - 1 in
47+
let t = Random.State.bits (Domain.DLS.get k) land wait_mask in
48+
for _ = 0 to t do
49+
Domain.cpu_relax ()
50+
done;
51+
let upper_wait_log = get_upper_wait_log backoff in
52+
let next_wait_log = Int.min upper_wait_log (wait_log + 1) in
53+
backoff lxor wait_log lor next_wait_log
54+
55+
let default = create ()

src/backoff.mli

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
(*
22
* Copyright (c) 2015, Théo Laurent <theo.laurent@ens.fr>
33
* Copyright (c) 2015, KC Sivaramakrishnan <sk826@cl.cam.ac.uk>
4+
* Copyright (c) 2023, Vesa Karvonen <vesa.a.j.k@gmail.com>
45
*
56
* Permission to use, copy, modify, and/or distribute this software for any
67
* purpose with or without fee is hereby granted, provided that the above
@@ -15,12 +16,29 @@
1516
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1617
*)
1718

18-
module type S = sig
19-
type t
19+
type t
20+
(** Type of backoff values. *)
2021

21-
val create : ?max:int -> unit -> t
22-
val once : t -> unit
23-
val reset : t -> unit
24-
end
22+
val max_wait_log : int
23+
(** Logarithm of the maximum allowed value for wait. *)
2524

26-
module M : S
25+
val create : ?lower_wait_log:int -> ?upper_wait_log:int -> unit -> t
26+
(** [create] creates a backoff value. [upper_wait_log], [lower_wait_log]
27+
override the logarithmic upper and lower bound on the number of spins
28+
executed by {!once}. *)
29+
30+
val default : t
31+
(** [default] is equivalent to [create ()]. *)
32+
33+
val once : t -> t
34+
(** [once b] executes one wait and returns a new backoff with logarithm of the
35+
current maximum value incremented unless it is already at [upper_wait_log]
36+
of [b]. *)
37+
38+
val reset : t -> t
39+
(** [reset b] returns a backoff equivalent to [b] except with current value set
40+
to the [lower_wait_log] of [b]. *)
41+
42+
val get_wait_log : t -> int
43+
(** [get_wait_log b] returns logarithm of the maximum value of wait for next
44+
{!once}. *)

0 commit comments

Comments
 (0)