File: countdown.ml

package info (click to toggle)
ocaml-multicore-bench 0.1.7-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 320 kB
  • sloc: ml: 1,476; sh: 60; makefile: 6
file content (58 lines) | stat: -rw-r--r-- 1,966 bytes parent folder | download
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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
module Atomic = Multicore_magic.Transparent_atomic

type t = int Atomic.t array

let create ~n_domains () =
  if n_domains < 1 then invalid_arg "n_domains < 1";
  let ceil_pow_2_minus_1 n =
    let open Nativeint in
    let n = of_int n in
    let n = logor n (shift_right_logical n 1) in
    let n = logor n (shift_right_logical n 2) in
    let n = logor n (shift_right_logical n 4) in
    let n = logor n (shift_right_logical n 8) in
    let n = logor n (shift_right_logical n 16) in
    to_int (if Sys.int_size > 32 then logor n (shift_right_logical n 32) else n)
  in
  let n = ceil_pow_2_minus_1 n_domains in
  let atomics = Array.init n_domains (fun _ -> Atomic.make_contended 0) in
  Array.init n @@ fun i -> Array.unsafe_get atomics (i mod n_domains)

let rec arity t i =
  if i < Array.length t && Array.unsafe_get t i != Array.unsafe_get t 0 then
    arity t (i + 1)
  else i

let[@inline] arity t = arity t 1

let non_atomic_set t count =
  if count < 0 then invalid_arg "count < 0";
  let n = arity t in
  let d = count / n in
  let j = count - (n * d) in
  for i = 0 to n - 1 do
    Atomic.set (Array.unsafe_get t i) (d + Bool.to_int (i < j))
  done

let rec get t count i =
  if i < Array.length t && Array.unsafe_get t i != Array.unsafe_get t 0 then
    get t (count + Int_ext.max 0 (Atomic.get (Array.unsafe_get t i))) (i + 1)
  else count

let[@inline] get t = get t (Int_ext.max 0 (Atomic.get (Array.unsafe_get t 0))) 1

let rec alloc t ~batch i =
  if i < Array.length t then
    let c = Array.unsafe_get t i in
    if 0 < Atomic.get c then
      let n = Atomic.fetch_and_add c (-batch) in
      if 0 < n then Int_ext.min n batch else alloc t ~batch (i + 1)
    else alloc t ~batch (i + 1)
  else 0

let[@inline] alloc t ~domain_index ~batch =
  let c = Array.unsafe_get t domain_index in
  if 0 < Atomic.get c then
    let n = Atomic.fetch_and_add c (-batch) in
    if 0 < n then Int_ext.min n batch else alloc t ~batch 0
  else alloc t ~batch 0