Skip to content

Commit 8824391

Browse files
committed
CP-49158: Throttle: add Thread.yield
Give an opportunity for more fields to be filled, e.g. when waiting for a task to complete, give a chance for the task to actually run. No feature flag, it only changes timing. Signed-off-by: Edwin Török <[email protected]>
1 parent 44cbe87 commit 8824391

File tree

3 files changed

+16
-8
lines changed

3 files changed

+16
-8
lines changed

dune-project

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,7 @@
327327
(synopsis "The toolstack daemon which implements the XenAPI")
328328
(description "This daemon exposes the XenAPI and is used by clients such as 'xe' and 'XenCenter' to manage clusters of Xen-enabled hosts.")
329329
(depends
330+
(ocaml (>= 4.09))
330331
(alcotest :with-test)
331332
angstrom
332333
astring

ocaml/xapi-aux/throttle.ml

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -56,25 +56,31 @@ module Batching = struct
5656
in
5757
{delay_initial; delay_before; delay_between}
5858

59+
let span_min a b = if Mtime.Span.is_shorter a ~than:b then a else b
60+
5961
(** [perform_delay delay] calls {!val:Thread.delay} when [delay] is non-zero.
6062
6163
Thread.delay 0 provides no fairness guarantees, the current thread may actually be the one that gets the global lock again.
6264
Instead {!val:Thread.yield} could be used, which does provide fairness guarantees, but it may also introduce large latencies
63-
when there are lots of threads waiting for the OCaml runtime lock.
65+
when there are lots of threads waiting for the OCaml runtime lock. Only invoke this once, in the [delay_before] section.
6466
*)
65-
let perform_delay delay =
67+
let perform_delay ~yield delay =
6668
if Mtime.Span.is_longer delay ~than:Mtime.Span.min_span then
6769
Thread.delay (Clock.Timer.span_to_s delay)
68-
69-
let span_min a b = if Mtime.Span.is_shorter a ~than:b then a else b
70+
else if yield then
71+
(* this is a low-priority thread, if there are any other threads waiting, then run them now.
72+
If there are no threads waiting then this a noop.
73+
Requires OCaml >= 4.09 (older versions had fairness issues in Thread.yield)
74+
*)
75+
Thread.yield ()
7076

7177
let with_recursive_loop config f =
7278
let rec self arg input =
7379
let arg = span_min config.delay_between Mtime.Span.(2 * arg) in
74-
perform_delay arg ;
80+
perform_delay ~yield:false arg ;
7581
(f [@tailcall]) (self arg) input
7682
in
77-
let self0 arg input = (f [@tailcall]) (self arg) input in
78-
perform_delay config.delay_before ;
79-
f (self0 config.delay_initial)
83+
let self0 input = (f [@tailcall]) (self config.delay_initial) input in
84+
perform_delay ~yield:true config.delay_before ;
85+
f self0
8086
end

xapi.opam

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ homepage: "https://xapi-project.github.io/"
1010
bug-reports: "https://github.com/xapi-project/xen-api/issues"
1111
depends: [
1212
"dune" {>= "3.15"}
13+
"ocaml" {>= "4.09"}
1314
"alcotest" {with-test}
1415
"angstrom"
1516
"astring"

0 commit comments

Comments
 (0)