diff options
Diffstat (limited to 'erts/emulator')
-rw-r--r-- | erts/emulator/beam/beam_debug.c | 18 | ||||
-rw-r--r-- | erts/emulator/beam/erl_nif.c | 17 | ||||
-rw-r--r-- | erts/emulator/beam/erl_process.c | 42 | ||||
-rw-r--r-- | erts/emulator/beam/erl_process.h | 27 | ||||
-rw-r--r-- | erts/emulator/beam/erl_process_dict.c | 4 | ||||
-rw-r--r-- | erts/emulator/test/Makefile | 3 | ||||
-rw-r--r-- | erts/emulator/test/emulator_node_container_SUITE.spec | 2 | ||||
-rw-r--r-- | erts/emulator/test/scheduler_SUITE.erl | 78 |
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) -> |