|
| 1 | +(* TEST |
| 2 | + runtime5; |
| 3 | + { bytecode; } |
| 4 | + { native; } |
| 5 | +*) |
| 6 | + |
| 7 | +type t = { |
| 8 | + sender: int; |
| 9 | + code: int; |
| 10 | + msgsize: int; |
| 11 | + message: int array; |
| 12 | +} |
| 13 | + |
| 14 | +let size = 20_000 |
| 15 | +let table = Array.init size (fun _ -> Atomic.make None) |
| 16 | +let go = Atomic.make true |
| 17 | +let log = false |
| 18 | + |
| 19 | +let run me msgsize iters = |
| 20 | + (* domain 0 keeps a bunch of extra local data, |
| 21 | + to unbalance sweeping loads *) |
| 22 | + let kept = ref [] in |
| 23 | + if me = 0 then kept := [Array.init 10000 ref]; |
| 24 | + let count = ref iters in |
| 25 | + let from0 = ref 0 in |
| 26 | + while !count > 0 && Atomic.get go do |
| 27 | + ignore (Sys.opaque_identity (ref [])); |
| 28 | + let slot = Random.int size in |
| 29 | + match Atomic.get table.(slot) with |
| 30 | + | None as prev -> |
| 31 | + let code = Random.bits () in |
| 32 | + let msg = {sender = me; code; msgsize; message = Array.make msgsize code} in |
| 33 | + if me = 0 then kept := Array.init 5 ref :: !kept; |
| 34 | + (* pointless string formatting to create minor garbage *) |
| 35 | + let dbg = |
| 36 | + Printf.sprintf "[%d]: %03d: %d %08x --->\n" me slot msg.msgsize msg.code in |
| 37 | + if Sys.opaque_identity log then print_string dbg; |
| 38 | + if Atomic.compare_and_set table.(slot) prev (Some msg) then |
| 39 | + decr count |
| 40 | + | Some msg as prev when |
| 41 | + msg.sender <> me && |
| 42 | + Atomic.compare_and_set table.(slot) prev None -> |
| 43 | + |
| 44 | + let dbg = Printf.sprintf "[%d]: ---> %03d: %d %08x\n" me slot msg.msgsize msg.code in |
| 45 | + if Sys.opaque_identity log then print_string dbg; |
| 46 | + assert (Array.length msg.message = msg.msgsize); |
| 47 | + for i = 0 to msg.msgsize - 1 do |
| 48 | + assert (msg.message.(i) = msg.code) |
| 49 | + done; |
| 50 | + if msg.sender = 0 then incr from0; |
| 51 | + | Some _ -> () |
| 52 | + done; |
| 53 | + ignore (Sys.opaque_identity !kept); |
| 54 | + !from0 |
| 55 | + |
| 56 | +let () = |
| 57 | + let iters = 200_000 in |
| 58 | + let d1 = Domain.spawn (fun () -> run 1 100 max_int) in |
| 59 | + let d2 = Domain.spawn (fun () -> run 2 5 max_int) in |
| 60 | + let recv_local = run 0 20 iters in |
| 61 | + assert (recv_local = 0); |
| 62 | + Atomic.set go false; |
| 63 | + let r = Domain.join d1 + Domain.join d2 in |
| 64 | + let remaining = |
| 65 | + table |
| 66 | + |> Array.to_list |
| 67 | + |> List.filter (fun x -> match Atomic.get x with Some {sender=0; _} -> true | _ -> false) |
| 68 | + |> List.length in |
| 69 | + Printf.printf "%d\n" (r+remaining) |
0 commit comments