File 0813-erts-Fix-single-core-performance-bug-ERL-716.patch of Package erlang
From b40c79b7841ae2912378c0a5a17dd8b80a230fc3 Mon Sep 17 00:00:00 2001
From: Sverker Eriksson <sverker@erlang.org>
Date: Thu, 26 Mar 2020 16:12:47 +0100
Subject: [PATCH] erts: Fix single core performance bug (ERL-716)
Symptom:
Seen on Windows in VirtualBox assigned a single core
as a very slow (10s) startup using 100% cpu.
Problem:
Scheduler out of work calls erts_thr_progress_active(_, 0) which
calls leader_update(). The wakeup_managed(0) call at the end of
leader_update() will poke aux thread to make thread progress. But
the poking thread (the scheduler) has not yet set its own 'current'
counter to ERTS_THR_PRGR_VAL_WAITING, which will prevent thread
progress to advance. Aux thread spins around in aux_thread() trying
but failing to make thread progress. Not until the scheduler is again
scheduled by the OS and calls erts_thr_progress_prepare_wait() and set
its 'current' to ERTS_THR_PRGR_VAL_WAITING can aux thread make
thread progress.
In short:
Don't wake another thread to do something before you have set all
prerequisite for it to do it.
Solution:
The no-leader-no-active conditional call to wakeup_managed(0) at the
end of leader_update() is actally not needed as it is done again in
erts_thr_progress_prepare_wait() *after* threads 'current' has been
set to ERTS_THR_PRGR_VAL_WAITING.
---
erts/emulator/beam/erl_thr_progress.c | 17 +++--------------
1 file changed, 3 insertions(+), 14 deletions(-)
diff --git a/erts/emulator/beam/erl_thr_progress.c b/erts/emulator/beam/erl_thr_progress.c
index bac437efe9..1a3eb6e747 100644
--- a/erts/emulator/beam/erl_thr_progress.c
+++ b/erts/emulator/beam/erl_thr_progress.c
@@ -763,7 +763,6 @@ leader_update(ErtsThrPrgrData *tpd)
(void) block_thread(tpd);
}
else {
- int force_wakeup_check = 0;
erts_aint32_t set_flags = ERTS_THR_PRGR_LFLG_NO_LEADER;
tpd->leader = 0;
tpd->leader_state.current = ERTS_THR_PRGR_VAL_WAITING;
@@ -788,21 +787,11 @@ leader_update(ErtsThrPrgrData *tpd)
/* Need to check umrefc again */
ETHR_MEMBAR(ETHR_StoreLoad);
refc = erts_atomic_read_nob(&intrnl->umrefc[umrefc_ix].refc);
- if (refc == 0) {
- /* Need to force wakeup check */
- force_wakeup_check = 1;
+ if (refc == 0 && got_sched_wakeups()) {
+ /* Someone need to make progress */
+ wakeup_managed(tpd->id);
}
}
-
- if ((force_wakeup_check
- || ((lflgs & (ERTS_THR_PRGR_LFLG_NO_LEADER
- | ERTS_THR_PRGR_LFLG_WAITING_UM
- | ERTS_THR_PRGR_LFLG_ACTIVE_MASK))
- == ERTS_THR_PRGR_LFLG_NO_LEADER))
- && got_sched_wakeups()) {
- /* Someone need to make progress */
- wakeup_managed(tpd->id);
- }
}
}
--
2.16.4