Skip to content

Commit c4a84f1

Browse files
authored
Improved pending actions handling in caml_enter_blocking_section (r5 only) (#3740)
1 parent 00e65ee commit c4a84f1

File tree

1 file changed

+21
-23
lines changed

1 file changed

+21
-23
lines changed

runtime/signals.c

+21-23
Original file line numberDiff line numberDiff line change
@@ -163,33 +163,31 @@ CAMLexport void (*caml_leave_blocking_section_hook)(void) =
163163

164164
static int check_pending_actions(caml_domain_state * dom_st);
165165

166-
CAMLexport void caml_enter_blocking_section(void)
166+
CAMLexport void caml_enter_blocking_section_no_pending(void)
167167
{
168-
caml_domain_state * domain = Caml_state;
169-
while (1){
170-
if (Caml_state->in_minor_collection)
171-
caml_fatal_error("caml_enter_blocking_section from inside minor GC");
172-
/* Process all pending signals now */
173-
if (check_pending_actions(domain)) {
174-
/* First reset young_limit, and set action_pending in case there
175-
are further async callbacks pending beyond OCaml signal
176-
handlers. */
177-
caml_handle_gc_interrupt();
178-
caml_raise_async_if_exception(caml_process_pending_signals_exn(), "");
179-
}
180-
caml_enter_blocking_section_hook ();
181-
/* Check again if a signal arrived in the meanwhile. If none,
182-
done; otherwise, try again. Since we do not hold the domain
183-
lock, we cannot read [young_ptr] and we cannot call
184-
[Caml_check_gc_interrupt]. */
185-
if (atomic_load_relaxed(&domain->young_limit) != UINTNAT_MAX) break;
186-
caml_leave_blocking_section_hook ();
187-
}
168+
caml_enter_blocking_section_hook ();
188169
}
189170

190-
CAMLexport void caml_enter_blocking_section_no_pending(void)
171+
CAMLexport void caml_enter_blocking_section(void)
191172
{
192-
caml_enter_blocking_section_hook ();
173+
if (Caml_state->in_minor_collection)
174+
caml_fatal_error("caml_enter_blocking_section from inside minor GC");
175+
176+
/* Execute pending signal handlers until there are no more remaining.
177+
We check [action_pending] as it's faster than the signals check. */
178+
while (Caml_check_gc_interrupt(Caml_state)
179+
|| (Caml_state->action_pending && caml_check_pending_signals())) {
180+
/* First reset young_limit, and set action_pending in case there
181+
are further async callbacks pending beyond OCaml signal
182+
handlers. */
183+
caml_handle_gc_interrupt();
184+
caml_raise_async_if_exception(caml_process_pending_signals_exn(), "");
185+
}
186+
187+
/* Drop the systhreads lock */
188+
caml_enter_blocking_section_no_pending ();
189+
/* Any pending actions that happen at this point onwards can be handled by
190+
another thread, or by this thread upon leaving the blocking section. */
193191
}
194192

195193
CAMLexport void caml_leave_blocking_section(void)

0 commit comments

Comments
 (0)