aboutsummaryrefslogtreecommitdiffstats
path: root/erts/emulator/beam
diff options
context:
space:
mode:
Diffstat (limited to 'erts/emulator/beam')
-rw-r--r--erts/emulator/beam/beam_bp.c1
-rw-r--r--erts/emulator/beam/beam_load.c14
-rw-r--r--erts/emulator/beam/bif.c24
-rw-r--r--erts/emulator/beam/big.c33
-rwxr-xr-xerts/emulator/beam/erl_bif_info.c2
-rw-r--r--erts/emulator/beam/erl_bif_trace.c4
-rw-r--r--erts/emulator/beam/erl_db.c7
-rw-r--r--erts/emulator/beam/erl_init.c16
-rw-r--r--erts/emulator/beam/erl_port_task.c15
-rw-r--r--erts/emulator/beam/erl_process.c165
-rw-r--r--erts/emulator/beam/erl_process.h8
-rw-r--r--erts/emulator/beam/erl_ptab.c9
-rw-r--r--erts/emulator/beam/erl_ptab.h2
-rw-r--r--erts/emulator/beam/erl_thr_progress.c2
-rw-r--r--erts/emulator/beam/erl_thr_progress.h2
-rw-r--r--erts/emulator/beam/erl_unicode.c2
-rw-r--r--erts/emulator/beam/io.c23
-rw-r--r--erts/emulator/beam/utils.c34
18 files changed, 243 insertions, 120 deletions
diff --git a/erts/emulator/beam/beam_bp.c b/erts/emulator/beam/beam_bp.c
index 9b17de34ec..ce025c9b6d 100644
--- a/erts/emulator/beam/beam_bp.c
+++ b/erts/emulator/beam/beam_bp.c
@@ -1580,6 +1580,7 @@ clear_function_break(BeamInstr *pc, Uint break_flags)
}
if (common & ERTS_BPF_META_TRACE) {
MatchSetUnref(bp->meta_ms);
+ bp_meta_unref(bp->meta_pid);
}
if (common & ERTS_BPF_COUNT) {
ASSERT((bp->flags & ERTS_BPF_COUNT_ACTIVE) == 0);
diff --git a/erts/emulator/beam/beam_load.c b/erts/emulator/beam/beam_load.c
index bd4e5a52d0..4193eb4f3f 100644
--- a/erts/emulator/beam/beam_load.c
+++ b/erts/emulator/beam/beam_load.c
@@ -2964,19 +2964,19 @@ gen_put_integer(LoaderState* stp, GenOpArg Fail, GenOpArg Size,
NEW_GENOP(stp, op);
NATIVE_ENDIAN(Flags);
- if (Size.type == TAG_i && Size.val < 0) {
- error:
/* Negative size must fail */
- op->op = genop_badarg_1;
- op->arity = 1;
- op->a[0] = Fail;
- } else if (Size.type == TAG_i) {
+ if (Size.type == TAG_i) {
op->op = genop_i_new_bs_put_integer_imm_4;
op->arity = 4;
op->a[0] = Fail;
op->a[1].type = TAG_u;
if (!safe_mul(Size.val, Unit.val, &op->a[1].val)) {
- goto error;
+ error:
+ op->op = genop_badarg_1;
+ op->arity = 1;
+ op->a[0] = Fail;
+ op->next = NULL;
+ return op;
}
op->a[1].val = Size.val * Unit.val;
op->a[2].type = Flags.type;
diff --git a/erts/emulator/beam/bif.c b/erts/emulator/beam/bif.c
index 9c438679ea..ff237b6a78 100644
--- a/erts/emulator/beam/bif.c
+++ b/erts/emulator/beam/bif.c
@@ -2543,7 +2543,7 @@ BIF_RETTYPE insert_element_3(BIF_ALIST_3)
Eterm* hp;
Uint arity;
Eterm res;
- Sint ix;
+ Sint ix, c1, c2;
if (is_not_tuple(BIF_ARG_2) || is_not_small(BIF_ARG_1)) {
BIF_ERROR(BIF_P, BADARG);
@@ -2561,14 +2561,12 @@ BIF_RETTYPE insert_element_3(BIF_ALIST_3)
res = make_tuple(hp);
*hp = make_arityval(arity + 1);
- ix--;
- arity -= ix;
-
- while (ix--) { *++hp = *++ptr; }
+ c1 = ix - 1;
+ c2 = arity - ix + 1;
+ while (c1--) { *++hp = *++ptr; }
*++hp = BIF_ARG_3;
-
- while(arity--) { *++hp = *++ptr; }
+ while (c2--) { *++hp = *++ptr; }
BIF_RET(res);
}
@@ -2579,7 +2577,7 @@ BIF_RETTYPE delete_element_2(BIF_ALIST_3)
Eterm* hp;
Uint arity;
Eterm res;
- Sint ix;
+ Sint ix, c1, c2;
if (is_not_tuple(BIF_ARG_2) || is_not_small(BIF_ARG_1)) {
BIF_ERROR(BIF_P, BADARG);
@@ -2597,14 +2595,12 @@ BIF_RETTYPE delete_element_2(BIF_ALIST_3)
res = make_tuple(hp);
*hp = make_arityval(arity - 1);
- ix--;
- arity -= ix;
-
- while (ix--) { *++hp = *++ptr; }
+ c1 = ix - 1;
+ c2 = arity - ix;
+ while (c1--) { *++hp = *++ptr; }
++ptr;
-
- while(arity--) { *++hp = *++ptr; }
+ while (c2--) { *++hp = *++ptr; }
BIF_RET(res);
}
diff --git a/erts/emulator/beam/big.c b/erts/emulator/beam/big.c
index acfcc845e4..6f9b171224 100644
--- a/erts/emulator/beam/big.c
+++ b/erts/emulator/beam/big.c
@@ -150,14 +150,14 @@
#define D2GTE(a1,a0,b1,b0) (!D2LT(a1,a0,b1,b0))
#define D2LTE(a1,a0,b1,b0) (!D2GT(a1,a0,b1,b0))
-// Add (A+B), A=(a1B+a0) B=(b1B+b0)
+/* Add (A+B), A=(a1B+a0) B=(b1B+b0) */
#define D2ADD(a1,a0,b1,b0,c1,c0) do { \
ErtsDigit __ci = 0; \
DSUM(a0,b0,__ci,c0); \
DSUMc(a1,b1,__ci,c1); \
} while(0)
-// Subtract (A-B), A=(a1B+a0), B=(b1B+b0) (A>=B)
+/* Subtract (A-B), A=(a1B+a0), B=(b1B+b0) (A>=B) */
#define D2SUB(a1,a0,b1,b0,c1,c0) do { \
ErtsDigit __bi; \
DSUB(a0,b0,__bi,c0); \
@@ -1337,7 +1337,7 @@ static dsize_t I_lshift(ErtsDigit* x, dsize_t xl, Sint y,
while(bw--)
*r++ = 0;
- if (sw) { // NOTE! x >> 32 is not = 0!
+ if (sw) { /* NOTE! x >> 32 is not = 0! */
while(xl--) {
a0 = (*x << sw) | a1;
a1 = (*x >> (D_EXP - sw));
@@ -1384,7 +1384,7 @@ static dsize_t I_lshift(ErtsDigit* x, dsize_t xl, Sint y,
x += (xl-1);
r += (rl-1);
xl -= bw;
- if (sw) { // NOTE! x >> 32 is not = 0!
+ if (sw) { /* NOTE! x >> 32 is not = 0! */
while(xl--) {
a1 = (*x >> sw) | a0;
a0 = (*x << (D_EXP-sw));
@@ -2468,7 +2468,7 @@ int term_equals_2pow32(Eterm x)
if (!is_big(x))
return 0;
bp = big_val(x);
-#if D_EXP == 16 // 16 bit platfrom not really supported!!!
+#if D_EXP == 16 /* 16 bit platfrom not really supported!!! */
return (BIG_SIZE(bp) == 3) && !BIG_DIGIT(bp,0) && !BIG_DIGIT(bp,1) &&
BIG_DIGIT(bp,2) == 1;
#elif D_EXP == 32
@@ -2528,17 +2528,18 @@ const byte d_base_exp_lookup[] = { 31, 19, 15, 13, 11, 11, 10, 9, 9, 8, 8, 8, 8,
* end
* How much can the characters which fit in 31 bit represent
*/
-const Uint d_base_base_lookup[] = { 2147483648, 1162261467, 1073741824,
- 1220703125, 362797056, 1977326743, 1073741824, 387420489, 1000000000,
- 214358881, 429981696, 815730721, 1475789056, 170859375, 268435456,
- 410338673, 612220032, 893871739, 1280000000, 1801088541, 113379904,
- 148035889, 191102976, 244140625, 308915776, 387420489, 481890304,
- 594823321, 729000000, 887503681, 1073741824, 1291467969, 1544804416,
- 1838265625, 60466176, 69343957, 79235168, 90224199, 102400000,
- 115856201, 130691232, 147008443, 164916224, 184528125, 205962976,
- 229345007, 254803968, 282475249, 312500000, 345025251, 380204032,
- 418195493, 459165024, 503284375, 550731776, 601692057, 656356768,
- 714924299, 777600000, 844596301, 916132832, 992436543, 1073741824 };
+const Uint d_base_base_lookup[] = { 2147483648u, 1162261467u, 1073741824u,
+ 1220703125u, 362797056u, 1977326743u, 1073741824u, 387420489u,
+ 1000000000u, 214358881u, 429981696u, 815730721u, 1475789056u,
+ 170859375u, 268435456u, 410338673u, 612220032u, 893871739u, 1280000000u,
+ 1801088541u, 113379904u, 148035889u, 191102976u, 244140625u, 308915776u,
+ 387420489u, 481890304u, 594823321u, 729000000u, 887503681u, 1073741824u,
+ 1291467969u, 1544804416u, 1838265625u, 60466176u, 69343957u, 79235168u,
+ 90224199u, 102400000u, 115856201u, 130691232u, 147008443u, 164916224u,
+ 184528125u, 205962976u, 229345007u, 254803968u, 282475249u, 312500000u,
+ 345025251u, 380204032u, 418195493u, 459165024u, 503284375u, 550731776u,
+ 601692057u, 656356768u, 714924299u, 777600000u, 844596301u, 916132832u,
+ 992436543u, 1073741824u };
Eterm erts_chars_to_integer(Process *BIF_P, char *bytes,
Uint size, const int base) {
diff --git a/erts/emulator/beam/erl_bif_info.c b/erts/emulator/beam/erl_bif_info.c
index 8582a8954b..379d3eecc6 100755
--- a/erts/emulator/beam/erl_bif_info.c
+++ b/erts/emulator/beam/erl_bif_info.c
@@ -3077,7 +3077,7 @@ BIF_RETTYPE is_process_alive_1(BIF_ALIST_1)
if (BIF_ARG_1 == BIF_P->common.id)
BIF_RET(am_true);
- rp = erts_proc_lookup(BIF_ARG_1);
+ rp = erts_proc_lookup_raw(BIF_ARG_1);
if (!rp) {
BIF_RET(am_false);
}
diff --git a/erts/emulator/beam/erl_bif_trace.c b/erts/emulator/beam/erl_bif_trace.c
index 41c98bbffb..559cb3efa1 100644
--- a/erts/emulator/beam/erl_bif_trace.c
+++ b/erts/emulator/beam/erl_bif_trace.c
@@ -1224,9 +1224,7 @@ trace_info_func(Process* p, Eterm func_spec, Eterm key)
match_spec_meta = NIL;
}
if (r & FUNC_TRACE_COUNT_TRACE) {
- c = count < 0 ?
- erts_make_integer(-count-1, p) :
- erts_make_integer(count, p);
+ c = erts_make_integer(count, p);
}
if (r & FUNC_TRACE_TIME_TRACE) {
ct = call_time;
diff --git a/erts/emulator/beam/erl_db.c b/erts/emulator/beam/erl_db.c
index d0afc8ed8d..98c2988323 100644
--- a/erts/emulator/beam/erl_db.c
+++ b/erts/emulator/beam/erl_db.c
@@ -264,9 +264,10 @@ static void schedule_free_dbtable(DbTable* tb)
* function has returned).
*/
ASSERT(erts_refc_read(&tb->common.ref, 0) == 0);
- erts_schedule_thr_prgr_later_op(free_dbtable,
- (void *) tb,
- &tb->release.data);
+ erts_schedule_thr_prgr_later_cleanup_op(free_dbtable,
+ (void *) tb,
+ &tb->release.data,
+ sizeof(DbTable));
}
static ERTS_INLINE void db_init_lock(DbTable* tb, int use_frequent_read_lock,
diff --git a/erts/emulator/beam/erl_init.c b/erts/emulator/beam/erl_init.c
index e7e4030900..e6a96d427f 100644
--- a/erts/emulator/beam/erl_init.c
+++ b/erts/emulator/beam/erl_init.c
@@ -532,6 +532,8 @@ void erts_usage(void)
erts_fprintf(stderr, " see the erl(1) documentation for more info.\n");
erts_fprintf(stderr, "-sws val set scheduler wakeup strategy, valid values are:\n");
erts_fprintf(stderr, " default|legacy.\n");
+ erts_fprintf(stderr, "-swct val set scheduler wake cleanup threshold, valid values are:\n");
+ erts_fprintf(stderr, " very_lazy|lazy|medium|eager|very_eager.\n");
erts_fprintf(stderr, "-swt val set scheduler wakeup threshold, valid values are:\n");
erts_fprintf(stderr, " very_low|low|medium|high|very_high.\n");
erts_fprintf(stderr, "-sss size suggested stack size in kilo words for scheduler threads,\n");
@@ -1413,7 +1415,17 @@ erl_start(int argc, char **argv)
erts_usage();
}
}
- else if (sys_strcmp("wt", sub_param) == 0) {
+ else if (has_prefix("wct", sub_param)) {
+ arg = get_arg(sub_param+3, argv[i+1], &i);
+ if (erts_sched_set_wake_cleanup_threshold(arg) != 0) {
+ erts_fprintf(stderr, "scheduler wake cleanup threshold: %s\n",
+ arg);
+ erts_usage();
+ }
+ VERBOSE(DEBUG_SYSTEM,
+ ("scheduler wake cleanup threshold: %s\n", arg));
+ }
+ else if (has_prefix("wt", sub_param)) {
arg = get_arg(sub_param+2, argv[i+1], &i);
if (erts_sched_set_wakeup_other_thresold(arg) != 0) {
erts_fprintf(stderr, "scheduler wakeup threshold: %s\n",
@@ -1423,7 +1435,7 @@ erl_start(int argc, char **argv)
VERBOSE(DEBUG_SYSTEM,
("scheduler wakeup threshold: %s\n", arg));
}
- else if (sys_strcmp("ws", sub_param) == 0) {
+ else if (has_prefix("ws", sub_param)) {
arg = get_arg(sub_param+2, argv[i+1], &i);
if (erts_sched_set_wakeup_other_type(arg) != 0) {
erts_fprintf(stderr, "scheduler wakeup strategy: %s\n",
diff --git a/erts/emulator/beam/erl_port_task.c b/erts/emulator/beam/erl_port_task.c
index ce045ec94e..0ed08bee01 100644
--- a/erts/emulator/beam/erl_port_task.c
+++ b/erts/emulator/beam/erl_port_task.c
@@ -151,9 +151,10 @@ static ERTS_INLINE void
schedule_port_task_free(ErtsPortTask *ptp)
{
#ifdef ERTS_SMP
- erts_schedule_thr_prgr_later_op(call_port_task_free,
- (void *) ptp,
- &ptp->u.release);
+ erts_schedule_thr_prgr_later_cleanup_op(call_port_task_free,
+ (void *) ptp,
+ &ptp->u.release,
+ sizeof(ErtsPortTask));
#else
port_task_free(ptp);
#endif
@@ -772,9 +773,10 @@ static void
schedule_port_task_handle_list_free(ErtsPortTaskHandleList *pthlp)
{
#ifdef ERTS_SMP
- erts_schedule_thr_prgr_later_op(free_port_task_handle_list,
- (void *) pthlp,
- &pthlp->u.release);
+ erts_schedule_thr_prgr_later_cleanup_op(free_port_task_handle_list,
+ (void *) pthlp,
+ &pthlp->u.release,
+ sizeof(ErtsPortTaskHandleList));
#else
erts_free(ERTS_ALC_T_PT_HNDL_LIST, pthlp);
#endif
@@ -1999,6 +2001,7 @@ begin_port_cleanup(Port *pp, ErtsPortTask **execqp, int *processing_busy_q_p)
* Schedule cleanup of port structure...
*/
#ifdef ERTS_SMP
+ /* Has to be more or less immediate to release any driver */
erts_schedule_thr_prgr_later_op(release_port,
(void *) pp,
&pp->common.u.release);
diff --git a/erts/emulator/beam/erl_process.c b/erts/emulator/beam/erl_process.c
index 00247b387a..5d9c5af55f 100644
--- a/erts/emulator/beam/erl_process.c
+++ b/erts/emulator/beam/erl_process.c
@@ -146,6 +146,14 @@ extern BeamInstr beam_continue_exit[];
int erts_sched_compact_load;
Uint erts_no_schedulers;
+#define ERTS_THR_PRGR_LATER_CLEANUP_OP_THRESHOLD_VERY_LAZY (4*1024*1024)
+#define ERTS_THR_PRGR_LATER_CLEANUP_OP_THRESHOLD_LAZY (512*1024)
+#define ERTS_THR_PRGR_LATER_CLEANUP_OP_THRESHOLD_MEDIUM (64*1024)
+#define ERTS_THR_PRGR_LATER_CLEANUP_OP_THRESHOLD_EAGER (16*1024)
+#define ERTS_THR_PRGR_LATER_CLEANUP_OP_THRESHOLD_VERY_EAGER (1024)
+
+static UWord thr_prgr_later_cleanup_op_threshold = ERTS_THR_PRGR_LATER_CLEANUP_OP_THRESHOLD_MEDIUM;
+
ErtsPTab erts_proc erts_align_attribute(ERTS_CACHE_LINE_SIZE);
int erts_sched_thread_suggested_stack_size = -1;
@@ -496,6 +504,7 @@ erts_init_process(int ncpu, int proc_tab_size)
#endif
(ErtsPTabElementCommon *) &erts_invalid_process.common,
proc_tab_size,
+ sizeof(Process),
"process_table");
last_reductions = 0;
@@ -909,6 +918,53 @@ unset_aux_work_flags(ErtsSchedulerSleepInfo *ssi, erts_aint32_t flgs)
#ifdef ERTS_SMP
static ERTS_INLINE void
+haw_chk_later_cleanup_op_wakeup(ErtsAuxWorkData *awdp, ErtsThrPrgrVal val)
+{
+ if (awdp->later_op.first
+ && erts_thr_progress_cmp(val, awdp->later_op.thr_prgr) >= 0) {
+ awdp->later_op.size = thr_prgr_later_cleanup_op_threshold;
+ }
+}
+
+static ERTS_INLINE void
+haw_thr_prgr_wakeup(ErtsAuxWorkData *awdp, ErtsThrPrgrVal val)
+{
+ int cmp = erts_thr_progress_cmp(val, awdp->latest_wakeup);
+ if (cmp != 0) {
+ if (cmp > 0) {
+ awdp->latest_wakeup = val;
+ haw_chk_later_cleanup_op_wakeup(awdp, val);
+ }
+ erts_thr_progress_wakeup(awdp->esdp, val);
+ }
+}
+
+static ERTS_INLINE void
+haw_thr_prgr_soft_wakeup(ErtsAuxWorkData *awdp, ErtsThrPrgrVal val)
+{
+ if (erts_thr_progress_cmp(val, awdp->latest_wakeup) > 0) {
+ awdp->latest_wakeup = val;
+ haw_chk_later_cleanup_op_wakeup(awdp, val);
+ erts_thr_progress_wakeup(awdp->esdp, val);
+ }
+}
+
+static ERTS_INLINE void
+haw_thr_prgr_later_cleanup_op_wakeup(ErtsAuxWorkData *awdp, ErtsThrPrgrVal val, UWord size)
+{
+ if (erts_thr_progress_cmp(val, awdp->latest_wakeup) > 0) {
+ awdp->later_op.thr_prgr = val;
+ if (awdp->later_op.size > size)
+ awdp->later_op.size -= size;
+ else {
+ awdp->latest_wakeup = val;
+ awdp->later_op.size = thr_prgr_later_cleanup_op_threshold;
+ erts_thr_progress_wakeup(awdp->esdp, val);
+ }
+ }
+}
+
+static ERTS_INLINE void
haw_thr_prgr_current_reset(ErtsAuxWorkData *awdp)
{
awdp->current_thr_prgr = ERTS_THR_PRGR_INVALID;
@@ -1066,8 +1122,7 @@ misc_aux_work_clean(ErtsThrQ_t *q,
case ERTS_THR_Q_NEED_THR_PRGR:
#ifdef ERTS_SMP
set_aux_work_flags(awdp->ssi, ERTS_SSI_AUX_WORK_MISC_THR_PRGR);
- erts_thr_progress_wakeup(awdp->esdp,
- erts_thr_q_need_thr_progress(q));
+ haw_thr_prgr_soft_wakeup(awdp, erts_thr_q_need_thr_progress(q));
#endif
case ERTS_THR_Q_CLEAN:
break;
@@ -1225,8 +1280,7 @@ handle_async_ready_clean(ErtsAuxWorkData *awdp,
return aux_work & ~ERTS_SSI_AUX_WORK_ASYNC_READY_CLEAN;
#ifdef ERTS_SMP
case ERTS_ASYNC_READY_NEED_THR_PRGR:
- erts_thr_progress_wakeup(awdp->esdp,
- awdp->async_ready.thr_prgr);
+ haw_thr_prgr_soft_wakeup(awdp, awdp->async_ready.thr_prgr);
awdp->async_ready.need_thr_prgr = 1;
return aux_work & ~ERTS_SSI_AUX_WORK_ASYNC_READY_CLEAN;
#endif
@@ -1300,7 +1354,7 @@ handle_delayed_dealloc(ErtsAuxWorkData *awdp, erts_aint32_t aux_work, int waitin
awdp->dd.thr_prgr = wakeup;
set_aux_work_flags(ssi, ERTS_SSI_AUX_WORK_DD_THR_PRGR);
awdp->dd.thr_prgr = wakeup;
- erts_thr_progress_wakeup(awdp->esdp, wakeup);
+ haw_thr_prgr_soft_wakeup(awdp, wakeup);
}
else if (awdp->dd.completed_callback) {
awdp->dd.completed_callback(awdp->dd.completed_arg);
@@ -1341,7 +1395,7 @@ handle_delayed_dealloc_thr_prgr(ErtsAuxWorkData *awdp, erts_aint32_t aux_work, i
if (wakeup == ERTS_THR_PRGR_INVALID)
wakeup = erts_thr_progress_later(awdp->esdp);
awdp->dd.thr_prgr = wakeup;
- erts_thr_progress_wakeup(awdp->esdp, wakeup);
+ haw_thr_prgr_soft_wakeup(awdp, wakeup);
}
else {
unset_aux_work_flags(ssi, ERTS_SSI_AUX_WORK_DD_THR_PRGR);
@@ -1376,6 +1430,7 @@ handle_thr_prgr_later_op(ErtsAuxWorkData *awdp, erts_aint32_t aux_work, int wait
}
lop->func(lop->data);
if (!awdp->later_op.first) {
+ awdp->later_op.size = thr_prgr_later_cleanup_op_threshold;
awdp->later_op.last = NULL;
unset_aux_work_flags(awdp->ssi,
ERTS_SSI_AUX_WORK_THR_PRGR_LATER_OP);
@@ -1386,6 +1441,29 @@ handle_thr_prgr_later_op(ErtsAuxWorkData *awdp, erts_aint32_t aux_work, int wait
return aux_work;
}
+static ERTS_INLINE ErtsThrPrgrVal
+enqueue_later_op(ErtsSchedulerData *esdp,
+ void (*later_func)(void *),
+ void *later_data,
+ ErtsThrPrgrLaterOp *lop)
+{
+ ErtsThrPrgrVal later = erts_thr_progress_later(esdp);
+ ASSERT(esdp);
+
+ lop->func = later_func;
+ lop->data = later_data;
+ lop->later = later;
+ lop->next = NULL;
+ if (!esdp->aux_work_data.later_op.last)
+ esdp->aux_work_data.later_op.first = lop;
+ else
+ esdp->aux_work_data.later_op.last->next = lop;
+ esdp->aux_work_data.later_op.last = lop;
+ set_aux_work_flags_wakeup_nob(esdp->ssi,
+ ERTS_SSI_AUX_WORK_THR_PRGR_LATER_OP);
+ return later;
+}
+
#endif /* ERTS_SMP */
void
@@ -1396,31 +1474,24 @@ erts_schedule_thr_prgr_later_op(void (*later_func)(void *),
#ifndef ERTS_SMP
later_func(later_data);
#else
- ErtsSchedulerData *esdp;
- ErtsAuxWorkData *awdp;
- int request_wakeup = 1;
-
- esdp = erts_get_scheduler_data();
- ASSERT(esdp);
- awdp = &esdp->aux_work_data;
+ ErtsSchedulerData *esdp = erts_get_scheduler_data();
+ ErtsThrPrgrVal later = enqueue_later_op(esdp, later_func, later_data, lop);
+ haw_thr_prgr_wakeup(&esdp->aux_work_data, later);
+#endif
+}
- lop->func = later_func;
- lop->data = later_data;
- lop->later = erts_thr_progress_later(esdp);
- lop->next = NULL;
- if (!awdp->later_op.last)
- awdp->later_op.first = lop;
- else {
- ErtsThrPrgrLaterOp *last = awdp->later_op.last;
- last->next = lop;
- if (erts_thr_progress_equal(last->later, lop->later))
- request_wakeup = 0;
- }
- awdp->later_op.last = lop;
- set_aux_work_flags_wakeup_nob(awdp->ssi,
- ERTS_SSI_AUX_WORK_THR_PRGR_LATER_OP);
- if (request_wakeup)
- erts_thr_progress_wakeup(esdp, lop->later);
+void
+erts_schedule_thr_prgr_later_cleanup_op(void (*later_func)(void *),
+ void *later_data,
+ ErtsThrPrgrLaterOp *lop,
+ UWord size)
+{
+#ifndef ERTS_SMP
+ later_func(later_data);
+#else
+ ErtsSchedulerData *esdp = erts_get_scheduler_data();
+ ErtsThrPrgrVal later = enqueue_later_op(esdp, later_func, later_data, lop);
+ haw_thr_prgr_later_cleanup_op_wakeup(&esdp->aux_work_data, later, size);
#endif
}
@@ -1811,7 +1882,7 @@ erts_set_aux_work_timeout(int ix, erts_aint32_t type, int enable)
ERTS_DBG_CHK_AUX_WORK_VAL(type);
ERTS_DBG_CHK_AUX_WORK_VAL(erts_atomic32_read_nob(&aux_work_tmo->type[ix]));
-// erts_fprintf(stderr, "t(%d, 0x%x, %d)\n", ix, type, enable);
+ /* erts_fprintf(stderr, "t(%d, 0x%x, %d)\n", ix, type, enable); */
if (!enable) {
old = erts_atomic32_read_band_mb(&aux_work_tmo->type[ix], ~type);
@@ -2554,6 +2625,8 @@ set_no_active_runqs(int active)
erts_aint32_t exp = erts_smp_atomic32_read_nob(&balance_info.no_runqs);
while (1) {
erts_aint32_t act, new;
+ if ((exp & ERTS_NO_RUNQS_MASK) == active)
+ break;
new = exp & (ERTS_NO_RUNQS_MASK << ERTS_NO_USED_RUNQS_SHIFT);
new |= active & ERTS_NO_RUNQS_MASK;
act = erts_smp_atomic32_cmpxchg_nob(&balance_info.no_runqs, new, exp);
@@ -3100,9 +3173,6 @@ evacuate_run_queue(ErtsRunQueue *rq,
if (notify)
smp_notify_inc_runq(to_rq);
}
-
- if (ERTS_EMPTY_RUNQ(rq))
- empty_runq(rq);
}
static int
@@ -3996,9 +4066,8 @@ static void
change_no_used_runqs(int used)
{
ErtsMigrationPaths *new_mpaths, *old_mpaths;
- int active, qix;
+ int qix;
erts_smp_mtx_lock(&balance_info.update_mtx);
- get_no_runqs(&active, NULL);
set_no_used_runqs(used);
old_mpaths = erts_get_migration_paths_managed();
@@ -4358,6 +4427,25 @@ erts_sched_set_busy_wait_threshold(char *str)
return 0;
}
+
+int
+erts_sched_set_wake_cleanup_threshold(char *str)
+{
+ if (sys_strcmp(str, "very_lazy") == 0)
+ thr_prgr_later_cleanup_op_threshold = ERTS_THR_PRGR_LATER_CLEANUP_OP_THRESHOLD_VERY_LAZY;
+ else if (sys_strcmp(str, "lazy") == 0)
+ thr_prgr_later_cleanup_op_threshold = ERTS_THR_PRGR_LATER_CLEANUP_OP_THRESHOLD_LAZY;
+ else if (sys_strcmp(str, "medium") == 0)
+ thr_prgr_later_cleanup_op_threshold = ERTS_THR_PRGR_LATER_CLEANUP_OP_THRESHOLD_MEDIUM;
+ else if (sys_strcmp(str, "eager") == 0)
+ thr_prgr_later_cleanup_op_threshold = ERTS_THR_PRGR_LATER_CLEANUP_OP_THRESHOLD_EAGER;
+ else if (sys_strcmp(str, "very_eager") == 0)
+ thr_prgr_later_cleanup_op_threshold = ERTS_THR_PRGR_LATER_CLEANUP_OP_THRESHOLD_VERY_EAGER;
+ else
+ return EINVAL;
+ return 0;
+}
+
static void
init_aux_work_data(ErtsAuxWorkData *awdp, ErtsSchedulerData *esdp, char *dawwp)
{
@@ -4365,10 +4453,13 @@ init_aux_work_data(ErtsAuxWorkData *awdp, ErtsSchedulerData *esdp, char *dawwp)
awdp->esdp = esdp;
awdp->ssi = esdp ? esdp->ssi : NULL;
#ifdef ERTS_SMP
+ awdp->latest_wakeup = ERTS_THR_PRGR_VAL_FIRST;
awdp->misc.thr_prgr = ERTS_THR_PRGR_VAL_WAITING;
awdp->dd.thr_prgr = ERTS_THR_PRGR_VAL_WAITING;
awdp->dd.completed_callback = NULL;
awdp->dd.completed_arg = NULL;
+ awdp->later_op.thr_prgr = ERTS_THR_PRGR_VAL_FIRST;
+ awdp->later_op.size = 0;
awdp->later_op.first = NULL;
awdp->later_op.last = NULL;
#endif
@@ -4604,7 +4695,7 @@ erts_init_scheduling(int no_schedulers, int no_schedulers_online)
schdlr_sspnd.msb.ongoing = 0;
erts_smp_atomic32_init_nob(&schdlr_sspnd.active, no_schedulers);
schdlr_sspnd.msb.procs = NULL;
- init_no_runqs(no_schedulers, no_schedulers_online);
+ init_no_runqs(no_schedulers_online, no_schedulers_online);
balance_info.last_active_runqs = no_schedulers;
erts_smp_mtx_init(&balance_info.update_mtx, "migration_info_update");
balance_info.forced_check_balance = 0;
diff --git a/erts/emulator/beam/erl_process.h b/erts/emulator/beam/erl_process.h
index 6d1032c292..3d3579fa7e 100644
--- a/erts/emulator/beam/erl_process.h
+++ b/erts/emulator/beam/erl_process.h
@@ -430,6 +430,7 @@ typedef struct {
ErtsSchedulerSleepInfo *ssi;
#ifdef ERTS_SMP
ErtsThrPrgrVal current_thr_prgr;
+ ErtsThrPrgrVal latest_wakeup;
#endif
struct {
int ix;
@@ -444,6 +445,8 @@ typedef struct {
void (*completed_arg)(void *);
} dd;
struct {
+ ErtsThrPrgrVal thr_prgr;
+ UWord size;
ErtsThrPrgrLaterOp *first;
ErtsThrPrgrLaterOp *last;
} later_op;
@@ -1298,10 +1301,15 @@ ERTS_GLB_INLINE int erts_proclist_is_last(ErtsProcList *list,
int erts_sched_set_wakeup_other_thresold(char *str);
int erts_sched_set_wakeup_other_type(char *str);
int erts_sched_set_busy_wait_threshold(char *str);
+int erts_sched_set_wake_cleanup_threshold(char *);
void erts_schedule_thr_prgr_later_op(void (*)(void *),
void *,
ErtsThrPrgrLaterOp *);
+void erts_schedule_thr_prgr_later_cleanup_op(void (*)(void *),
+ void *,
+ ErtsThrPrgrLaterOp *,
+ UWord);
#if defined(ERTS_SMP) && defined(ERTS_ENABLE_LOCK_CHECK)
int erts_dbg_check_halloc_lock(Process *p);
diff --git a/erts/emulator/beam/erl_ptab.c b/erts/emulator/beam/erl_ptab.c
index 87beeafa1a..5bbc71c659 100644
--- a/erts/emulator/beam/erl_ptab.c
+++ b/erts/emulator/beam/erl_ptab.c
@@ -421,6 +421,7 @@ erts_ptab_init_table(ErtsPTab *ptab,
void (*release_element)(void *),
ErtsPTabElementCommon *invalid_element,
int size,
+ UWord element_size,
char *name)
{
size_t tab_sz;
@@ -443,6 +444,7 @@ erts_ptab_init_table(ErtsPTab *ptab,
bits = erts_fit_in_bits_int32((Sint32) size - 1);
}
+ ptab->r.o.element_size = element_size;
ptab->r.o.max = size;
tab_sz = ERTS_ALC_CACHE_LINE_ALIGN_SIZE(size*sizeof(erts_smp_atomic_t));
@@ -670,9 +672,10 @@ erts_ptab_delete_element(ErtsPTab *ptab,
}
if (ptab->r.o.release_element)
- erts_schedule_thr_prgr_later_op(ptab->r.o.release_element,
- (void *) ptab_el,
- &ptab_el->u.release);
+ erts_schedule_thr_prgr_later_cleanup_op(ptab->r.o.release_element,
+ (void *) ptab_el,
+ &ptab_el->u.release,
+ ptab->r.o.element_size);
}
/*
diff --git a/erts/emulator/beam/erl_ptab.h b/erts/emulator/beam/erl_ptab.h
index 8a130f42a3..7fa1251900 100644
--- a/erts/emulator/beam/erl_ptab.h
+++ b/erts/emulator/beam/erl_ptab.h
@@ -109,6 +109,7 @@ typedef struct {
ErtsPTabElementCommon *invalid_element;
Eterm invalid_data;
void (*release_element)(void *);
+ UWord element_size;
} ErtsPTabReadOnlyData;
typedef struct {
@@ -177,6 +178,7 @@ void erts_ptab_init_table(ErtsPTab *ptab,
void (*release_element)(void *),
ErtsPTabElementCommon *invalid_element,
int size,
+ UWord element_size,
char *name);
int erts_ptab_new_element(ErtsPTab *ptab,
ErtsPTabElementCommon *ptab_el,
diff --git a/erts/emulator/beam/erl_thr_progress.c b/erts/emulator/beam/erl_thr_progress.c
index 1292cb0678..cf5e3dc012 100644
--- a/erts/emulator/beam/erl_thr_progress.c
+++ b/erts/emulator/beam/erl_thr_progress.c
@@ -418,7 +418,7 @@ erts_thr_progress_pre_init(void)
{
intrnl = NULL;
erts_tsd_key_create(&erts_thr_prgr_data_key__);
- init_nob(&erts_thr_prgr__.current, 0);
+ init_nob(&erts_thr_prgr__.current, ERTS_THR_PRGR_VAL_FIRST);
}
void
diff --git a/erts/emulator/beam/erl_thr_progress.h b/erts/emulator/beam/erl_thr_progress.h
index 1416aa6166..1aeecf2b06 100644
--- a/erts/emulator/beam/erl_thr_progress.h
+++ b/erts/emulator/beam/erl_thr_progress.h
@@ -108,6 +108,8 @@ struct ErtsThrPrgrLaterOp_ {
#ifdef ERTS_SMP
+/* ERTS_THR_PRGR_VAL_FIRST should only be used when initializing... */
+#define ERTS_THR_PRGR_VAL_FIRST ((ErtsThrPrgrVal) 0)
#define ERTS_THR_PRGR_VAL_WAITING (~((ErtsThrPrgrVal) 0))
#define ERTS_THR_PRGR_INVALID (~((ErtsThrPrgrVal) 0))
diff --git a/erts/emulator/beam/erl_unicode.c b/erts/emulator/beam/erl_unicode.c
index fa53fd0937..ad6f8b993a 100644
--- a/erts/emulator/beam/erl_unicode.c
+++ b/erts/emulator/beam/erl_unicode.c
@@ -724,7 +724,7 @@ L_Again: /* Restart with sublist, old listend was pushed on stack */
hp = HAlloc(p, 2);
obj = CDR(objp);
ioterm = CONS(hp, rest_term, obj);
- //(*left) = 0;
+ /* (*left) = 0; */
goto done;
}
if (rest_term != NIL) {
diff --git a/erts/emulator/beam/io.c b/erts/emulator/beam/io.c
index 8c67f731f4..f93b599632 100644
--- a/erts/emulator/beam/io.c
+++ b/erts/emulator/beam/io.c
@@ -2651,11 +2651,17 @@ void erts_init_io(int port_tab_size,
int port_tab_size_ignore_files)
{
ErlDrvEntry** dp;
+ UWord common_element_size;
erts_smp_rwmtx_opt_t drv_list_rwmtx_opts = ERTS_SMP_RWMTX_OPT_DEFAULT_INITER;
drv_list_rwmtx_opts.type = ERTS_SMP_RWMTX_TYPE_EXTREMELY_FREQUENT_READ;
drv_list_rwmtx_opts.lived = ERTS_SMP_RWMTX_LONG_LIVED;
+ common_element_size = ERTS_ALC_DATA_ALIGN_SIZE(sizeof(Port));
+ common_element_size += ERTS_ALC_DATA_ALIGN_SIZE(sizeof(ErtsPortTaskBusyPortQ));
+ common_element_size += 10; /* name */
#ifdef ERTS_SMP
+ common_element_size += sizeof(erts_mtx_t);
+
init_xports_list_alloc();
#endif
@@ -2684,6 +2690,7 @@ void erts_init_io(int port_tab_size,
NULL,
(ErtsPTabElementCommon *) &erts_invalid_port.common,
port_tab_size,
+ common_element_size, /* Doesn't need to be excact */
"port_table");
erts_smp_atomic_init_nob(&erts_bytes_out, 0);
@@ -4140,7 +4147,7 @@ port_sig_call(Port *prt,
ErlOffHeap *ohp;
Process *rp;
ErtsProcLocks rp_locks = 0;
- Uint hsz;
+ Sint hsz;
rp = erts_proc_lookup_raw(sigdp->caller);
if (!rp)
@@ -4257,7 +4264,7 @@ erts_port_call(Process* c_p,
switch (try_call_res) {
case ERTS_TRY_IMM_DRV_CALL_OK: {
Eterm *hp, *hp_end;
- Uint hsz;
+ Sint hsz;
unsigned ret_flags = 0U;
Eterm term;
@@ -5934,10 +5941,6 @@ int driver_outputv(ErlDrvPort ix, char* hbuf, ErlDrvSizeT hlen,
return driver_output2(ix, hbuf, hlen, NULL, 0);
size = vec->size - skip; /* Size of remaining bytes in vector */
- ASSERT(hlen >= 0); /* debug only */
- if (hlen < 0)
- hlen = 0;
-
prt = erts_drvport2port_state(ix, &state);
if (prt == ERTS_INVALID_ERL_DRV_PORT)
return -1;
@@ -5960,7 +5963,7 @@ int driver_outputv(ErlDrvPort ix, char* hbuf, ErlDrvSizeT hlen,
binv++;
n--;
} else {
- iov->iov_base += skip;
+ iov->iov_base = ((char *)(iov->iov_base)) + skip;
iov->iov_len -= skip;
skip = 0;
}
@@ -6405,7 +6408,7 @@ int driver_enqv(ErlDrvPort ix, ErlIOVec* vec, ErlDrvSizeT skip)
n--;
}
else {
- iov->iov_base += skip;
+ iov->iov_base = ((char *)(iov->iov_base)) + skip;
iov->iov_len -= skip;
skip = 0;
}
@@ -6470,7 +6473,7 @@ int driver_pushqv(ErlDrvPort ix, ErlIOVec* vec, ErlDrvSizeT skip)
n--;
}
else {
- iov->iov_base += skip;
+ iov->iov_base = ((char *)(iov->iov_base)) + skip;
iov->iov_len -= skip;
skip = 0;
}
@@ -6529,7 +6532,7 @@ ErlDrvSizeT driver_deq(ErlDrvPort ix, ErlDrvSizeT size)
q->v_head++;
}
else {
- q->v_head->iov_base += size;
+ q->v_head->iov_base = ((char *)(q->v_head->iov_base)) + size;
q->v_head->iov_len -= size;
size = 0;
}
diff --git a/erts/emulator/beam/utils.c b/erts/emulator/beam/utils.c
index a8f15fdc38..d5d97d748a 100644
--- a/erts/emulator/beam/utils.c
+++ b/erts/emulator/beam/utils.c
@@ -2713,25 +2713,26 @@ tailrecur_ne:
case SMALL_FLOAT:
GET_DOUBLE(bw, f2);
if (f2.fd < MAX_LOSSLESS_FLOAT && f2.fd > MIN_LOSSLESS_FLOAT) {
- // Float is within the no loss limit
+ /* Float is within the no loss limit */
f1.fd = signed_val(aw);
j = float_comp(f1.fd, f2.fd);
#if ERTS_SIZEOF_ETERM == 8
} else if (f2.fd > (double) (MAX_SMALL + 1)) {
- // Float is a positive bignum, i.e. bigger
+ /* Float is a positive bignum, i.e. bigger */
j = -1;
} else if (f2.fd < (double) (MIN_SMALL - 1)) {
- // Float is a negative bignum, i.e. smaller
+ /* Float is a negative bignum, i.e. smaller */
j = 1;
- } else { // Float is a Sint but less precise
+ } else {
+ /* Float is a Sint but less precise */
j = signed_val(aw) - (Sint) f2.fd;
}
#else
} else {
- // If float is positive it is bigger than small
+ /* If float is positive it is bigger than small */
j = (f2.fd > 0.0) ? -1 : 1;
}
-#endif // ERTS_SIZEOF_ETERM == 8
+#endif /* ERTS_SIZEOF_ETERM == 8 */
break;
case FLOAT_BIG:
{
@@ -2743,18 +2744,18 @@ tailrecur_ne:
GET_DOUBLE(bw, f2);
if ((f2.fd < (double) (MAX_SMALL + 1))
&& (f2.fd > (double) (MIN_SMALL - 1))) {
- // Float is a Sint
+ /* Float is a Sint */
j = big_sign(aw) ? -1 : 1;
} else if (big_arity(aw) > BIG_ARITY_FLOAT_MAX
|| pow(2.0,(big_arity(aw)-1)*D_EXP) > fabs(f2.fd)) {
- // If bignum size shows that it is bigger than the abs float
+ /* If bignum size shows that it is bigger than the abs float */
j = big_sign(aw) ? -1 : 1;
} else if (big_arity(aw) < BIG_ARITY_FLOAT_MAX
&& (pow(2.0,(big_arity(aw))*D_EXP)-1.0) < fabs(f2.fd)) {
- // If bignum size shows that it is smaller than the abs float
+ /* If bignum size shows that it is smaller than the abs float */
j = f2.fd < 0 ? 1 : -1;
} else if (f2.fd < MAX_LOSSLESS_FLOAT && f2.fd > MIN_LOSSLESS_FLOAT) {
- // Float is within the no loss limit
+ /* Float is within the no loss limit */
if (big_to_double(aw, &f1.fd) < 0) {
j = big_sign(aw) ? -1 : 1;
} else {
@@ -2771,25 +2772,26 @@ tailrecur_ne:
case FLOAT_SMALL:
GET_DOUBLE(aw, f1);
if (f1.fd < MAX_LOSSLESS_FLOAT && f1.fd > MIN_LOSSLESS_FLOAT) {
- // Float is within the no loss limit
+ /* Float is within the no loss limit */
f2.fd = signed_val(bw);
j = float_comp(f1.fd, f2.fd);
#if ERTS_SIZEOF_ETERM == 8
} else if (f1.fd > (double) (MAX_SMALL + 1)) {
- // Float is a positive bignum, i.e. bigger
+ /* Float is a positive bignum, i.e. bigger */
j = 1;
} else if (f1.fd < (double) (MIN_SMALL - 1)) {
- // Float is a negative bignum, i.e. smaller
+ /* Float is a negative bignum, i.e. smaller */
j = -1;
- } else { // Float is a Sint but less precise it
+ } else {
+ /* Float is a Sint but less precise it */
j = (Sint) f1.fd - signed_val(bw);
}
#else
} else {
- // If float is positive it is bigger than small
+ /* If float is positive it is bigger than small */
j = (f1.fd > 0.0) ? 1 : -1;
}
-#endif // ERTS_SIZEOF_ETERM == 8
+#endif /* ERTS_SIZEOF_ETERM == 8 */
break;
default:
j = b_tag - a_tag;