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

openSUSE Build Service is sponsored by