aboutsummaryrefslogtreecommitdiffstats
path: root/erts
diff options
context:
space:
mode:
authorRickard Green <[email protected]>2013-06-11 17:30:47 +0200
committerRickard Green <[email protected]>2013-06-11 18:33:38 +0200
commit4c9a66c4ba3bbbd6136f3a284fc1accbc0e9cea2 (patch)
treef6ecb789473b7d15fad43b3c0838d8784a9aaf3b /erts
parent9919508b2cc177ec4afdb53bb9d20563973461f8 (diff)
downloadotp-4c9a66c4ba3bbbd6136f3a284fc1accbc0e9cea2.tar.gz
otp-4c9a66c4ba3bbbd6136f3a284fc1accbc0e9cea2.tar.bz2
otp-4c9a66c4ba3bbbd6136f3a284fc1accbc0e9cea2.zip
erts: Add the +sfwi system flag
+sfwi Interval Set scheduler forced wakeup interval. All run queues will be scanned each Interval milliseconds. While there are sleeping schedulers in the system, one scheduler will be woken for each non-empty run queue found. An Interval of zero disables this feature, which also is the default. This feature has been introduced as a temporary workaround for lengthy executing native code, and native code that do not bump reductions properly in OTP. When these bugs have be fixed the +sfwi flag will be removed.
Diffstat (limited to 'erts')
-rw-r--r--erts/doc/src/erl.xml14
-rw-r--r--erts/emulator/beam/erl_init.c16
-rw-r--r--erts/emulator/beam/erl_process.c85
-rw-r--r--erts/emulator/beam/erl_process.h4
-rw-r--r--erts/etc/common/erlexec.c1
5 files changed, 117 insertions, 3 deletions
diff --git a/erts/doc/src/erl.xml b/erts/doc/src/erl.xml
index 8dca7402e8..70569b1c6c 100644
--- a/erts/doc/src/erl.xml
+++ b/erts/doc/src/erl.xml
@@ -1037,6 +1037,20 @@
<p>For more information, see
<seealso marker="erlang#system_info_cpu_topology">erlang:system_info(cpu_topology)</seealso>.</p>
</item>
+ <tag><marker id="+sfwi"><c>+sfwi Interval</c></marker></tag>
+ <item>
+ <p>Set scheduler forced wakeup interval. All run queues will
+ be scanned each <c>Interval</c> milliseconds. While there are
+ sleeping schedulers in the system, one scheduler will be woken
+ for each non-empty run queue found. An <c>Interval</c> of zero
+ disables this feature, which also is the default.
+ </p>
+ <p>This feature has been introduced as a temporary workaround
+ for lengthy executing native code, and native code that do not
+ bump reductions properly in OTP. When these bugs have be fixed
+ the <c>+sfwi</c> flag will be removed.
+ </p>
+ </item>
<tag><marker id="+stbt"><c>+stbt BindType</c></marker></tag>
<item>
<p>Try to set scheduler bind type. The same as the
diff --git a/erts/emulator/beam/erl_init.c b/erts/emulator/beam/erl_init.c
index b3a3c3d403..da5aa34ea6 100644
--- a/erts/emulator/beam/erl_init.c
+++ b/erts/emulator/beam/erl_init.c
@@ -1479,6 +1479,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 3d161f2aa0..d69f7bf63e 100644
--- a/erts/emulator/beam/erl_process.c
+++ b/erts/emulator/beam/erl_process.c
@@ -246,6 +246,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
@@ -2045,7 +2049,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);
+ }
}
}
@@ -2062,7 +2072,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);
+ }
}
}
@@ -2666,7 +2683,6 @@ try_inc_no_active_runqs(int active)
return 0;
}
-
static ERTS_INLINE int
chk_wake_sched(ErtsRunQueue *crq, int ix, int activate)
{
@@ -4332,6 +4348,53 @@ set_wakeup_other_data(void)
}
}
+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_FLGS_GET(rq) & ERTS_RUNQ_FLG_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
void
@@ -5755,6 +5818,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 3c1edfad7a..3398e6bd7a 100644
--- a/erts/emulator/beam/erl_process.h
+++ b/erts/emulator/beam/erl_process.h
@@ -387,6 +387,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 01134dd718..e61ebe15f5 100644
--- a/erts/etc/common/erlexec.c
+++ b/erts/etc/common/erlexec.c
@@ -122,6 +122,7 @@ static char *pluss_val_switches[] = {
"bwt",
"cl",
"ct",
+ "fwi",
"tbt",
"wct",
"wt",