-
-
Save evanmcc/a599f4c6374338ed672e to your computer and use it in GitHub Desktop.
Patch file to add +sfwi tuning to an R15B01 Erlang VM. Should be present without the patch in R16B01+. It's possible that this patch will apply to other releases. Use at your own risk.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
From 005be2e442074ea529ae0a188399eda553cb8783 Mon Sep 17 00:00:00 2001 | |
From: evan <evan@basho.com> | |
Date: Tue, 18 Jun 2013 17:52:54 -0400 | |
Subject: [PATCH] backport sfwi to R15B01 | |
--- | |
erts/emulator/beam/erl_init.c | 16 +++++++ | |
erts/emulator/beam/erl_process.c | 89 ++++++++++++++++++++++++++++++++++++-- | |
erts/emulator/beam/erl_process.h | 9 ++++ | |
erts/etc/common/erlexec.c | 1 + | |
4 files changed, 112 insertions(+), 3 deletions(-) | |
diff --git a/erts/emulator/beam/erl_init.c b/erts/emulator/beam/erl_init.c | |
index ca4385d..4c2aef3 100644 | |
--- a/erts/emulator/beam/erl_init.c | |
+++ b/erts/emulator/beam/erl_init.c | |
@@ -1283,6 +1283,22 @@ erl_start(int argc, char **argv) | |
("suggested scheduler thread stack size %d kilo words\n", | |
erts_sched_thread_suggested_stack_size)); | |
} | |
+ else if (has_prefix("fwi", sub_param)) { | |
+ long val; | |
+ arg = get_arg(sub_param+3, argv[i+1], &i); | |
+ errno = 0; | |
+ val = strtol(arg, NULL, 10); | |
+ if (errno != 0 || val < 0) { | |
+ erts_fprintf(stderr, | |
+ "bad scheduler forced wakeup " | |
+ "interval %s\n", | |
+ arg); | |
+ erts_usage(); | |
+ } | |
+#ifdef ERTS_SMP | |
+ erts_runq_supervision_interval = val; | |
+#endif | |
+ } | |
else { | |
erts_fprintf(stderr, "bad scheduling option %s\n", argv[i]); | |
erts_usage(); | |
diff --git a/erts/emulator/beam/erl_process.c b/erts/emulator/beam/erl_process.c | |
index 95d408f..fec9160 100644 | |
--- a/erts/emulator/beam/erl_process.c | |
+++ b/erts/emulator/beam/erl_process.c | |
@@ -211,6 +211,10 @@ static erts_smp_atomic32_t function_calls; | |
#ifdef ERTS_SMP | |
static erts_smp_atomic32_t doing_sys_schedule; | |
static erts_smp_atomic32_t no_empty_run_queues; | |
+long erts_runq_supervision_interval = 0; | |
+static ethr_event runq_supervision_event; | |
+static erts_tid_t runq_supervisor_tid; | |
+static erts_atomic_t runq_supervisor_sleeping; | |
#else /* !ERTS_SMP */ | |
ErtsSchedulerData *erts_scheduler_data; | |
#endif | |
@@ -1794,7 +1798,13 @@ empty_runq(ErtsRunQueue *rq) | |
*/ | |
ASSERT(0 <= empty && empty < 2*erts_no_run_queues); | |
#endif | |
- erts_smp_atomic32_inc_relb(&no_empty_run_queues); | |
+ if (!erts_runq_supervision_interval) | |
+ erts_smp_atomic32_inc_relb(&no_empty_run_queues); | |
+ else { | |
+ erts_smp_atomic32_inc_mb(&no_empty_run_queues); | |
+ if (erts_atomic_read_nob(&runq_supervisor_sleeping)) | |
+ ethr_event_set(&runq_supervision_event); | |
+ } | |
} | |
} | |
@@ -1812,7 +1822,14 @@ non_empty_runq(ErtsRunQueue *rq) | |
*/ | |
ASSERT(0 < empty && empty <= 2*erts_no_run_queues); | |
#endif | |
- erts_smp_atomic32_dec_relb(&no_empty_run_queues); | |
+ if (!erts_runq_supervision_interval) | |
+ erts_smp_atomic32_dec_relb(&no_empty_run_queues); | |
+ else { | |
+ erts_aint32_t no; | |
+ no = erts_smp_atomic32_dec_read_mb(&no_empty_run_queues); | |
+ if (no > 0 && erts_atomic_read_nob(&runq_supervisor_sleeping)) | |
+ ethr_event_set(&runq_supervision_event); | |
+ } | |
} | |
} | |
@@ -2412,7 +2429,6 @@ try_inc_no_active_runqs(int active) | |
return 0; | |
} | |
- | |
static ERTS_INLINE int | |
chk_wake_sched(ErtsRunQueue *crq, int ix, int activate) | |
{ | |
@@ -3875,6 +3891,57 @@ erts_get_scheduler_data(void) | |
return (ErtsSchedulerData *) erts_tsd_get(sched_data_key); | |
} | |
+#ifdef ERTS_SMP | |
+ | |
+static int | |
+no_runqs_to_supervise(void) | |
+{ | |
+ int used; | |
+ erts_aint32_t nerq = erts_smp_atomic32_read_acqb(&no_empty_run_queues); | |
+ if (nerq <= 0) | |
+ return 0; | |
+ get_no_runqs(NULL, &used); | |
+ if (nerq >= used) | |
+ return 0; | |
+ return used; | |
+} | |
+ | |
+static void * | |
+runq_supervisor(void *unused) | |
+{ | |
+ while (1) { | |
+ int ix, no_rqs; | |
+ | |
+ erts_milli_sleep(erts_runq_supervision_interval); | |
+ no_rqs = no_runqs_to_supervise(); | |
+ if (!no_rqs) { | |
+ erts_atomic_set_nob(&runq_supervisor_sleeping, 1); | |
+ while (1) { | |
+ ethr_event_reset(&runq_supervision_event); | |
+ no_rqs = no_runqs_to_supervise(); | |
+ if (no_rqs) { | |
+ erts_atomic_set_nob(&runq_supervisor_sleeping, 0); | |
+ break; | |
+ } | |
+ ethr_event_wait(&runq_supervision_event); | |
+ } | |
+ } | |
+ | |
+ for (ix = 0; ix < no_rqs; ix++) { | |
+ ErtsRunQueue *rq = ERTS_RUNQ_IX(ix); | |
+ if (ERTS_RUNQ_IFLGS_GET(rq) & ERTS_RUNQ_IFLG_NONEMPTY) { | |
+ erts_smp_runq_lock(rq); | |
+ if (rq->len != 0) { | |
+ wake_scheduler_on_empty_runq(rq); /* forced wakeup... */ | |
+ } | |
+ erts_smp_runq_unlock(rq); | |
+ } | |
+ } | |
+ } | |
+ return NULL; | |
+} | |
+ | |
+#endif | |
#endif | |
static int remove_proc_from_runq(ErtsRunQueue *rq, Process *p, int to_inactive); | |
@@ -4851,6 +4918,22 @@ erts_start_schedulers(void) | |
ethr_thr_opts opts = ETHR_THR_OPTS_DEFAULT_INITER; | |
opts.detached = 1; | |
+ | |
+#ifdef ERTS_SMP | |
+ if (erts_runq_supervision_interval) { | |
+ opts.suggested_stack_size = 16; | |
+ erts_atomic_init_nob(&runq_supervisor_sleeping, 0); | |
+ if (0 != ethr_event_init(&runq_supervision_event)) | |
+ erl_exit(1, "Failed to create run-queue supervision event\n"); | |
+ if (0 != ethr_thr_create(&runq_supervisor_tid, | |
+ runq_supervisor, | |
+ NULL, | |
+ &opts)) | |
+ erl_exit(1, "Failed to create run-queue supervision thread\n"); | |
+ | |
+ } | |
+#endif | |
+ | |
opts.suggested_stack_size = erts_sched_thread_suggested_stack_size; | |
if (wanted < 1) | |
diff --git a/erts/emulator/beam/erl_process.h b/erts/emulator/beam/erl_process.h | |
index cff0783..e1f4f1e 100644 | |
--- a/erts/emulator/beam/erl_process.h | |
+++ b/erts/emulator/beam/erl_process.h | |
@@ -148,6 +148,8 @@ extern int erts_sched_thread_suggested_stack_size; | |
(((Uint32) 1) << (ERTS_RUNQ_FLG_BASE2 + 3)) | |
#define ERTS_RUNQ_FLG_INACTIVE \ | |
(((Uint32) 1) << (ERTS_RUNQ_FLG_BASE2 + 4)) | |
+#define ERTS_RUNQ_FLG_NONEMPTY \ | |
+ (((Uint32) 1) << (ERTS_RUNQ_FLG_BASE2 + 5)) | |
#define ERTS_RUNQ_FLGS_MIGRATION_QMASKS \ | |
(ERTS_RUNQ_FLGS_EMIGRATE_QMASK \ | |
@@ -186,6 +188,9 @@ extern int erts_sched_thread_suggested_stack_size; | |
#define ERTS_UNSET_RUNQ_FLG_EVACUATE(FLGS, PRIO) \ | |
((FLGS) &= ~ERTS_RUNQ_FLG_EVACUATE((PRIO))) | |
+#define ERTS_RUNQ_IFLGS_GET(RQ) \ | |
+ ((Uint32) erts_smp_atomic32_read_acqb(&(RQ)->info_flags)) | |
+ | |
#define ERTS_RUNQ_IFLG_SUSPENDED (((erts_aint32_t) 1) << 0) | |
#define ERTS_RUNQ_IFLG_NONEMPTY (((erts_aint32_t) 1) << 1) | |
@@ -370,6 +375,10 @@ struct ErtsRunQueue_ { | |
} ports; | |
}; | |
+#ifdef ERTS_SMP | |
+extern long erts_runq_supervision_interval; | |
+#endif | |
+ | |
typedef union { | |
ErtsRunQueue runq; | |
char align[ERTS_ALC_CACHE_LINE_ALIGN_SIZE(sizeof(ErtsRunQueue))]; | |
diff --git a/erts/etc/common/erlexec.c b/erts/etc/common/erlexec.c | |
index 19b3bb8..ac4e509 100644 | |
--- a/erts/etc/common/erlexec.c | |
+++ b/erts/etc/common/erlexec.c | |
@@ -123,6 +123,7 @@ static char *pluss_val_switches[] = { | |
"bt", | |
"cl", | |
"ct", | |
+ "fwi", | |
"wt", | |
"ss", | |
NULL | |
-- | |
1.7.9.5 | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment