diff options
Diffstat (limited to 'erts/emulator')
-rw-r--r-- | erts/emulator/beam/erl_bits.c | 18 | ||||
-rw-r--r-- | erts/emulator/beam/erl_port_task.c | 19 | ||||
-rw-r--r-- | erts/emulator/beam/erl_process.c | 66 | ||||
-rw-r--r-- | erts/emulator/beam/erl_process.h | 2 | ||||
-rw-r--r-- | erts/emulator/test/bs_bit_binaries_SUITE.erl | 43 | ||||
-rw-r--r-- | erts/emulator/test/bs_construct_SUITE.erl | 49 |
6 files changed, 164 insertions, 33 deletions
diff --git a/erts/emulator/beam/erl_bits.c b/erts/emulator/beam/erl_bits.c index 6bc227eeda..3753b618e1 100644 --- a/erts/emulator/beam/erl_bits.c +++ b/erts/emulator/beam/erl_bits.c @@ -1247,6 +1247,12 @@ erts_bs_append(Process* c_p, Eterm* reg, Uint live, Eterm build_size_term, */ erts_bin_offset = 8*sb->size + sb->bitsize; + if (unit > 1) { + if ((unit == 8 && (erts_bin_offset & 7) != 0) || + (erts_bin_offset % unit) != 0) { + goto badarg; + } + } used_size_in_bits = erts_bin_offset + build_size_in_bits; sb->is_writable = 0; /* Make sure that no one else can write. */ pb->size = NBYTES(used_size_in_bits); @@ -1316,6 +1322,12 @@ erts_bs_append(Process* c_p, Eterm* reg, Uint live, Eterm build_size_term, */ ERTS_GET_BINARY_BYTES(bin, src_bytes, bitoffs, bitsize); erts_bin_offset = 8*binary_size(bin) + bitsize; + if (unit > 1) { + if ((unit == 8 && (erts_bin_offset & 7) != 0) || + (erts_bin_offset % unit) != 0) { + goto badarg; + } + } used_size_in_bits = erts_bin_offset + build_size_in_bits; used_size_in_bytes = NBYTES(used_size_in_bits); bin_size = 2*used_size_in_bytes; @@ -1363,12 +1375,6 @@ erts_bs_append(Process* c_p, Eterm* reg, Uint live, Eterm build_size_term, /* * Now copy the data into the binary. */ - if (unit > 1) { - if ((unit == 8 && (erts_bin_offset & 7) != 0) || - (erts_bin_offset % unit) != 0) { - return THE_NON_VALUE; - } - } copy_binary_to_buffer(erts_current_bin, 0, src_bytes, bitoffs, erts_bin_offset); return make_binary(sb); diff --git a/erts/emulator/beam/erl_port_task.c b/erts/emulator/beam/erl_port_task.c index 0f1a0d441a..3dc7c14faf 100644 --- a/erts/emulator/beam/erl_port_task.c +++ b/erts/emulator/beam/erl_port_task.c @@ -573,13 +573,8 @@ erts_port_task_schedule(Eterm id, ERTS_PT_CHK_PRES_PORTQ(runq, pp); - if (!pp->sched.taskq) { - pp->sched.taskq = port_taskq_init(port_taskq_alloc(), pp); - enq_port = !pp->sched.exe_taskq; - } - + if (!pp->sched.taskq && !pp->sched.exe_taskq) { #ifdef ERTS_SMP - if (enq_port) { ErtsRunQueue *xrunq = erts_check_emigration_need(runq, ERTS_PORT_PRIO_LEVEL); if (xrunq) { /* Port emigrated ... */ @@ -587,12 +582,17 @@ erts_port_task_schedule(Eterm id, erts_smp_runq_unlock(runq); runq = xrunq; } - } + enq_port = !pp->sched.taskq && !pp->sched.exe_taskq; +#else + enq_port = 1; #endif + } ASSERT(!enq_port || !(runq->flags & ERTS_RUNQ_FLG_SUSPENDED)); - ASSERT(pp->sched.taskq); + if (!pp->sched.taskq) + pp->sched.taskq = port_taskq_init(port_taskq_alloc(), pp); + ASSERT(ptp); ptp->type = type; @@ -984,8 +984,9 @@ erts_port_task_execute(ErtsRunQueue *runq, Port **curr_port_pp) #endif done: - ERTS_SMP_LC_ASSERT(erts_smp_lc_runq_is_locked(runq)); + runq->scheduler->reductions += reds; + ERTS_SMP_LC_ASSERT(erts_smp_lc_runq_is_locked(runq)); ERTS_PORT_REDUCTIONS_EXECUTED(runq, reds); return res; diff --git a/erts/emulator/beam/erl_process.c b/erts/emulator/beam/erl_process.c index 0fa2def5af..c5127bc29d 100644 --- a/erts/emulator/beam/erl_process.c +++ b/erts/emulator/beam/erl_process.c @@ -43,6 +43,9 @@ #include "erl_async.h" #include "dtrace-wrapper.h" +#define ERTS_DELAYED_WAKEUP_INFINITY (~(Uint64) 0) +#define ERTS_DELAYED_WAKEUP_REDUCTIONS ((Uint64) CONTEXT_REDS/2) + #define ERTS_RUNQ_CHECK_BALANCE_REDS_PER_SCHED (2000*CONTEXT_REDS) #define ERTS_RUNQ_CALL_CHECK_BALANCE_REDS \ (ERTS_RUNQ_CHECK_BALANCE_REDS_PER_SCHED/2) @@ -932,9 +935,15 @@ haw_thr_prgr_current_check_progress(ErtsAuxWorkData *awdp) } static ERTS_INLINE erts_aint32_t -handle_delayed_aux_work_wakeup(ErtsAuxWorkData *awdp, erts_aint32_t aux_work) +handle_delayed_aux_work_wakeup(ErtsAuxWorkData *awdp, erts_aint32_t aux_work, int waiting) { int jix, max_jix; + + ASSERT(awdp->delayed_wakeup.next != ERTS_DELAYED_WAKEUP_INFINITY); + + if (!waiting && awdp->delayed_wakeup.next > awdp->esdp->reductions) + return aux_work; + unset_aux_work_flags(awdp->ssi, ERTS_SSI_AUX_WORK_DELAYED_AW_WAKEUP); ERTS_THR_MEMORY_BARRIER; @@ -950,11 +959,14 @@ handle_delayed_aux_work_wakeup(ErtsAuxWorkData *awdp, erts_aint32_t aux_work) set_aux_work_flags_wakeup_nob(ERTS_SCHED_SLEEP_INFO_IX(sched-1), aux_work); } + awdp->delayed_wakeup.next = ERTS_DELAYED_WAKEUP_INFINITY; return aux_work & ~ERTS_SSI_AUX_WORK_DELAYED_AW_WAKEUP; } static ERTS_INLINE void -schedule_aux_work_wakeup(ErtsAuxWorkData *awdp, int sched, erts_aint32_t aux_work) +schedule_aux_work_wakeup(ErtsAuxWorkData *awdp, + int sched, + erts_aint32_t aux_work) { int jix = awdp->delayed_wakeup.sched2jix[sched]; if (jix >= 0) { @@ -967,7 +979,20 @@ schedule_aux_work_wakeup(ErtsAuxWorkData *awdp, int sched, erts_aint32_t aux_wor awdp->delayed_wakeup.job[jix].sched = sched; awdp->delayed_wakeup.job[jix].aux_work = aux_work; } - set_aux_work_flags_wakeup_nob(awdp->ssi, ERTS_SSI_AUX_WORK_DELAYED_AW_WAKEUP); + + if (awdp->delayed_wakeup.next != ERTS_DELAYED_WAKEUP_INFINITY) { + ASSERT(erts_atomic32_read_nob(&awdp->ssi->aux_work) + & ERTS_SSI_AUX_WORK_DELAYED_AW_WAKEUP); + } + else { + awdp->delayed_wakeup.next = (awdp->esdp->reductions + + ERTS_DELAYED_WAKEUP_REDUCTIONS); + + ASSERT(!(erts_atomic32_read_nob(&awdp->ssi->aux_work) + & ERTS_SSI_AUX_WORK_DELAYED_AW_WAKEUP)); + set_aux_work_flags_wakeup_nob(awdp->ssi, + ERTS_SSI_AUX_WORK_DELAYED_AW_WAKEUP); + } } #endif @@ -1046,7 +1071,8 @@ misc_aux_work_clean(ErtsThrQ_t *q, static ERTS_INLINE erts_aint32_t handle_misc_aux_work(ErtsAuxWorkData *awdp, - erts_aint32_t aux_work) + erts_aint32_t aux_work, + int waiting) { ErtsThrQ_t *q = &misc_aux_work_queues[awdp->sched_id].q; @@ -1066,7 +1092,8 @@ handle_misc_aux_work(ErtsAuxWorkData *awdp, static ERTS_INLINE erts_aint32_t handle_misc_aux_work_thr_prgr(ErtsAuxWorkData *awdp, - erts_aint32_t aux_work) + erts_aint32_t aux_work, + int waiting) { if (!erts_thr_progress_has_reached_this(haw_thr_prgr_current(awdp), awdp->misc.thr_prgr)) @@ -1145,7 +1172,8 @@ erts_notify_check_async_ready_queue(void *vno) static ERTS_INLINE erts_aint32_t handle_async_ready(ErtsAuxWorkData *awdp, - erts_aint32_t aux_work) + erts_aint32_t aux_work, + int waiting) { ErtsSchedulerSleepInfo *ssi = awdp->ssi; unset_aux_work_flags(ssi, ERTS_SSI_AUX_WORK_ASYNC_READY); @@ -1167,7 +1195,8 @@ handle_async_ready(ErtsAuxWorkData *awdp, static ERTS_INLINE erts_aint32_t handle_async_ready_clean(ErtsAuxWorkData *awdp, - erts_aint32_t aux_work) + erts_aint32_t aux_work, + int waiting) { void *thr_prgr_p; @@ -1203,7 +1232,7 @@ handle_async_ready_clean(ErtsAuxWorkData *awdp, #endif static ERTS_INLINE erts_aint32_t -handle_fix_alloc(ErtsAuxWorkData *awdp, erts_aint32_t aux_work) +handle_fix_alloc(ErtsAuxWorkData *awdp, erts_aint32_t aux_work, int waiting) { ErtsSchedulerSleepInfo *ssi = awdp->ssi; erts_aint32_t res; @@ -1237,7 +1266,7 @@ erts_alloc_notify_delayed_dealloc(int ix) } static ERTS_INLINE erts_aint32_t -handle_delayed_dealloc(ErtsAuxWorkData *awdp, erts_aint32_t aux_work) +handle_delayed_dealloc(ErtsAuxWorkData *awdp, erts_aint32_t aux_work, int waiting) { ErtsSchedulerSleepInfo *ssi = awdp->ssi; int need_thr_progress = 0; @@ -1275,7 +1304,7 @@ handle_delayed_dealloc(ErtsAuxWorkData *awdp, erts_aint32_t aux_work) } static ERTS_INLINE erts_aint32_t -handle_delayed_dealloc_thr_prgr(ErtsAuxWorkData *awdp, erts_aint32_t aux_work) +handle_delayed_dealloc_thr_prgr(ErtsAuxWorkData *awdp, erts_aint32_t aux_work, int waiting) { ErtsSchedulerSleepInfo *ssi; int need_thr_progress; @@ -1403,7 +1432,7 @@ erts_smp_notify_check_children_needed(void) } static ERTS_INLINE erts_aint32_t -handle_check_children(ErtsAuxWorkData *awdp, erts_aint32_t aux_work) +handle_check_children(ErtsAuxWorkData *awdp, erts_aint32_t aux_work, int waiting) { unset_aux_work_flags(awdp->ssi, ERTS_SSI_AUX_WORK_CHECK_CHILDREN); erts_check_children(); @@ -1426,7 +1455,7 @@ erts_smp_atomic32_t erts_halt_progress; int erts_halt_code; static ERTS_INLINE erts_aint32_t -handle_reap_ports(ErtsAuxWorkData *awdp, erts_aint32_t aux_work) +handle_reap_ports(ErtsAuxWorkData *awdp, erts_aint32_t aux_work, int waiting) { unset_aux_work_flags(awdp->ssi, ERTS_SSI_AUX_WORK_REAP_PORTS); awdp->esdp->run_queue->halt_in_progress = 1; @@ -1474,7 +1503,7 @@ handle_reap_ports(ErtsAuxWorkData *awdp, erts_aint32_t aux_work) #if HAVE_ERTS_MSEG static ERTS_INLINE erts_aint32_t -handle_mseg_cache_check(ErtsAuxWorkData *awdp, erts_aint32_t aux_work) +handle_mseg_cache_check(ErtsAuxWorkData *awdp, erts_aint32_t aux_work, int waiting) { unset_aux_work_flags(awdp->ssi, ERTS_SSI_AUX_WORK_MSEG_CACHE_CHECK); erts_mseg_cache_check(); @@ -1484,7 +1513,7 @@ handle_mseg_cache_check(ErtsAuxWorkData *awdp, erts_aint32_t aux_work) #endif static ERTS_INLINE erts_aint32_t -handle_setup_aux_work_timer(ErtsAuxWorkData *awdp, erts_aint32_t aux_work) +handle_setup_aux_work_timer(ErtsAuxWorkData *awdp, erts_aint32_t aux_work, int waiting) { unset_aux_work_flags(awdp->ssi, ERTS_SSI_AUX_WORK_SET_TMO); setup_aux_work_timer(); @@ -1498,7 +1527,7 @@ handle_aux_work(ErtsAuxWorkData *awdp, erts_aint32_t orig_aux_work, int waiting) #define HANDLE_AUX_WORK(FLG, HNDLR) \ ignore |= FLG; \ if (aux_work & FLG) { \ - aux_work = HNDLR(awdp, aux_work); \ + aux_work = HNDLR(awdp, aux_work, waiting); \ ERTS_DBG_CHK_AUX_WORK_VAL(aux_work); \ if (!(aux_work & ~ignore)) { \ ERTS_DBG_CHK_AUX_WORK_VAL(aux_work); \ @@ -3917,6 +3946,7 @@ init_aux_work_data(ErtsAuxWorkData *awdp, ErtsSchedulerData *esdp, char *dawwp) awdp->async_ready.queue = NULL; #endif #ifdef ERTS_SMP + awdp->delayed_wakeup.next = ERTS_DELAYED_WAKEUP_INFINITY; if (!dawwp) { awdp->delayed_wakeup.job = NULL; awdp->delayed_wakeup.sched2jix = NULL; @@ -4121,6 +4151,9 @@ erts_init_scheduling(int no_schedulers, int no_schedulers_online) #ifdef ERTS_SMP daww_ptr += daww_sz; #endif + + esdp->reductions = 0; + init_sched_wall_time(&esdp->sched_wall_time); } @@ -6664,6 +6697,9 @@ Process *schedule(Process *p, int calls) || p->rcount == 0); } #endif + + esdp->reductions += reds; + erts_smp_runq_lock(rq); ERTS_PROC_REDUCTIONS_EXECUTED(rq, p->prio, reds, actual_reds); diff --git a/erts/emulator/beam/erl_process.h b/erts/emulator/beam/erl_process.h index 9e7a5a5c74..7c481a91dd 100644 --- a/erts/emulator/beam/erl_process.h +++ b/erts/emulator/beam/erl_process.h @@ -439,6 +439,7 @@ typedef struct { #endif #ifdef ERTS_SMP struct { + Uint64 next; int *sched2jix; int jix; ErtsDelayedAuxWorkWakeupJob *job; @@ -481,6 +482,7 @@ struct ErtsSchedulerData_ { ErtsSchedAllocData alloc_data; + Uint64 reductions; ErtsSchedWallTime sched_wall_time; #ifdef ERTS_DO_VERIFY_UNUSED_TEMP_ALLOC diff --git a/erts/emulator/test/bs_bit_binaries_SUITE.erl b/erts/emulator/test/bs_bit_binaries_SUITE.erl index ff1088118d..1428387a65 100644 --- a/erts/emulator/test/bs_bit_binaries_SUITE.erl +++ b/erts/emulator/test/bs_bit_binaries_SUITE.erl @@ -177,14 +177,55 @@ append(Config) when is_list(Config) -> cs_init(), ?line <<(-1):256/signed-unit:8>> = cs(do_append(id(<<>>), 256*8)), ?line <<(-1):256/signed-unit:8>> = cs(do_append2(id(<<>>), 256*4)), + <<(-1):256/signed-unit:8>> = cs(do_append3(id(<<>>), 256*8)), cs_end(). do_append(Bin, N) when N > 0 -> do_append(<<Bin/bits,1:1>>, N-1); do_append(Bin, 0) -> Bin. -do_append2(Bin, N) when N > 0 -> do_append2(<<Bin/bits,3:2>>, N-1); +do_append2(Bin, N) when N > 0 -> do_append2(<<Bin/binary-unit:2,3:2>>, N-1); do_append2(Bin, 0) -> Bin. +do_append3(Bin, N) when N > 0 -> + Bits = bit_size(Bin), + if + Bits rem 2 =:= 0 -> + do_append3(<<Bin/binary-unit:2,1:1>>, N-1); + Bits rem 3 =:= 0 -> + do_append3(<<Bin/binary-unit:3,1:1>>, N-1); + Bits rem 4 =:= 0 -> + do_append3(<<Bin/binary-unit:4,1:1>>, N-1); + Bits rem 5 =:= 0 -> + do_append3(<<Bin/binary-unit:5,1:1>>, N-1); + Bits rem 6 =:= 0 -> + do_append3(<<Bin/binary-unit:6,1:1>>, N-1); + Bits rem 7 =:= 0 -> + do_append3(<<Bin/binary-unit:7,1:1>>, N-1); + Bits rem 8 =:= 0 -> + do_append3(<<Bin/binary-unit:8,1:1>>, N-1); + Bits rem 9 =:= 0 -> + do_append3(<<Bin/binary-unit:9,1:1>>, N-1); + Bits rem 10 =:= 0 -> + do_append3(<<Bin/binary-unit:10,1:1>>, N-1); + Bits rem 11 =:= 0 -> + do_append3(<<Bin/binary-unit:11,1:1>>, N-1); + Bits rem 12 =:= 0 -> + do_append3(<<Bin/binary-unit:12,1:1>>, N-1); + Bits rem 13 =:= 0 -> + do_append3(<<Bin/binary-unit:13,1:1>>, N-1); + Bits rem 14 =:= 0 -> + do_append3(<<Bin/binary-unit:14,1:1>>, N-1); + Bits rem 15 =:= 0 -> + do_append3(<<Bin/binary-unit:15,1:1>>, N-1); + Bits rem 16 =:= 0 -> + do_append3(<<Bin/binary-unit:16,1:1>>, N-1); + Bits rem 17 =:= 0 -> + do_append3(<<Bin/binary-unit:17,1:1>>, N-1); + true -> + do_append3(<<Bin/binary-unit:1,1:1>>, N-1) + end; +do_append3(Bin, 0) -> Bin. + cs_init() -> erts_debug:set_internal_state(available_internal_state, true), ok. diff --git a/erts/emulator/test/bs_construct_SUITE.erl b/erts/emulator/test/bs_construct_SUITE.erl index 8b5c82d968..9c88803fea 100644 --- a/erts/emulator/test/bs_construct_SUITE.erl +++ b/erts/emulator/test/bs_construct_SUITE.erl @@ -28,7 +28,7 @@ mem_leak/1, coerce_to_float/1, bjorn/1, huge_float_field/1, huge_binary/1, system_limit/1, badarg/1, copy_writable_binary/1, kostis/1, dynamic/1, bs_add/1, - otp_7422/1, zero_width/1]). + otp_7422/1, zero_width/1, bad_append/1]). -include_lib("test_server/include/test_server.hrl"). @@ -38,7 +38,8 @@ all() -> [test1, test2, test3, test4, test5, testf, not_used, in_guard, mem_leak, coerce_to_float, bjorn, huge_float_field, huge_binary, system_limit, badarg, - copy_writable_binary, kostis, dynamic, bs_add, otp_7422, zero_width]. + copy_writable_binary, kostis, dynamic, bs_add, otp_7422, zero_width, + bad_append]. groups() -> []. @@ -827,5 +828,49 @@ zero_width(Config) when is_list(Config) -> ?line {'EXIT',{badarg,_}} = (catch <<(id(not_a_number)):0>>), ok. + +bad_append(_) -> + do_bad_append(<<127:1>>, fun append_unit_3/1), + do_bad_append(<<127:2>>, fun append_unit_3/1), + do_bad_append(<<127:17>>, fun append_unit_3/1), + + do_bad_append(<<127:3>>, fun append_unit_4/1), + do_bad_append(<<127:5>>, fun append_unit_4/1), + do_bad_append(<<127:7>>, fun append_unit_4/1), + do_bad_append(<<127:199>>, fun append_unit_4/1), + + do_bad_append(<<127:7>>, fun append_unit_8/1), + do_bad_append(<<127:9>>, fun append_unit_8/1), + + do_bad_append(<<0:8>>, fun append_unit_16/1), + do_bad_append(<<0:15>>, fun append_unit_16/1), + do_bad_append(<<0:17>>, fun append_unit_16/1), + ok. + +do_bad_append(Bin0, Appender) -> + {'EXIT',{badarg,_}} = (catch Appender(Bin0)), + + Bin1 = id(<<0:3,Bin0/bitstring>>), + <<_:3,Bin2/bitstring>> = Bin1, + {'EXIT',{badarg,_}} = (catch Appender(Bin2)), + + %% Create a writable binary. + Empty = id(<<>>), + Bin3 = <<Empty/bitstring,Bin0/bitstring>>, + {'EXIT',{badarg,_}} = (catch Appender(Bin3)), + ok. + +append_unit_3(Bin) -> + <<Bin/binary-unit:3,0:1>>. + +append_unit_4(Bin) -> + <<Bin/binary-unit:4,0:1>>. + +append_unit_8(Bin) -> + <<Bin/binary,0:1>>. + +append_unit_16(Bin) -> + <<Bin/binary-unit:16,0:1>>. + id(I) -> I. |