aboutsummaryrefslogtreecommitdiff
path: root/clib/cThread.ml
diff options
context:
space:
mode:
authorLasse Blaauwbroek2021-04-01 09:18:00 +0200
committerLasse Blaauwbroek2021-04-09 21:05:43 +0200
commit520ac61dfe5a6e865cb7b10f4a822c0d72f3ded9 (patch)
tree965f41e71b205511685060a215fbaa228390be4c /clib/cThread.ml
parent1a64b1560ce88855a76e2faa14cec2864de2f37c (diff)
Make critical sections safe in the presence of exceptions
We introduce the `with_lock` combinator that locks a mutex in an atomic fashion. This ensures that exceptions thrown by signals will not leave the system in a deadlocked state.
Diffstat (limited to 'clib/cThread.ml')
-rw-r--r--clib/cThread.ml19
1 files changed, 19 insertions, 0 deletions
diff --git a/clib/cThread.ml b/clib/cThread.ml
index 89ca2f7d83..3796fdf788 100644
--- a/clib/cThread.ml
+++ b/clib/cThread.ml
@@ -107,3 +107,22 @@ let mask_sigalrm f x =
let create f x =
Thread.create (mask_sigalrm f) x
+
+(*
+ Atomic mutex lock taken from https://gitlab.com/gadmm/memprof-limits/-/blob/master/src/thread_map.ml#L23-34
+ Critical sections :
+ - Mutex.lock does not poll on leaving the blocking section
+ since 4.12.
+ - Never inline, to avoid theoretically-possible reorderings with
+ flambda.
+ (workaround to the lack of masking)
+*)
+
+(* We inline the call to Mutex.unlock to avoid polling in bytecode mode *)
+external unlock: Mutex.t -> unit = "caml_mutex_unlock"
+
+let[@inline never] with_lock m ~scope =
+ let () = Mutex.lock m (* BEGIN ATOMIC *) in
+ match (* END ATOMIC *) scope () with
+ | (* BEGIN ATOMIC *) x -> unlock m ; (* END ATOMIC *) x
+ | (* BEGIN ATOMIC *) exception e -> unlock m ; (* END ATOMIC *) raise e