summaryrefslogtreecommitdiff
path: root/testsuite/tests/lib-systhreads/testyield.ml
diff options
context:
space:
mode:
Diffstat (limited to 'testsuite/tests/lib-systhreads/testyield.ml')
-rw-r--r--testsuite/tests/lib-systhreads/testyield.ml51
1 files changed, 51 insertions, 0 deletions
diff --git a/testsuite/tests/lib-systhreads/testyield.ml b/testsuite/tests/lib-systhreads/testyield.ml
new file mode 100644
index 0000000000..30e70ce946
--- /dev/null
+++ b/testsuite/tests/lib-systhreads/testyield.ml
@@ -0,0 +1,51 @@
+(* TEST
+ (* Test that yielding between busy threads reliably triggers a thread
+ switch. *)
+ include systhreads
+ * not-windows
+ ** bytecode
+ ** native
+*)
+
+let threads = 4
+
+let are_ready = ref 0
+
+let yields = ref 0
+
+let iters = 50000
+
+let last = ref (-1)
+
+let report thread run_length =
+ (* The below loop tests how many times in a row a loop that calls yield runs
+ without changing threads. Ideally the answer would *always* be one, but
+ it's not clear we can reliably guarantee that unless nothing else ever
+ drops the Ocaml lock, so instead just rely on it being small. *)
+ if run_length > 3
+ then Printf.printf "Thread %d ran %d consecutive iters\n" thread run_length
+
+
+let threads =
+ List.init threads (Thread.create (fun i ->
+ incr are_ready;
+ (* Don't make any progress until all threads are spawned and properly
+ contending for the Ocaml lock. *)
+ while !are_ready < threads do
+ Thread.yield ()
+ done;
+ let consecutive = ref 0 in
+ while !yields < iters do
+ incr yields;
+ last := i;
+ Thread.yield ();
+ incr consecutive;
+ if not (!last = i)
+ then (
+ report i !consecutive;
+ consecutive := 0)
+ done;
+ if !consecutive > 0 then report i !consecutive;
+ ));;
+
+List.iter Thread.join threads