aboutsummaryrefslogtreecommitdiffstats
path: root/erts/emulator
diff options
context:
space:
mode:
Diffstat (limited to 'erts/emulator')
-rw-r--r--erts/emulator/beam/beam_debug.c18
-rw-r--r--erts/emulator/beam/erl_nif.c17
-rw-r--r--erts/emulator/beam/erl_process.c42
-rw-r--r--erts/emulator/beam/erl_process.h27
-rw-r--r--erts/emulator/beam/erl_process_dict.c4
-rw-r--r--erts/emulator/test/Makefile3
-rw-r--r--erts/emulator/test/emulator_node_container_SUITE.spec2
-rw-r--r--erts/emulator/test/scheduler_SUITE.erl78
8 files changed, 125 insertions, 66 deletions
diff --git a/erts/emulator/beam/beam_debug.c b/erts/emulator/beam/beam_debug.c
index 88b223cf49..37d8699a4b 100644
--- a/erts/emulator/beam/beam_debug.c
+++ b/erts/emulator/beam/beam_debug.c
@@ -853,15 +853,23 @@ dirty_test(Process *c_p, Eterm type, Eterm arg1, Eterm arg2, UWord *I)
goto badarg;
esdp = erts_proc_sched_data(c_p);
if (!esdp)
- ERTS_BIF_PREP_RET(ret, am_error);
- else if (!ERTS_SCHEDULER_IS_DIRTY(esdp))
+ goto scheduler_type_error;
+
+ switch (esdp->type) {
+ case ERTS_SCHED_NORMAL:
ERTS_BIF_PREP_RET(ret, am_normal);
- else if (ERTS_SCHEDULER_IS_DIRTY_CPU(esdp))
+ break;
+ case ERTS_SCHED_DIRTY_CPU:
ERTS_BIF_PREP_RET(ret, am_dirty_cpu);
- else if (ERTS_SCHEDULER_IS_DIRTY_IO(esdp))
+ break;
+ case ERTS_SCHED_DIRTY_IO:
ERTS_BIF_PREP_RET(ret, am_dirty_io);
- else
+ break;
+ default:
+ scheduler_type_error:
ERTS_BIF_PREP_RET(ret, am_error);
+ break;
+ }
}
else if (am_error == arg1) {
switch (arg2) {
diff --git a/erts/emulator/beam/erl_nif.c b/erts/emulator/beam/erl_nif.c
index 63a4a997da..f86b9739fa 100644
--- a/erts/emulator/beam/erl_nif.c
+++ b/erts/emulator/beam/erl_nif.c
@@ -2818,14 +2818,19 @@ enif_thread_type(void)
if (!esdp)
return ERL_NIF_THR_UNDEFINED;
- if (!ERTS_SCHEDULER_IS_DIRTY(esdp))
+ switch (esdp->type) {
+ case ERTS_SCHED_NORMAL:
return ERL_NIF_THR_NORMAL_SCHEDULER;
-
- if (ERTS_SCHEDULER_IS_DIRTY_CPU(esdp))
+#ifdef ERTS_DIRTY_SCHEDULERS
+ case ERTS_SCHED_DIRTY_CPU:
return ERL_NIF_THR_DIRTY_CPU_SCHEDULER;
-
- ASSERT(ERTS_SCHEDULER_IS_DIRTY_IO(esdp));
- return ERL_NIF_THR_DIRTY_IO_SCHEDULER;
+ case ERTS_SCHED_DIRTY_IO:
+ return ERL_NIF_THR_DIRTY_IO_SCHEDULER;
+#endif
+ default:
+ ERTS_INTERNAL_ERROR("Invalid scheduler type");
+ return -1;
+ }
}
/* Maps */
diff --git a/erts/emulator/beam/erl_process.c b/erts/emulator/beam/erl_process.c
index f0fd3e3dc9..6b5b64993f 100644
--- a/erts/emulator/beam/erl_process.c
+++ b/erts/emulator/beam/erl_process.c
@@ -5947,14 +5947,30 @@ erts_sched_set_wake_cleanup_threshold(char *str)
static void
init_aux_work_data(ErtsAuxWorkData *awdp, ErtsSchedulerData *esdp, char *dawwp)
{
- if (!esdp)
- awdp->sched_id = 0;
+ int id = 0;
+ if (esdp) {
+ switch (esdp->type) {
+ case ERTS_SCHED_NORMAL:
+ id = (int) esdp->no;
+ break;
#ifdef ERTS_DIRTY_SCHEDULERS
- else if (ERTS_SCHEDULER_IS_DIRTY(esdp))
- awdp->sched_id = (int) ERTS_DIRTY_SCHEDULER_NO(esdp);
+ case ERTS_SCHED_DIRTY_CPU:
+ id = (int) erts_no_schedulers;
+ id += (int) esdp->dirty_no;
+ break;
+ case ERTS_SCHED_DIRTY_IO:
+ id = (int) erts_no_schedulers;
+ id += (int) erts_no_dirty_cpu_schedulers;
+ id += (int) esdp->dirty_no;
+ break;
#endif
- else
- awdp->sched_id = (int) esdp->no;
+ default:
+ ERTS_INTERNAL_ERROR("Invalid scheduler type");
+ break;
+ }
+ }
+
+ awdp->sched_id = id;
awdp->esdp = esdp;
awdp->ssi = esdp ? esdp->ssi : NULL;
#ifdef ERTS_SMP
@@ -6027,7 +6043,7 @@ init_scheduler_data(ErtsSchedulerData* esdp, int num,
ASSERT(runq == ERTS_DIRTY_IO_RUNQ);
esdp->type = ERTS_SCHED_DIRTY_IO;
}
- ERTS_DIRTY_SCHEDULER_NO(esdp) = (Uint) num;
+ esdp->dirty_no = (Uint) num;
if (num == 1) {
/*
* Multi-scheduling block functionality depends
@@ -6039,7 +6055,7 @@ init_scheduler_data(ErtsSchedulerData* esdp, int num,
else {
esdp->type = ERTS_SCHED_NORMAL;
esdp->no = (Uint) num;
- ERTS_DIRTY_SCHEDULER_NO(esdp) = 0;
+ esdp->dirty_no = 0;
runq->scheduler = esdp;
}
esdp->dirty_shadow_process = shadow_proc;
@@ -7776,11 +7792,11 @@ suspend_scheduler(ErtsSchedulerData *esdp)
break;
case ERTS_SCHED_DIRTY_CPU:
online_flag = ERTS_SCHDLR_SSPND_CHNG_DCPU_ONLN;
- no = ERTS_DIRTY_SCHEDULER_NO(esdp);
+ no = esdp->dirty_no;
break;
case ERTS_SCHED_DIRTY_IO:
online_flag = 0;
- no = ERTS_DIRTY_SCHEDULER_NO(esdp);
+ no = esdp->dirty_no;
break;
default:
ERTS_INTERNAL_ERROR("Invalid scheduler type");
@@ -8805,8 +8821,7 @@ sched_dirty_cpu_thread_func(void *vesdp)
{
ErtsThrPrgrCallbacks callbacks;
ErtsSchedulerData *esdp = vesdp;
- Uint no = ERTS_DIRTY_SCHEDULER_NO(esdp);
- ERTS_DIRTY_SCHEDULER_TYPE(esdp) = ERTS_DIRTY_CPU_SCHEDULER;
+ Uint no = esdp->dirty_no;
ASSERT(no != 0);
ERTS_DIRTY_CPU_SCHED_SLEEP_INFO_IX(no-1)->event = erts_tse_fetch();
callbacks.arg = (void *) esdp->ssi;
@@ -8854,8 +8869,7 @@ sched_dirty_io_thread_func(void *vesdp)
{
ErtsThrPrgrCallbacks callbacks;
ErtsSchedulerData *esdp = vesdp;
- Uint no = ERTS_DIRTY_SCHEDULER_NO(esdp);
- ERTS_DIRTY_SCHEDULER_TYPE(esdp) = ERTS_DIRTY_IO_SCHEDULER;
+ Uint no = esdp->dirty_no;
ASSERT(no != 0);
ERTS_DIRTY_IO_SCHED_SLEEP_INFO_IX(no-1)->event = erts_tse_fetch();
callbacks.arg = (void *) esdp->ssi;
diff --git a/erts/emulator/beam/erl_process.h b/erts/emulator/beam/erl_process.h
index baf830615d..883d9f2a4c 100644
--- a/erts/emulator/beam/erl_process.h
+++ b/erts/emulator/beam/erl_process.h
@@ -641,13 +641,6 @@ typedef enum {
ERTS_DIRTY_IO_SCHEDULER
} ErtsDirtySchedulerType;
-typedef union {
- struct {
- ErtsDirtySchedulerType type: 1;
- Uint num: sizeof(Uint)*8 - 1;
- } s;
- Uint no;
-} ErtsDirtySchedId;
#endif
struct ErtsSchedulerData_ {
@@ -674,7 +667,7 @@ struct ErtsSchedulerData_ {
ErtsSchedType type;
Uint no; /* Scheduler number for normal schedulers */
#ifdef ERTS_DIRTY_SCHEDULERS
- ErtsDirtySchedId dirty_no; /* Scheduler number for dirty schedulers */
+ Uint dirty_no; /* Scheduler number for dirty schedulers */
Process *dirty_shadow_process;
#endif
Port *current_port;
@@ -1578,23 +1571,13 @@ extern int erts_system_profile_ts_type;
#define ERTS_DIRTY_IO_SCHEDULER_IX(IX) \
(ASSERT(0 <= (IX) && (IX) < erts_no_dirty_io_schedulers), \
&erts_aligned_dirty_io_scheduler_data[(IX)].esd)
-#define ERTS_DIRTY_SCHEDULER_NO(ESDP) \
- ((ESDP)->dirty_no.s.num)
-#define ERTS_DIRTY_SCHEDULER_TYPE(ESDP) \
- ((ESDP)->dirty_no.s.type)
-#ifdef ERTS_SMP
#define ERTS_SCHEDULER_IS_DIRTY(ESDP) \
- ((ESDP)->dirty_no.s.num != 0)
+ ((ESDP)->type != ERTS_SCHED_NORMAL)
#define ERTS_SCHEDULER_IS_DIRTY_CPU(ESDP) \
- (ERTS_SCHEDULER_IS_DIRTY((ESDP)) & ((ESDP)->dirty_no.s.type == 0))
+ ((ESDP)->type == ERTS_SCHED_DIRTY_CPU)
#define ERTS_SCHEDULER_IS_DIRTY_IO(ESDP) \
- (ERTS_SCHEDULER_IS_DIRTY((ESDP)) & ((ESDP)->dirty_no.s.type == 1))
-#else
-#define ERTS_SCHEDULER_IS_DIRTY(ESDP) 0
-#define ERTS_SCHEDULER_IS_DIRTY_CPU(ESDP) 0
-#define ERTS_SCHEDULER_IS_DIRTY_IO(ESDP) 0
-#endif
-#else
+ ((ESDP)->type == ERTS_SCHED_DIRTY_IO)
+#else /* !ERTS_DIRTY_SCHEDULERS */
#define ERTS_RUNQ_IX_IS_DIRTY(IX) 0
#define ERTS_SCHEDULER_IS_DIRTY(ESDP) 0
#define ERTS_SCHEDULER_IS_DIRTY_CPU(ESDP) 0
diff --git a/erts/emulator/beam/erl_process_dict.c b/erts/emulator/beam/erl_process_dict.c
index 8311fde025..7cfdf20341 100644
--- a/erts/emulator/beam/erl_process_dict.c
+++ b/erts/emulator/beam/erl_process_dict.c
@@ -54,9 +54,9 @@
#define HASH_RANGE(PDict) ((PDict)->usedSlots)
#define MAKE_HASH(Term) \
- ((is_small(Term)) ? unsigned_val(Term) : \
+ ((is_small(Term)) ? (Uint32) unsigned_val(Term) : \
((is_atom(Term)) ? \
- atom_val(Term) : \
+ (Uint32) atom_val(Term) : \
make_internal_hash(Term)))
#define PD_SZ2BYTES(Sz) (sizeof(ProcDict) + ((Sz) - 1)*sizeof(Eterm))
diff --git a/erts/emulator/test/Makefile b/erts/emulator/test/Makefile
index 5478932b13..186f9fef8d 100644
--- a/erts/emulator/test/Makefile
+++ b/erts/emulator/test/Makefile
@@ -157,7 +157,8 @@ EMAKEFILE=Emakefile
TEST_SPEC_FILES= emulator.spec \
emulator.spec.win \
emulator_bench.spec \
- emulator_smoke.spec
+ emulator_smoke.spec \
+ emulator_node_container_SUITE.spec
# ----------------------------------------------------
# Release directory specification
diff --git a/erts/emulator/test/emulator_node_container_SUITE.spec b/erts/emulator/test/emulator_node_container_SUITE.spec
new file mode 100644
index 0000000000..77c28ba7ae
--- /dev/null
+++ b/erts/emulator/test/emulator_node_container_SUITE.spec
@@ -0,0 +1,2 @@
+{enable_builtin_hooks, false}.
+{suites,"../emulator_test",node_container_SUITE}.
diff --git a/erts/emulator/test/scheduler_SUITE.erl b/erts/emulator/test/scheduler_SUITE.erl
index b178dede5b..885298ce34 100644
--- a/erts/emulator/test/scheduler_SUITE.erl
+++ b/erts/emulator/test/scheduler_SUITE.erl
@@ -807,21 +807,31 @@ update_cpu_info(Config) when is_list(Config) ->
%% Nothing much to test; just a smoke test
ok;
Onln0 ->
- %% unset least significant bit
- Aff = (OldAff band (OldAff - 1)),
- set_affinity_mask(Aff),
- Onln1 = Avail - 1,
- case adjust_schedulers_online() of
- {Onln0, Onln1} ->
- Onln1 = erlang:system_info(schedulers_online),
- receive after 500 -> ok end,
- io:format("TEST - Affinity mask: ~p - Schedulers online: ~p - Scheduler bindings: ~p~n",
- [Aff, Onln1, erlang:system_info(scheduler_bindings)]),
- unchanged = adjust_schedulers_online(),
- ok;
- Fail ->
- ct:fail(Fail)
- end
+ Cpus = bits_in_mask(OldAff),
+ RmCpus = case Cpus > Onln0 of
+ true -> Cpus - Onln0 + 1;
+ false -> Onln0 - Cpus + 1
+ end,
+ Onln1 = Cpus - RmCpus,
+ case Onln1 > 0 of
+ false ->
+ %% Nothing much to test; just a smoke test
+ ok;
+ true ->
+ Aff = restrict_affinity_mask(OldAff, RmCpus),
+ set_affinity_mask(Aff),
+ case adjust_schedulers_online() of
+ {Onln0, Onln1} ->
+ Onln1 = erlang:system_info(schedulers_online),
+ receive after 500 -> ok end,
+ io:format("TEST - Affinity mask: ~p - Schedulers online: ~p - Scheduler bindings: ~p~n",
+ [Aff, Onln1, erlang:system_info(scheduler_bindings)]),
+ unchanged = adjust_schedulers_online(),
+ ok;
+ Fail ->
+ ct:fail(Fail)
+ end
+ end
end
after
set_affinity_mask(OldAff),
@@ -835,13 +845,49 @@ update_cpu_info(Config) when is_list(Config) ->
end
end.
+bits_in_mask(Mask) ->
+ bits_in_mask(Mask, 0, 0).
+
+bits_in_mask(0, Shift, N) ->
+ N;
+bits_in_mask(Mask, Shift, N) ->
+ case Mask band (1 bsl Shift) of
+ 0 -> bits_in_mask(Mask, Shift+1, N);
+ _ -> bits_in_mask(Mask band (bnot (1 bsl Shift)),
+ Shift+1, N+1)
+ end.
+
+restrict_affinity_mask(Mask, N) ->
+ try
+ restrict_affinity_mask(Mask, 0, N)
+ catch
+ throw : Reason ->
+ exit({Reason, Mask, N})
+ end.
+
+restrict_affinity_mask(Mask, _Shift, 0) ->
+ Mask;
+restrict_affinity_mask(0, _Shift, _N) ->
+ throw(overresticted_affinity_mask);
+restrict_affinity_mask(Mask, Shift, N) ->
+ case Mask band (1 bsl Shift) of
+ 0 -> restrict_affinity_mask(Mask, Shift+1, N);
+ _ -> restrict_affinity_mask(Mask band (bnot (1 bsl Shift)),
+ Shift+1, N-1)
+ end.
+
adjust_schedulers_online() ->
case erlang:system_info(update_cpu_info) of
unchanged ->
unchanged;
changed ->
Avail = erlang:system_info(logical_processors_available),
- {erlang:system_flag(schedulers_online, Avail), Avail}
+ Scheds = erlang:system_info(schedulers),
+ SOnln = case Avail > Scheds of
+ true -> Scheds;
+ false -> Avail
+ end,
+ {erlang:system_flag(schedulers_online, SOnln), SOnln}
end.
read_affinity(Data) ->