Remove 50ms delay at exit for programs using threads

$ cat /tmp/b.ml
let () = Thread.join (Thread.create ignore ())
let () = for _ = 0 to 100000; do () done
$ ocamlopt -I +threads unix.cmxa threads.cmxa /tmp/b.ml -o b
$ time ./b # before this commit

real	0m0.053s
user	0m0.000s
sys	0m0.000s
$ time ./b # after this commit

real	0m0.003s
user	0m0.000s
sys	0m0.000s
master
Valentin Gatien-Baron 2017-07-30 10:41:42 -04:00
parent ea4e009533
commit e26c27e002
5 changed files with 31 additions and 23 deletions

View File

@ -396,6 +396,9 @@ Working version
- GPR#1073: Remove statically allocated compare stack.
(Stephen Dolan)
- GPR#1269: Remove 50ms delay at exit for programs using threads
(Valentin Gatien-Baron, review by Stephen Dolan)
* MPR#7594, GPR#1274: String_val now returns 'const char*', not
'char*' when -safe-string is enabled at configure time.
New macro Bytes_val for accessing bytes values.

View File

@ -138,11 +138,11 @@ int caml_startup_aux(int pooling)
return 1;
}
static void do_at_exit()
static void call_registered_value(char* name)
{
value *at_exit = caml_named_value("Pervasives.do_at_exit");
if (at_exit != NULL)
caml_callback_exn(*at_exit, Val_unit);
value *f = caml_named_value(name);
if (f != NULL)
caml_callback_exn(*f, Val_unit);
}
CAMLexport void caml_shutdown(void)
@ -156,7 +156,8 @@ CAMLexport void caml_shutdown(void)
if (startup_count > 0)
return;
do_at_exit();
call_registered_value("Pervasives.do_at_exit");
call_registered_value("Thread.at_shutdown");
caml_finalise_heap();
#ifndef NATIVE_CODE
caml_free_shared_libs();

View File

@ -505,7 +505,9 @@ CAMLprim value caml_thread_initialize(value unit) /* ML */
return Val_unit;
}
/* Cleanup the thread machinery on program exit or DLL unload. */
/* Cleanup the thread machinery when the runtime is shut down. Joining the tick
thread take 25ms on average / 50ms in the worst case, so we don't do it on
program exit. */
CAMLprim value caml_thread_cleanup(value unit) /* ML */
{

View File

@ -57,18 +57,17 @@ let preempt_signal =
| "Win32" -> Sys.sigterm
| _ -> Sys.sigvtalrm
let _ =
let () =
Sys.set_signal preempt_signal (Sys.Signal_handle preempt);
thread_initialize();
at_exit
(fun () ->
thread_cleanup();
(* In case of DLL-embedded OCaml the preempt_signal handler
will point to nowhere after DLL unloading and an accidental
preempt_signal will crash the main program. So restore the
default handler. *)
Sys.set_signal preempt_signal Sys.Signal_default
)
thread_initialize ();
Callback.register "Thread.at_shutdown" (fun () ->
thread_cleanup();
(* In case of DLL-embedded OCaml the preempt_signal handler
will point to nowhere after DLL unloading and an accidental
preempt_signal will crash the main program. So restore the
default handler. *)
Sys.set_signal preempt_signal Sys.Signal_default
)
(* Wait functions *)

View File

@ -1200,12 +1200,15 @@ val exit : int -> 'a
terminates early because of an uncaught exception. *)
val at_exit : (unit -> unit) -> unit
(** Register the given function to be called at program
termination time. The functions registered with [at_exit]
will be called when the program executes {!Pervasives.exit},
or terminates, either normally or because of an uncaught exception.
The functions are called in 'last in, first out' order:
the function most recently added with [at_exit] is called first. *)
(** Register the given function to be called at program termination
time. The functions registered with [at_exit] will be called when
the program does any of the following:
- executes {!Pervasives.exit}
- terminates, either normally or because of an uncaught
exception
- executes the C function [caml_shutdown].
The functions are called in 'last in, first out' order: the
function most recently added with [at_exit] is called first. *)
(**/**)