aboutsummaryrefslogtreecommitdiffstats
path: root/erts/emulator
diff options
context:
space:
mode:
Diffstat (limited to 'erts/emulator')
-rw-r--r--erts/emulator/Makefile.in6
-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.tab6
-rw-r--r--erts/emulator/beam/big.c33
-rw-r--r--erts/emulator/beam/break.c1
-rw-r--r--erts/emulator/beam/dist.c16
-rw-r--r--erts/emulator/beam/erl_alloc.c89
-rw-r--r--erts/emulator/beam/erl_alloc.h20
-rw-r--r--erts/emulator/beam/erl_alloc.types1
-rw-r--r--erts/emulator/beam/erl_alloc_util.c89
-rwxr-xr-xerts/emulator/beam/erl_bif_info.c62
-rw-r--r--erts/emulator/beam/erl_bif_port.c173
-rw-r--r--erts/emulator/beam/erl_bif_trace.c4
-rw-r--r--erts/emulator/beam/erl_instrument.c97
-rw-r--r--erts/emulator/beam/erl_lock_check.c4
-rw-r--r--erts/emulator/beam/erl_monitors.c20
-rw-r--r--erts/emulator/beam/erl_monitors.h2
-rw-r--r--erts/emulator/beam/erl_mtrace.c44
-rw-r--r--erts/emulator/beam/erl_node_tables.c6
-rw-r--r--erts/emulator/beam/erl_port.h22
-rw-r--r--erts/emulator/beam/erl_port_task.c28
-rw-r--r--erts/emulator/beam/erl_port_task.h2
-rw-r--r--erts/emulator/beam/erl_process.c4
-rw-r--r--erts/emulator/beam/erl_process.h3
-rw-r--r--erts/emulator/beam/erl_process_dump.c37
-rw-r--r--erts/emulator/beam/erl_unicode.c2
-rw-r--r--erts/emulator/beam/external.c15
-rw-r--r--erts/emulator/beam/io.c331
-rw-r--r--erts/emulator/beam/utils.c34
-rw-r--r--erts/emulator/drivers/common/efile_drv.c108
-rw-r--r--erts/emulator/drivers/common/erl_efile.h16
-rw-r--r--erts/emulator/drivers/common/inet_drv.c137
-rw-r--r--erts/emulator/drivers/common/zlib_drv.c2
-rw-r--r--erts/emulator/drivers/unix/ttsl_drv.c45
-rw-r--r--erts/emulator/drivers/unix/unix_efile.c2
-rw-r--r--erts/emulator/drivers/win32/ttsl_drv.c4
-rw-r--r--erts/emulator/hipe/hipe_native_bif.c4
-rw-r--r--erts/emulator/hipe/hipe_x86_gc.h2
-rw-r--r--erts/emulator/hipe/hipe_x86_signal.c1
-rw-r--r--erts/emulator/internal_doc/dec.erl5
-rw-r--r--erts/emulator/pcre/pcre_exec.c2
-rw-r--r--erts/emulator/sys/common/erl_mseg.c14
-rw-r--r--erts/emulator/sys/unix/sys_float.c14
-rwxr-xr-xerts/emulator/sys/win32/sys.c26
-rw-r--r--erts/emulator/sys/win32/sys_float.c4
-rw-r--r--erts/emulator/test/busy_port_SUITE.erl2
-rw-r--r--erts/emulator/test/code_parallel_load_SUITE.erl1
48 files changed, 875 insertions, 680 deletions
diff --git a/erts/emulator/Makefile.in b/erts/emulator/Makefile.in
index 6c42faf34e..2031ec3a4c 100644
--- a/erts/emulator/Makefile.in
+++ b/erts/emulator/Makefile.in
@@ -483,8 +483,10 @@ endif
ifdef DTRACE_ENABLED
# global.h causes problems by including dtrace-wrapper.h which includes
# the autogenerated erlang_dtrace.h ... so make erlang_dtrace.h very early.
-generate: $(TARGET)/erlang_dtrace.h $(GENERATE)
+DTRACE_HEADERS = $(TARGET)/erlang_dtrace.h
+generate: $(DTRACE_HEADERS) $(GENERATE)
else
+DTRACE_HEADERS =
generate: $(GENERATE)
endif
@@ -870,7 +872,7 @@ $(OBJDIR)/%.o: hipe/%.c
$(BINDIR)/hipe_mkliterals$(TF_MARKER): $(OBJDIR)/hipe_mkliterals.o
$(ld_verbose)$(CC) $(CFLAGS) $(INCLUDES) -o $@ $<
-$(OBJDIR)/hipe_mkliterals.o: $(HIPE_ASM) $(TTF_DIR)/erl_alloc_types.h \
+$(OBJDIR)/hipe_mkliterals.o: $(HIPE_ASM) $(TTF_DIR)/erl_alloc_types.h $(DTRACE_HEADERS) \
$(TTF_DIR)/OPCODES-GENERATED $(TARGET)/TABLES-GENERATED
$(TTF_DIR)/hipe_literals.h: $(BINDIR)/hipe_mkliterals$(TF_MARKER)
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.tab b/erts/emulator/beam/bif.tab
index 8bc994c8c3..dc8e9101de 100644
--- a/erts/emulator/beam/bif.tab
+++ b/erts/emulator/beam/bif.tab
@@ -154,8 +154,10 @@ bif erts_internal:port_command/3
bif erts_internal:port_control/3
bif erts_internal:port_close/1
bif erts_internal:port_connect/2
-bif erts_internal:port_set_data/2
-bif erts_internal:port_get_data/1
+
+# inet_db support
+bif erlang:port_set_data/2
+bif erlang:port_get_data/1
# Tracing & debugging.
bif erlang:trace_pattern/2
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/break.c b/erts/emulator/beam/break.c
index 9aa1e5f30d..e34fc8388c 100644
--- a/erts/emulator/beam/break.c
+++ b/erts/emulator/beam/break.c
@@ -331,6 +331,7 @@ print_process_info(int to, void *to_arg, Process *p)
erts_print(to, to_arg, "Heap unused: %bpu\n", (p->hend - p->htop));
erts_print(to, to_arg, "OldHeap unused: %bpu\n",
(OLD_HEAP(p) == NULL) ? 0 : (OLD_HEND(p) - OLD_HTOP(p)) );
+ erts_print(to, to_arg, "Memory: %beu\n", erts_process_memory(p));
if (garbing) {
print_garb_info(to, to_arg, p);
diff --git a/erts/emulator/beam/dist.c b/erts/emulator/beam/dist.c
index 0781665f05..44f4eb9d43 100644
--- a/erts/emulator/beam/dist.c
+++ b/erts/emulator/beam/dist.c
@@ -455,7 +455,7 @@ int erts_do_net_exits(DistEntry *dep, Eterm reason)
Eterm nd_reason = (reason == am_no_network
? am_no_network
: am_net_kernel_terminated);
- erts_smp_rwmtx_rwlock(&erts_dist_table_rwmtx);
+ erts_smp_rwmtx_rlock(&erts_dist_table_rwmtx);
for (tdep = erts_hidden_dist_entries; tdep; tdep = tdep->next)
no_dist_port++;
@@ -464,7 +464,7 @@ int erts_do_net_exits(DistEntry *dep, Eterm reason)
/* KILL all port controllers */
if (no_dist_port == 0)
- erts_smp_rwmtx_rwunlock(&erts_dist_table_rwmtx);
+ erts_smp_rwmtx_runlock(&erts_dist_table_rwmtx);
else {
Eterm def_buf[128];
int i = 0;
@@ -483,7 +483,7 @@ int erts_do_net_exits(DistEntry *dep, Eterm reason)
ASSERT(is_internal_port(tdep->cid));
dist_port[i++] = tdep->cid;
}
- erts_smp_rwmtx_rwunlock(&erts_dist_table_rwmtx);
+ erts_smp_rwmtx_runlock(&erts_dist_table_rwmtx);
for (i = 0; i < no_dist_port; i++) {
Port *prt = erts_port_lookup(dist_port[i],
@@ -2560,9 +2560,9 @@ BIF_RETTYPE setnode_2(BIF_ALIST_2)
erts_smp_proc_unlock(net_kernel, ERTS_PROC_LOCK_MAIN);
#ifdef DEBUG
- erts_smp_rwmtx_rwlock(&erts_dist_table_rwmtx);
+ erts_smp_rwmtx_rlock(&erts_dist_table_rwmtx);
ASSERT(!erts_visible_dist_entries && !erts_hidden_dist_entries);
- erts_smp_rwmtx_rwunlock(&erts_dist_table_rwmtx);
+ erts_smp_rwmtx_runlock(&erts_dist_table_rwmtx);
#endif
erts_smp_proc_unlock(BIF_P, ERTS_PROC_LOCK_MAIN);
@@ -2912,7 +2912,7 @@ BIF_RETTYPE nodes_1(BIF_ALIST_1)
length = 0;
- erts_smp_rwmtx_rwlock(&erts_dist_table_rwmtx);
+ erts_smp_rwmtx_rlock(&erts_dist_table_rwmtx);
ASSERT(erts_no_of_not_connected_dist_entries >= 0);
ASSERT(erts_no_of_hidden_dist_entries >= 0);
@@ -2929,7 +2929,7 @@ BIF_RETTYPE nodes_1(BIF_ALIST_1)
result = NIL;
if (length == 0) {
- erts_smp_rwmtx_rwunlock(&erts_dist_table_rwmtx);
+ erts_smp_rwmtx_runlock(&erts_dist_table_rwmtx);
goto done;
}
@@ -2958,7 +2958,7 @@ BIF_RETTYPE nodes_1(BIF_ALIST_1)
hp += 2;
}
ASSERT(endp == hp);
- erts_smp_rwmtx_rwunlock(&erts_dist_table_rwmtx);
+ erts_smp_rwmtx_runlock(&erts_dist_table_rwmtx);
done:
UnUseTmpHeap(2,BIF_P);
diff --git a/erts/emulator/beam/erl_alloc.c b/erts/emulator/beam/erl_alloc.c
index d748f86d75..c19a2647e4 100644
--- a/erts/emulator/beam/erl_alloc.c
+++ b/erts/emulator/beam/erl_alloc.c
@@ -495,6 +495,38 @@ refuse_af_strategy(struct au_init *init)
static void hdbg_init(void);
#endif
+static void adjust_fix_alloc_sizes(UWord extra_block_size)
+{
+
+ if (extra_block_size && erts_allctrs_info[ERTS_ALC_A_FIXED_SIZE].enabled) {
+ int j;
+
+#ifdef ERTS_SMP
+ if (erts_allctrs_info[ERTS_ALC_A_FIXED_SIZE].thr_spec) {
+ int i;
+ ErtsAllocatorThrSpec_t* tspec;
+
+ tspec = &erts_allctr_thr_spec[ERTS_ALC_A_FIXED_SIZE];
+ ASSERT(tspec->enabled);
+
+ for (i=0; i < tspec->size; i++) {
+ Allctr_t* allctr = tspec->allctr[i];
+ for (j=0; j < ERTS_ALC_NO_FIXED_SIZES; ++j) {
+ allctr->fix[j].type_size += extra_block_size;
+ }
+ }
+ }
+ else
+#endif
+ {
+ Allctr_t* allctr = erts_allctrs_info[ERTS_ALC_A_FIXED_SIZE].extra;
+ for (j=0; j < ERTS_ALC_NO_FIXED_SIZES; ++j) {
+ allctr->fix[j].type_size += extra_block_size;
+ }
+ }
+ }
+}
+
void
erts_alloc_init(int *argc, char **argv, ErtsAllocInitOpts *eaiop)
{
@@ -515,9 +547,9 @@ erts_alloc_init(int *argc, char **argv, ErtsAllocInitOpts *eaiop)
= sizeof(Process);
#if !HALFWORD_HEAP
fix_type_sizes[ERTS_ALC_FIX_TYPE_IX(ERTS_ALC_T_MONITOR_SH)]
- = ERTS_MONITOR_SH_SIZE;
+ = ERTS_MONITOR_SH_SIZE * sizeof(Uint);
fix_type_sizes[ERTS_ALC_FIX_TYPE_IX(ERTS_ALC_T_NLINK_SH)]
- = ERTS_LINK_SH_SIZE;
+ = ERTS_LINK_SH_SIZE * sizeof(Uint);
#endif
fix_type_sizes[ERTS_ALC_FIX_TYPE_IX(ERTS_ALC_T_DRV_EV_D_STATE)]
= sizeof(ErtsDrvEventDataState);
@@ -538,6 +570,8 @@ erts_alloc_init(int *argc, char **argv, ErtsAllocInitOpts *eaiop)
if (ncpu < 1)
ncpu = 1;
+ erts_tsd_key_create(&erts_allctr_prelock_tsd_key);
+
erts_sys_alloc_init();
erts_init_utils_mem();
@@ -768,7 +802,7 @@ erts_alloc_init(int *argc, char **argv, ErtsAllocInitOpts *eaiop)
#ifdef DEBUG
extra_block_size += install_debug_functions();
#endif
-
+ adjust_fix_alloc_sizes(extra_block_size);
}
void
@@ -3107,6 +3141,55 @@ erts_request_alloc_info(struct process *c_p,
return 1;
}
+/*
+ * The allocator wrapper prelocking stuff below is about the locking order.
+ * It only affects wrappers (erl_mtrace.c and erl_instrument.c) that keep locks
+ * during alloc/realloc/free.
+ *
+ * Some query functions in erl_alloc_util.c lock the allocator mutex and then
+ * use erts_printf that in turn may call the sys allocator through the wrappers.
+ * To avoid breaking locking order these query functions first "pre-locks" all
+ * allocator wrappers.
+ */
+ErtsAllocatorWrapper_t *erts_allctr_wrappers;
+int erts_allctr_wrapper_prelocked = 0;
+erts_tsd_key_t erts_allctr_prelock_tsd_key;
+
+void erts_allctr_wrapper_prelock_init(ErtsAllocatorWrapper_t* wrapper)
+{
+ ASSERT(wrapper->lock && wrapper->unlock);
+ wrapper->next = erts_allctr_wrappers;
+ erts_allctr_wrappers = wrapper;
+}
+
+void erts_allctr_wrapper_pre_lock(void)
+{
+ if (erts_allctr_wrappers) {
+ ErtsAllocatorWrapper_t* wrapper = erts_allctr_wrappers;
+ for ( ; wrapper; wrapper = wrapper->next) {
+ wrapper->lock();
+ }
+ ASSERT(!erts_allctr_wrapper_prelocked);
+ erts_allctr_wrapper_prelocked = 1;
+ erts_tsd_set(erts_allctr_prelock_tsd_key, (void*)1);
+ }
+}
+
+void erts_allctr_wrapper_pre_unlock(void)
+{
+ if (erts_allctr_wrappers) {
+ ErtsAllocatorWrapper_t* wrapper = erts_allctr_wrappers;
+
+ erts_allctr_wrapper_prelocked = 0;
+ erts_tsd_set(erts_allctr_prelock_tsd_key, (void*)0);
+ for ( ; wrapper; wrapper = wrapper->next) {
+ wrapper->unlock();
+ }
+ }
+}
+
+
+
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\
* Deprecated functions *
* *
diff --git a/erts/emulator/beam/erl_alloc.h b/erts/emulator/beam/erl_alloc.h
index ba5ec9c367..9cafd8ddc8 100644
--- a/erts/emulator/beam/erl_alloc.h
+++ b/erts/emulator/beam/erl_alloc.h
@@ -135,6 +135,18 @@ typedef struct {
extern ErtsAllocatorThrSpec_t erts_allctr_thr_spec[ERTS_ALC_A_MAX+1];
+typedef struct ErtsAllocatorWrapper_t_ {
+ void (*lock)(void);
+ void (*unlock)(void);
+ struct ErtsAllocatorWrapper_t_* next;
+}ErtsAllocatorWrapper_t;
+ErtsAllocatorWrapper_t *erts_allctr_wrappers;
+extern int erts_allctr_wrapper_prelocked;
+extern erts_tsd_key_t erts_allctr_prelock_tsd_key;
+void erts_allctr_wrapper_prelock_init(ErtsAllocatorWrapper_t* wrapper);
+void erts_allctr_wrapper_pre_lock(void);
+void erts_allctr_wrapper_pre_unlock(void);
+
void erts_alloc_register_scheduler(void *vesdp);
#ifdef ERTS_SMP
void erts_alloc_scheduler_handle_delayed_dealloc(void *vesdp,
@@ -188,6 +200,7 @@ void *erts_realloc(ErtsAlcType_t type, void *ptr, Uint size);
void erts_free(ErtsAlcType_t type, void *ptr);
void *erts_alloc_fnf(ErtsAlcType_t type, Uint size);
void *erts_realloc_fnf(ErtsAlcType_t type, void *ptr, Uint size);
+int erts_is_allctr_wrapper_prelocked(void);
#endif /* #if !ERTS_ALC_DO_INLINE */
@@ -258,6 +271,13 @@ void *erts_realloc_fnf(ErtsAlcType_t type, void *ptr, Uint size)
size);
}
+ERTS_ALC_INLINE
+int erts_is_allctr_wrapper_prelocked(void)
+{
+ return erts_allctr_wrapper_prelocked /* locked */
+ && !!erts_tsd_get(erts_allctr_prelock_tsd_key); /* by me */
+}
+
#endif /* #if ERTS_ALC_DO_INLINE || defined(ERTS_ALC_INTERNAL__) */
#define ERTS_ALC_GET_THR_IX() ((int) erts_get_scheduler_id())
diff --git a/erts/emulator/beam/erl_alloc.types b/erts/emulator/beam/erl_alloc.types
index 5e3615ccc2..5a92ab7f24 100644
--- a/erts/emulator/beam/erl_alloc.types
+++ b/erts/emulator/beam/erl_alloc.types
@@ -272,6 +272,7 @@ type CODE_IX_LOCK_Q SHORT_LIVED SYSTEM code_ix_lock_q
type PROC_INTERVAL LONG_LIVED SYSTEM process_interval
type BUSY_CALLER_TAB SHORT_LIVED SYSTEM busy_caller_table
type BUSY_CALLER SHORT_LIVED SYSTEM busy_caller
+type PORT_DATA_HEAP STANDARD SYSTEM port_data_heap
+if threads_no_smp
# Need thread safe allocs, but std_alloc and fix_alloc are not;
diff --git a/erts/emulator/beam/erl_alloc_util.c b/erts/emulator/beam/erl_alloc_util.c
index ac7f420708..cbeb2c1e3a 100644
--- a/erts/emulator/beam/erl_alloc_util.c
+++ b/erts/emulator/beam/erl_alloc_util.c
@@ -588,17 +588,21 @@ do { \
#ifdef DEBUG
#ifdef USE_THREADS
+# ifdef ERTS_SMP
+# define IS_ACTUALLY_BLOCKING (erts_thr_progress_is_blocking())
+# else
+# define IS_ACTUALLY_BLOCKING 0
+# endif
#define ERTS_ALCU_DBG_CHK_THR_ACCESS(A) \
do { \
- if (!(A)->thread_safe) { \
- if (!(A)->debug.saved_tid) { \
+ if (!(A)->thread_safe && !IS_ACTUALLY_BLOCKING) { \
+ if (!(A)->debug.saved_tid) { \
(A)->debug.tid = erts_thr_self(); \
(A)->debug.saved_tid = 1; \
} \
else { \
ERTS_SMP_LC_ASSERT( \
- ethr_equal_tids((A)->debug.tid, erts_thr_self()) \
- || erts_thr_progress_is_blocking()); \
+ ethr_equal_tids((A)->debug.tid, erts_thr_self())); \
} \
} \
} while (0)
@@ -878,8 +882,10 @@ erts_alcu_fix_alloc_shrink(Allctr_t *allctr, erts_aint32_t flgs)
#ifdef ERTS_SMP
-#define ERTS_ALCU_DD_FIX_TYPE_OFFS \
- ((sizeof(ErtsAllctrDDBlock_t)-1)/sizeof(UWord) + 1)
+typedef struct {
+ ErtsAllctrDDBlock_t ddblock__; /* must be first */
+ ErtsAlcType_t fix_type;
+}ErtsAllctrFixDDBlock_t;
static ERTS_INLINE Allctr_t*
@@ -1180,7 +1186,7 @@ handle_delayed_dealloc(Allctr_t *allctr,
if (fix) {
ErtsAlcType_t type;
- type = (ErtsAlcType_t) ((UWord *) ptr)[ERTS_ALCU_DD_FIX_TYPE_OFFS];
+ type = ((ErtsAllctrFixDDBlock_t*) ptr)->fix_type;
ix = type - ERTS_ALC_N_MIN_A_FIXED_SIZE;
ERTS_DBG_CHK_FIX_LIST(allctr, fix, ix, 1);
fix[ix].used--;
@@ -1242,7 +1248,7 @@ enqueue_dealloc_other_instance(ErtsAlcType_t type,
int cinit)
{
if (allctr->fix)
- ((UWord *) ptr)[ERTS_ALCU_DD_FIX_TYPE_OFFS] = (UWord) type;
+ ((ErtsAllctrFixDDBlock_t*) ptr)->fix_type = type;
if (ddq_enqueue(type, &allctr->dd.q, ptr, cinit))
erts_alloc_notify_delayed_dealloc(allctr->ix);
@@ -2508,12 +2514,6 @@ static erts_mtx_t init_atoms_mtx;
static void
init_atoms(Allctr_t *allctr)
{
-
-#ifdef USE_THREADS
- if (allctr && allctr->thread_safe)
- erts_mtx_unlock(&allctr->mutex);
-#endif
-
erts_mtx_lock(&init_atoms_mtx);
if (!atoms_initialized) {
@@ -2604,18 +2604,13 @@ init_atoms(Allctr_t *allctr)
fix_type_atoms[ix] = am_atom_put(name, len);
}
}
-
- if (allctr) {
+ if (allctr && !allctr->atoms_initialized) {
make_name_atoms(allctr);
(*allctr->init_atoms)();
-#ifdef USE_THREADS
- if (allctr->thread_safe)
- erts_mtx_lock(&allctr->mutex);
-#endif
allctr->atoms_initialized = 1;
}
@@ -3243,17 +3238,21 @@ erts_alcu_info_options(Allctr_t *allctr,
{
Eterm res;
+ if (hpp || szp)
+ ensure_atoms_initialized(allctr);
#ifdef USE_THREADS
- if (allctr->thread_safe)
+ if (allctr->thread_safe) {
+ erts_allctr_wrapper_pre_lock();
erts_mtx_lock(&allctr->mutex);
+ }
#endif
- if (hpp || szp)
- ensure_atoms_initialized(allctr);
res = info_options(allctr, print_to_p, print_to_arg, hpp, szp);
#ifdef USE_THREADS
- if (allctr->thread_safe)
+ if (allctr->thread_safe) {
erts_mtx_unlock(&allctr->mutex);
+ erts_allctr_wrapper_pre_unlock();
+ }
#endif
return res;
}
@@ -3280,16 +3279,18 @@ erts_alcu_sz_info(Allctr_t *allctr,
return am_false;
}
+ if (hpp || szp)
+ ensure_atoms_initialized(allctr);
+
#ifdef USE_THREADS
- if (allctr->thread_safe)
+ if (allctr->thread_safe) {
+ erts_allctr_wrapper_pre_lock();
erts_mtx_lock(&allctr->mutex);
+ }
#endif
ERTS_ALCU_DBG_CHK_THR_ACCESS(allctr);
- if (hpp || szp)
- ensure_atoms_initialized(allctr);
-
/* Update sbc values not continously updated */
allctr->sbcs.blocks.curr.no
= allctr->sbcs.curr.norm.mseg.no + allctr->sbcs.curr.norm.sys_alloc.no;
@@ -3325,13 +3326,16 @@ erts_alcu_sz_info(Allctr_t *allctr,
#ifdef USE_THREADS
- if (allctr->thread_safe)
+ if (allctr->thread_safe) {
erts_mtx_unlock(&allctr->mutex);
+ erts_allctr_wrapper_pre_unlock();
+ }
#endif
return res;
}
+
Eterm
erts_alcu_info(Allctr_t *allctr,
int begin_max_period,
@@ -3352,16 +3356,18 @@ erts_alcu_info(Allctr_t *allctr,
return am_false;
}
+ if (hpp || szp)
+ ensure_atoms_initialized(allctr);
+
#ifdef USE_THREADS
- if (allctr->thread_safe)
+ if (allctr->thread_safe) {
+ erts_allctr_wrapper_pre_lock();
erts_mtx_lock(&allctr->mutex);
+ }
#endif
ERTS_ALCU_DBG_CHK_THR_ACCESS(allctr);
- if (hpp || szp)
- ensure_atoms_initialized(allctr);
-
/* Update sbc values not continously updated */
allctr->sbcs.blocks.curr.no
= allctr->sbcs.curr.norm.mseg.no + allctr->sbcs.curr.norm.sys_alloc.no;
@@ -3414,8 +3420,10 @@ erts_alcu_info(Allctr_t *allctr,
#ifdef USE_THREADS
- if (allctr->thread_safe)
+ if (allctr->thread_safe) {
erts_mtx_unlock(&allctr->mutex);
+ erts_allctr_wrapper_pre_unlock();
+ }
#endif
return res;
@@ -3487,7 +3495,9 @@ do_erts_alcu_alloc(ErtsAlcType_t type, void *extra, Uint size)
fix = allctr->fix;
if (fix) {
int ix = type - ERTS_ALC_N_MIN_A_FIXED_SIZE;
+ ASSERT((unsigned)ix < ERTS_ALC_NO_FIXED_SIZES);
ERTS_DBG_CHK_FIX_LIST(allctr, fix, ix, 1);
+ ASSERT(size <= fix[ix].type_size);
fix[ix].used++;
res = fix[ix].list;
if (res) {
@@ -3508,8 +3518,7 @@ do_erts_alcu_alloc(ErtsAlcType_t type, void *extra, Uint size)
ERTS_DBG_CHK_FIX_LIST(allctr, fix, ix, 0);
return res;
}
- if (size < 2*sizeof(UWord))
- size += sizeof(UWord);
+ size = fix[ix].type_size;
if (fix[ix].limit < fix[ix].used)
fix[ix].limit = fix[ix].used;
if (fix[ix].max_used < fix[ix].used)
@@ -4198,9 +4207,8 @@ erts_alcu_start(Allctr_t *allctr, AllctrInit_t *init)
#if ERTS_SMP
if (init->tpref) {
Uint sz = ABLK_HDR_SZ;
- sz += ERTS_ALCU_DD_FIX_TYPE_OFFS*sizeof(UWord);
- if (init->fix)
- sz += sizeof(UWord);
+ sz += (init->fix ?
+ sizeof(ErtsAllctrFixDDBlock_t) : sizeof(ErtsAllctrDDBlock_t));
sz = UNIT_CEILING(sz);
if (sz > allctr->min_block_size)
allctr->min_block_size = sz;
@@ -4325,6 +4333,9 @@ erts_alcu_start(Allctr_t *allctr, AllctrInit_t *init)
allctr->fix[i].list = NULL;
allctr->fix[i].allocated = 0;
allctr->fix[i].used = 0;
+#ifdef ERTS_SMP
+ ASSERT(allctr->fix[i].type_size >= sizeof(ErtsAllctrFixDDBlock_t));
+#endif
}
}
diff --git a/erts/emulator/beam/erl_bif_info.c b/erts/emulator/beam/erl_bif_info.c
index 59843649f0..54eefe8d12 100755
--- a/erts/emulator/beam/erl_bif_info.c
+++ b/erts/emulator/beam/erl_bif_info.c
@@ -489,27 +489,6 @@ collect_one_suspend_monitor(ErtsSuspendMonitor *smon, void *vsmicp)
}
}
-
-static void one_link_size(ErtsLink *lnk, void *vpu)
-{
- Uint *pu = vpu;
- *pu += ERTS_LINK_SIZE*sizeof(Uint);
- if(!IS_CONST(lnk->pid))
- *pu += NC_HEAP_SIZE(lnk->pid)*sizeof(Uint);
- if (lnk->type != LINK_NODE && ERTS_LINK_ROOT(lnk) != NULL) {
- erts_doforall_links(ERTS_LINK_ROOT(lnk),&one_link_size,vpu);
- }
-}
-static void one_mon_size(ErtsMonitor *mon, void *vpu)
-{
- Uint *pu = vpu;
- *pu += ERTS_MONITOR_SIZE*sizeof(Uint);
- if(!IS_CONST(mon->pid))
- *pu += NC_HEAP_SIZE(mon->pid)*sizeof(Uint);
- if(!IS_CONST(mon->ref))
- *pu += NC_HEAP_SIZE(mon->ref)*sizeof(Uint);
-}
-
/*
* process_info/[1,2]
*/
@@ -1423,41 +1402,8 @@ process_info_aux(Process *BIF_P,
}
case am_memory: { /* Memory consumed in bytes */
- ErlMessage *mp;
- Uint size = 0;
Uint hsz = 3;
- struct saved_calls *scb;
- size += sizeof(Process);
-
- ERTS_SMP_MSGQ_MV_INQ2PRIVQ(rp);
-
- erts_doforall_links(ERTS_P_LINKS(rp), &one_link_size, &size);
- erts_doforall_monitors(ERTS_P_MONITORS(rp), &one_mon_size, &size);
- size += (rp->heap_sz + rp->mbuf_sz) * sizeof(Eterm);
- if (rp->old_hend && rp->old_heap)
- size += (rp->old_hend - rp->old_heap) * sizeof(Eterm);
-
- size += rp->msg.len * sizeof(ErlMessage);
-
- for (mp = rp->msg.first; mp; mp = mp->next)
- if (mp->data.attached)
- size += erts_msg_attached_data_size(mp)*sizeof(Eterm);
-
- if (rp->arg_reg != rp->def_arg_reg) {
- size += rp->arity * sizeof(rp->arg_reg[0]);
- }
-
- if (rp->psd)
- size += sizeof(ErtsPSD);
-
- scb = ERTS_PROC_GET_SAVED_CALLS_BUF(rp);
- if (scb) {
- size += (sizeof(struct saved_calls)
- + (scb->len-1) * sizeof(scb->ct[0]));
- }
-
- size += erts_dicts_mem_size(rp);
-
+ Uint size = erts_process_memory(rp);
(void) erts_bld_uint(NULL, &hsz, size);
hp = HAlloc(BIF_P, hsz);
res = erts_bld_uint(&hp, NULL, size);
@@ -2867,12 +2813,10 @@ erts_bld_port_info(Eterm **hpp, ErlOffHeap *ohp, Uint *szp, Port *prt, Eterm ite
included though).
*/
Uint size = 0;
- ErlHeapFragment* bp;
- erts_doforall_links(ERTS_P_LINKS(prt), &one_link_size, &size);
+ erts_doforall_links(ERTS_P_LINKS(prt), &erts_one_link_size, &size);
- for (bp = prt->bp; bp; bp = bp->next)
- size += sizeof(ErlHeapFragment) + (bp->alloc_size - 1)*sizeof(Eterm);
+ size += erts_port_data_size(prt);
if (prt->linebuf)
size += sizeof(LineBuf) + prt->linebuf->ovsiz;
diff --git a/erts/emulator/beam/erl_bif_port.c b/erts/emulator/beam/erl_bif_port.c
index 44fa41c7b6..109c54fd7f 100644
--- a/erts/emulator/beam/erl_bif_port.c
+++ b/erts/emulator/beam/erl_bif_port.c
@@ -423,57 +423,164 @@ BIF_RETTYPE erts_internal_port_info_2(BIF_ALIST_2)
}
}
+/*
+ * The erlang:port_set_data()/erlang:port_get_data() operations should
+ * be viewed as operations on a table (inet_db) with data values
+ * associated with port identifier keys. That is, these operations are
+ * *not* signals to/from ports.
+ */
+
+#if (TAG_PRIMARY_IMMED1 & 0x3) == 0
+# error "erlang:port_set_data()/erlang:port_get_data() needs to be rewritten!"
+#endif
+
+typedef struct {
+ ErtsThrPrgrLaterOp later_op;
+ Uint hsize;
+ Eterm data;
+ ErlOffHeap off_heap;
+ Eterm heap[1];
+} ErtsPortDataHeap;
-BIF_RETTYPE erts_internal_port_set_data_2(BIF_ALIST_2)
+static void
+free_port_data_heap(void *vpdhp)
{
- Eterm ref;
+ erts_cleanup_offheap(&((ErtsPortDataHeap *) vpdhp)->off_heap);
+ erts_free(ERTS_ALC_T_PORT_DATA_HEAP, vpdhp);
+}
+
+static ERTS_INLINE void
+cleanup_old_port_data(erts_aint_t data)
+{
+ if ((data & 0x3) != 0) {
+ ASSERT(is_immed((Eterm) data));
+ }
+ else {
+#ifdef ERTS_SMP
+ ErtsPortDataHeap *pdhp = (ErtsPortDataHeap *) data;
+ size_t size;
+ ERTS_SMP_DATA_DEPENDENCY_READ_MEMORY_BARRIER;
+ size = sizeof(ErtsPortDataHeap) + pdhp->hsize*(sizeof(Eterm) - 1);
+ erts_schedule_thr_prgr_later_cleanup_op(free_port_data_heap,
+ (void *) pdhp,
+ &pdhp->later_op,
+ size);
+#else
+ free_port_data_heap((void *) data);
+#endif
+ }
+}
+
+void
+erts_init_port_data(Port *prt)
+{
+ erts_smp_atomic_init_nob(&prt->data, (erts_aint_t) am_undefined);
+}
+
+void
+erts_cleanup_port_data(Port *prt)
+{
+ ASSERT(erts_atomic32_read_nob(&prt->state) & ERTS_PORT_SFLGS_INVALID_LOOKUP);
+ cleanup_old_port_data(erts_smp_atomic_read_nob(&prt->data));
+ erts_smp_atomic_set_nob(&prt->data, (erts_aint_t) THE_NON_VALUE);
+}
+
+Uint
+erts_port_data_size(Port *prt)
+{
+ erts_aint_t data = erts_smp_atomic_read_ddrb(&prt->data);
+
+ if ((data & 0x3) != 0) {
+ ASSERT(is_immed((Eterm) (UWord) data));
+ return (Uint) 0;
+ }
+ else {
+ ErtsPortDataHeap *pdhp = (ErtsPortDataHeap *) data;
+ return (Uint) sizeof(ErtsPortDataHeap) + pdhp->hsize*(sizeof(Eterm)-1);
+ }
+}
+
+ErlOffHeap *
+erts_port_data_offheap(Port *prt)
+{
+ erts_aint_t data = erts_smp_atomic_read_ddrb(&prt->data);
+
+ if ((data & 0x3) != 0) {
+ ASSERT(is_immed((Eterm) (UWord) data));
+ return NULL;
+ }
+ else {
+ ErtsPortDataHeap *pdhp = (ErtsPortDataHeap *) data;
+ return &pdhp->off_heap;
+ }
+}
+
+BIF_RETTYPE port_set_data_2(BIF_ALIST_2)
+{
+ /*
+ * This is not a signal. See comment above.
+ */
+ erts_aint_t data;
Port* prt;
prt = lookup_port(BIF_P, BIF_ARG_1);
if (!prt)
- BIF_RET(am_badarg);
+ BIF_ERROR(BIF_P, BADARG);
- switch (erts_port_set_data(BIF_P, prt, BIF_ARG_2, &ref)) {
- case ERTS_PORT_OP_CALLER_EXIT:
- case ERTS_PORT_OP_BADARG:
- case ERTS_PORT_OP_DROPPED:
- BIF_RET(am_badarg);
- case ERTS_PORT_OP_SCHEDULED:
- ASSERT(is_internal_ref(ref));
- BIF_RET(ref);
- case ERTS_PORT_OP_DONE:
- BIF_RET(am_true);
- default:
- ERTS_INTERNAL_ERROR("Unexpected erts_port_set_data() result");
- BIF_RET(am_internal_error);
+ if (is_immed(BIF_ARG_2)) {
+ data = (erts_aint_t) BIF_ARG_2;
+ ASSERT((data & 0x3) != 0);
}
+ else {
+ ErtsPortDataHeap *pdhp;
+ Uint hsize;
+ Eterm *hp;
+
+ hsize = size_object(BIF_ARG_2);
+ pdhp = erts_alloc(ERTS_ALC_T_PORT_DATA_HEAP,
+ sizeof(ErtsPortDataHeap) + hsize*(sizeof(Eterm)-1));
+ hp = &pdhp->heap[0];
+ pdhp->off_heap.first = NULL;
+ pdhp->off_heap.overhead = 0;
+ pdhp->data = copy_struct(BIF_ARG_2, hsize, &hp, &pdhp->off_heap);
+ data = (erts_aint_t) pdhp;
+ ASSERT((data & 0x3) == 0);
+ }
+
+ data = erts_smp_atomic_xchg_wb(&prt->data, data);
+
+ cleanup_old_port_data(data);
+
+ BIF_RET(am_true);
}
-BIF_RETTYPE erts_internal_port_get_data_1(BIF_ALIST_1)
+BIF_RETTYPE port_get_data_1(BIF_ALIST_1)
{
- Eterm retval;
+ /*
+ * This is not a signal. See comment above.
+ */
+ Eterm res;
+ erts_aint_t data;
Port* prt;
prt = lookup_port(BIF_P, BIF_ARG_1);
if (!prt)
- BIF_RET(am_badarg);
+ BIF_ERROR(BIF_P, BADARG);
- switch (erts_port_get_data(BIF_P, prt, &retval)) {
- case ERTS_PORT_OP_CALLER_EXIT:
- case ERTS_PORT_OP_BADARG:
- case ERTS_PORT_OP_DROPPED:
- BIF_RET(am_badarg);
- case ERTS_PORT_OP_SCHEDULED:
- ASSERT(is_internal_ref(retval));
- BIF_RET(retval);
- case ERTS_PORT_OP_DONE:
- ASSERT(is_not_internal_ref(retval));
- BIF_RET(retval);
- default:
- ERTS_INTERNAL_ERROR("Unexpected erts_port_get_data() result");
- BIF_RET(am_internal_error);
+ data = erts_smp_atomic_read_ddrb(&prt->data);
+
+ if ((data & 0x3) != 0) {
+ res = (Eterm) (UWord) data;
+ ASSERT(is_immed(res));
+ }
+ else {
+ ErtsPortDataHeap *pdhp = (ErtsPortDataHeap *) data;
+ Eterm *hp = HAlloc(BIF_P, pdhp->hsize);
+ res = copy_struct(pdhp->data, pdhp->hsize, &hp, &MSO(BIF_P));
}
+
+ BIF_RET(res);
}
/*
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_instrument.c b/erts/emulator/beam/erl_instrument.c
index b5b245288b..1aea3f65bc 100644
--- a/erts/emulator/beam/erl_instrument.c
+++ b/erts/emulator/beam/erl_instrument.c
@@ -271,6 +271,18 @@ stat_upd_realloc(ErtsAlcType_t n, Uint size, Uint old_size)
* stat instrumentation callback functions
*/
+static void stat_pre_lock(void)
+{
+ erts_mtx_lock(&instr_mutex);
+}
+
+static void stat_pre_unlock(void)
+{
+ erts_mtx_unlock(&instr_mutex);
+}
+
+static ErtsAllocatorWrapper_t instr_wrapper;
+
static void *
stat_alloc(ErtsAlcType_t n, void *extra, Uint size)
{
@@ -278,7 +290,9 @@ stat_alloc(ErtsAlcType_t n, void *extra, Uint size)
Uint ssize;
void *res;
- erts_mtx_lock(&instr_mutex);
+ if (!erts_is_allctr_wrapper_prelocked()) {
+ erts_mtx_lock(&instr_mutex);
+ }
ssize = size + STAT_BLOCK_HEADER_SIZE;
res = (*real_af->alloc)(n, real_af->extra, ssize);
@@ -293,7 +307,9 @@ stat_alloc(ErtsAlcType_t n, void *extra, Uint size)
res = (void *) ((StatBlock_t *) res)->mem;
}
- erts_mtx_unlock(&instr_mutex);
+ if (!erts_is_allctr_wrapper_prelocked()) {
+ erts_mtx_unlock(&instr_mutex);
+ }
return res;
}
@@ -307,7 +323,9 @@ stat_realloc(ErtsAlcType_t n, void *extra, void *ptr, Uint size)
void *sptr;
void *res;
- erts_mtx_lock(&instr_mutex);
+ if (!erts_is_allctr_wrapper_prelocked()) {
+ erts_mtx_lock(&instr_mutex);
+ }
if (ptr) {
sptr = (void *) (((char *) ptr) - STAT_BLOCK_HEADER_SIZE);
@@ -329,7 +347,9 @@ stat_realloc(ErtsAlcType_t n, void *extra, void *ptr, Uint size)
res = (void *) ((StatBlock_t *) res)->mem;
}
- erts_mtx_unlock(&instr_mutex);
+ if (!erts_is_allctr_wrapper_prelocked()) {
+ erts_mtx_unlock(&instr_mutex);
+ }
return res;
}
@@ -340,7 +360,9 @@ stat_free(ErtsAlcType_t n, void *extra, void *ptr)
ErtsAllocatorFunctions_t *real_af = (ErtsAllocatorFunctions_t *) extra;
void *sptr;
- erts_mtx_lock(&instr_mutex);
+ if (!erts_is_allctr_wrapper_prelocked()) {
+ erts_mtx_lock(&instr_mutex);
+ }
if (ptr) {
sptr = (void *) (((char *) ptr) - STAT_BLOCK_HEADER_SIZE);
@@ -352,7 +374,9 @@ stat_free(ErtsAlcType_t n, void *extra, void *ptr)
(*real_af->free)(n, real_af->extra, sptr);
- erts_mtx_unlock(&instr_mutex);
+ if (!erts_is_allctr_wrapper_prelocked()) {
+ erts_mtx_unlock(&instr_mutex);
+ }
}
@@ -360,6 +384,18 @@ stat_free(ErtsAlcType_t n, void *extra, void *ptr)
* map stat instrumentation callback functions
*/
+static void map_stat_pre_lock(void)
+{
+ erts_mtx_lock(&instr_x_mutex);
+ erts_mtx_lock(&instr_mutex);
+}
+
+static void map_stat_pre_unlock(void)
+{
+ erts_mtx_unlock(&instr_mutex);
+ erts_mtx_unlock(&instr_x_mutex);
+}
+
static void *
map_stat_alloc(ErtsAlcType_t n, void *extra, Uint size)
{
@@ -367,7 +403,9 @@ map_stat_alloc(ErtsAlcType_t n, void *extra, Uint size)
Uint msize;
void *res;
- erts_mtx_lock(&instr_mutex);
+ if (!erts_is_allctr_wrapper_prelocked()) {
+ erts_mtx_lock(&instr_mutex);
+ }
msize = size + MAP_STAT_BLOCK_HEADER_SIZE;
res = (*real_af->alloc)(n, real_af->extra, msize);
@@ -388,7 +426,9 @@ map_stat_alloc(ErtsAlcType_t n, void *extra, Uint size)
res = (void *) mb->mem;
}
- erts_mtx_unlock(&instr_mutex);
+ if (!erts_is_allctr_wrapper_prelocked()) {
+ erts_mtx_unlock(&instr_mutex);
+ }
return res;
}
@@ -402,8 +442,10 @@ map_stat_realloc(ErtsAlcType_t n, void *extra, void *ptr, Uint size)
void *mptr;
void *res;
- erts_mtx_lock(&instr_x_mutex);
- erts_mtx_lock(&instr_mutex);
+ if (!erts_is_allctr_wrapper_prelocked()) {
+ erts_mtx_lock(&instr_x_mutex);
+ erts_mtx_lock(&instr_mutex);
+ }
if (ptr) {
mptr = (void *) (((char *) ptr) - MAP_STAT_BLOCK_HEADER_SIZE);
@@ -449,9 +491,10 @@ map_stat_realloc(ErtsAlcType_t n, void *extra, void *ptr, Uint size)
res = (void *) mb->mem;
}
-
- erts_mtx_unlock(&instr_mutex);
- erts_mtx_unlock(&instr_x_mutex);
+ if (!erts_is_allctr_wrapper_prelocked()) {
+ erts_mtx_unlock(&instr_mutex);
+ erts_mtx_unlock(&instr_x_mutex);
+ }
return res;
}
@@ -462,8 +505,10 @@ map_stat_free(ErtsAlcType_t n, void *extra, void *ptr)
ErtsAllocatorFunctions_t *real_af = (ErtsAllocatorFunctions_t *) extra;
void *mptr;
- erts_mtx_lock(&instr_x_mutex);
- erts_mtx_lock(&instr_mutex);
+ if (!erts_is_allctr_wrapper_prelocked()) {
+ erts_mtx_lock(&instr_x_mutex);
+ erts_mtx_lock(&instr_mutex);
+ }
if (ptr) {
MapStatBlock_t *mb;
@@ -486,8 +531,10 @@ map_stat_free(ErtsAlcType_t n, void *extra, void *ptr)
(*real_af->free)(n, real_af->extra, mptr);
- erts_mtx_unlock(&instr_mutex);
- erts_mtx_unlock(&instr_x_mutex);
+ if (!erts_is_allctr_wrapper_prelocked()) {
+ erts_mtx_unlock(&instr_mutex);
+ erts_mtx_unlock(&instr_x_mutex);
+ }
}
@@ -496,8 +543,10 @@ static void dump_memory_map_to_stream(FILE *fp)
ErtsAlcType_t n;
MapStatBlock_t *bp;
int lock = !ERTS_IS_CRASH_DUMPING;
- if (lock)
+ if (lock) {
+ ASSERT(!erts_is_allctr_wrapper_prelocked());
erts_mtx_lock(&instr_mutex);
+ }
/* Write header */
@@ -1155,6 +1204,7 @@ erts_instr_get_type_info(Process *proc)
Uint
erts_instr_init(int stat, int map_stat)
{
+ Uint extra_sz;
int i;
am_tot = NULL;
@@ -1208,7 +1258,9 @@ erts_instr_init(int stat, int map_stat)
erts_allctrs[i].free = map_stat_free;
erts_allctrs[i].extra = (void *) &real_allctrs[i];
}
- return MAP_STAT_BLOCK_HEADER_SIZE;
+ instr_wrapper.lock = map_stat_pre_lock;
+ instr_wrapper.unlock = map_stat_pre_unlock;
+ extra_sz = MAP_STAT_BLOCK_HEADER_SIZE;
}
else {
erts_instr_stat = 1;
@@ -1220,8 +1272,11 @@ erts_instr_init(int stat, int map_stat)
erts_allctrs[i].free = stat_free;
erts_allctrs[i].extra = (void *) &real_allctrs[i];
}
- return STAT_BLOCK_HEADER_SIZE;
+ instr_wrapper.lock = stat_pre_lock;
+ instr_wrapper.unlock = stat_pre_unlock;
+ extra_sz = STAT_BLOCK_HEADER_SIZE;
}
-
+ erts_allctr_wrapper_prelock_init(&instr_wrapper);
+ return extra_sz;
}
diff --git a/erts/emulator/beam/erl_lock_check.c b/erts/emulator/beam/erl_lock_check.c
index 69bb4be717..a1d270adba 100644
--- a/erts/emulator/beam/erl_lock_check.c
+++ b/erts/emulator/beam/erl_lock_check.c
@@ -143,6 +143,8 @@ static erts_lc_lock_order_t erts_lock_order[] = {
{ "ptimer_pre_alloc_lock", "address", },
{ "btm_pre_alloc_lock", NULL, },
{ "dist_entry_out_queue", "address" },
+ { "port_sched_lock", "port_id" },
+ { "port_table", NULL },
#endif
{ "mtrace_op", NULL },
{ "instr_x", NULL },
@@ -154,10 +156,8 @@ static erts_lc_lock_order_t erts_lock_order[] = {
{ "pmmap", NULL },
#endif
#ifdef ERTS_SMP
- { "port_sched_lock", "port_id" },
{ "port_task_pre_alloc_lock", "address" },
{ "proclist_pre_alloc_lock", "address" },
- { "port_table", NULL },
{ "xports_list_pre_alloc_lock", "address" },
{ "inet_buffer_stack_lock", NULL },
{ "gc_info", NULL },
diff --git a/erts/emulator/beam/erl_monitors.c b/erts/emulator/beam/erl_monitors.c
index 70e592cc5f..244a2b26db 100644
--- a/erts/emulator/beam/erl_monitors.c
+++ b/erts/emulator/beam/erl_monitors.c
@@ -1024,3 +1024,23 @@ Eterm erts_debug_dump_links_1(BIF_ALIST_1)
}
}
}
+
+void erts_one_link_size(ErtsLink *lnk, void *vpu)
+{
+ Uint *pu = vpu;
+ *pu += ERTS_LINK_SIZE*sizeof(Uint);
+ if(!IS_CONST(lnk->pid))
+ *pu += NC_HEAP_SIZE(lnk->pid)*sizeof(Uint);
+ if (lnk->type != LINK_NODE && ERTS_LINK_ROOT(lnk) != NULL) {
+ erts_doforall_links(ERTS_LINK_ROOT(lnk),&erts_one_link_size,vpu);
+ }
+}
+void erts_one_mon_size(ErtsMonitor *mon, void *vpu)
+{
+ Uint *pu = vpu;
+ *pu += ERTS_MONITOR_SIZE*sizeof(Uint);
+ if(!IS_CONST(mon->pid))
+ *pu += NC_HEAP_SIZE(mon->pid)*sizeof(Uint);
+ if(!IS_CONST(mon->ref))
+ *pu += NC_HEAP_SIZE(mon->ref)*sizeof(Uint);
+}
diff --git a/erts/emulator/beam/erl_monitors.h b/erts/emulator/beam/erl_monitors.h
index 6a360a2336..fb11dbbd22 100644
--- a/erts/emulator/beam/erl_monitors.h
+++ b/erts/emulator/beam/erl_monitors.h
@@ -170,6 +170,8 @@ ErtsSuspendMonitor *erts_lookup_suspend_monitor(ErtsSuspendMonitor *root,
Eterm pid);
void erts_delete_suspend_monitor(ErtsSuspendMonitor **root, Eterm pid);
void erts_init_monitors(void);
+void erts_one_link_size(ErtsLink *lnk, void *vpu);
+void erts_one_mon_size(ErtsMonitor *mon, void *vpu);
#define erts_doforall_monitors erts_sweep_monitors
#define erts_doforall_links erts_sweep_links
diff --git a/erts/emulator/beam/erl_mtrace.c b/erts/emulator/beam/erl_mtrace.c
index e538ba30c2..c8bb126687 100644
--- a/erts/emulator/beam/erl_mtrace.c
+++ b/erts/emulator/beam/erl_mtrace.c
@@ -222,6 +222,8 @@ static byte *tracep;
static byte *endp;
static SysTimeval last_tv;
+static ErtsAllocatorWrapper_t mtrace_wrapper;
+
#if ERTS_MTRACE_SEGMENT_ID >= ERTS_ALC_A_MIN || ERTS_MTRACE_SEGMENT_ID < 0
#error ERTS_MTRACE_SEGMENT_ID >= ERTS_ALC_A_MIN || ERTS_MTRACE_SEGMENT_ID < 0
#endif
@@ -555,6 +557,8 @@ write_trace_header(char *nodename, char *pid, char *hostname)
return 1;
}
+static void mtrace_pre_lock(void);
+static void mtrace_pre_unlock(void);
static void *mtrace_alloc(ErtsAlcType_t, void *, Uint);
static void *mtrace_realloc(ErtsAlcType_t, void *, void *, Uint);
static void mtrace_free(ErtsAlcType_t, void *, void *);
@@ -635,12 +639,16 @@ erts_mtrace_install_wrapper_functions(void)
erts_allctrs[i].free = mtrace_free;
erts_allctrs[i].extra = (void *) &real_allctrs[i];
}
+ mtrace_wrapper.lock = mtrace_pre_lock;
+ mtrace_wrapper.unlock = mtrace_pre_unlock;
+ erts_allctr_wrapper_prelock_init(&mtrace_wrapper);
}
}
void
erts_mtrace_stop(void)
{
+ ASSERT(!erts_is_allctr_wrapper_prelocked());
erts_mtx_lock(&mtrace_op_mutex);
erts_mtx_lock(&mtrace_buf_mutex);
if (erts_mtrace_enabled) {
@@ -677,6 +685,7 @@ erts_mtrace_stop(void)
void
erts_mtrace_exit(Uint32 exit_value)
{
+ ASSERT(!erts_is_allctr_wrapper_prelocked());
erts_mtx_lock(&mtrace_op_mutex);
erts_mtx_lock(&mtrace_buf_mutex);
if (erts_mtrace_enabled) {
@@ -935,18 +944,33 @@ write_free_entry(byte tag,
erts_mtx_unlock(&mtrace_buf_mutex);
}
+static void mtrace_pre_lock(void)
+{
+ erts_mtx_lock(&mtrace_op_mutex);
+}
+
+static void mtrace_pre_unlock(void)
+{
+ erts_mtx_unlock(&mtrace_op_mutex);
+}
+
+
static void *
mtrace_alloc(ErtsAlcType_t n, void *extra, Uint size)
{
ErtsAllocatorFunctions_t *real_af = (ErtsAllocatorFunctions_t *) extra;
void *res;
- erts_mtx_lock(&mtrace_op_mutex);
+ if (!erts_is_allctr_wrapper_prelocked()) {
+ erts_mtx_lock(&mtrace_op_mutex);
+ }
res = (*real_af->alloc)(n, real_af->extra, size);
write_alloc_entry(ERTS_MT_ALLOC_BDY_TAG, res, n, 0, size);
- erts_mtx_unlock(&mtrace_op_mutex);
+ if (!erts_is_allctr_wrapper_prelocked()) {
+ erts_mtx_unlock(&mtrace_op_mutex);
+ }
return res;
}
@@ -957,12 +981,16 @@ mtrace_realloc(ErtsAlcType_t n, void *extra, void *ptr, Uint size)
ErtsAllocatorFunctions_t *real_af = (ErtsAllocatorFunctions_t *) extra;
void *res;
- erts_mtx_lock(&mtrace_op_mutex);
+ if (!erts_is_allctr_wrapper_prelocked()) {
+ erts_mtx_lock(&mtrace_op_mutex);
+ }
res = (*real_af->realloc)(n, real_af->extra, ptr, size);
write_realloc_entry(ERTS_MT_REALLOC_BDY_TAG, res, n, 0, ptr, size);
- erts_mtx_unlock(&mtrace_op_mutex);
+ if (!erts_is_allctr_wrapper_prelocked()) {
+ erts_mtx_unlock(&mtrace_op_mutex);
+ }
return res;
@@ -973,10 +1001,14 @@ mtrace_free(ErtsAlcType_t n, void *extra, void *ptr)
{
ErtsAllocatorFunctions_t *real_af = (ErtsAllocatorFunctions_t *) extra;
- erts_mtx_lock(&mtrace_op_mutex);
+ if (!erts_is_allctr_wrapper_prelocked()) {
+ erts_mtx_lock(&mtrace_op_mutex);
+ }
(*real_af->free)(n, real_af->extra, ptr);
- write_free_entry(ERTS_MT_FREE_BDY_TAG, n, 0, ptr);
+ if (!erts_is_allctr_wrapper_prelocked()) {
+ write_free_entry(ERTS_MT_FREE_BDY_TAG, n, 0, ptr);
+ }
erts_mtx_unlock(&mtrace_op_mutex);
}
diff --git a/erts/emulator/beam/erl_node_tables.c b/erts/emulator/beam/erl_node_tables.c
index ebfba065d1..e688e55c88 100644
--- a/erts/emulator/beam/erl_node_tables.c
+++ b/erts/emulator/beam/erl_node_tables.c
@@ -1371,6 +1371,7 @@ setup_reference_table(void)
/* Insert all ports */
max = erts_ptab_max(&erts_port);
for (i = 0; i < max; i++) {
+ ErlOffHeap *ohp;
erts_aint32_t state;
Port *prt;
@@ -1389,8 +1390,9 @@ setup_reference_table(void)
if (ERTS_P_MONITORS(prt))
insert_monitors(ERTS_P_MONITORS(prt), prt->common.id);
/* Insert port data */
- for(hfp = prt->bp; hfp; hfp = hfp->next)
- insert_offheap(&(hfp->off_heap), HEAP_REF, prt->common.id);
+ ohp = erts_port_data_offheap(prt);
+ if (ohp)
+ insert_offheap(ohp, HEAP_REF, prt->common.id);
/* Insert controller */
if (prt->dist_entry)
insert_dist_entry(prt->dist_entry,
diff --git a/erts/emulator/beam/erl_port.h b/erts/emulator/beam/erl_port.h
index 377aa72ed5..ad3f104a68 100644
--- a/erts/emulator/beam/erl_port.h
+++ b/erts/emulator/beam/erl_port.h
@@ -167,8 +167,7 @@ struct _erl_drv_port {
#endif
erts_atomic_t connected; /* A connected process */
Eterm caller; /* Current caller. */
- Eterm data; /* Data associated with port. */
- ErlHeapFragment* bp; /* Heap fragment holding data (NULL if imm data). */
+ erts_smp_atomic_t data; /* Data associated with port. */
Uint bytes_in; /* Number of bytes read */
Uint bytes_out; /* Number of bytes written */
@@ -189,6 +188,12 @@ struct _erl_drv_port {
int reds; /* Only used while executing driver callbacks */
};
+
+void erts_init_port_data(Port *);
+void erts_cleanup_port_data(Port *);
+Uint erts_port_data_size(Port *);
+ErlOffHeap *erts_port_data_offheap(Port *);
+
#define ERTS_PORT_GET_CONNECTED(PRT) \
((Eterm) erts_atomic_read_nob(&(PRT)->connected))
#define ERTS_PORT_SET_CONNECTED(PRT, PID) \
@@ -326,8 +331,6 @@ extern erts_smp_atomic_t erts_bytes_in; /* no bytes sent into the system */
#define ERTS_PORT_REDS_CONTROL (CONTEXT_REDS/100)
#define ERTS_PORT_REDS_CALL (CONTEXT_REDS/50)
#define ERTS_PORT_REDS_INFO (CONTEXT_REDS/100)
-#define ERTS_PORT_REDS_SET_DATA (CONTEXT_REDS/100)
-#define ERTS_PORT_REDS_GET_DATA (CONTEXT_REDS/100)
#define ERTS_PORT_REDS_TERMINATE (CONTEXT_REDS/50)
void print_port_info(Port *, int, void *);
@@ -794,8 +797,6 @@ struct binary;
#define ERTS_P2P_SIG_TYPE_INFO 7
#define ERTS_P2P_SIG_TYPE_LINK 8
#define ERTS_P2P_SIG_TYPE_UNLINK 9
-#define ERTS_P2P_SIG_TYPE_SET_DATA 10
-#define ERTS_P2P_SIG_TYPE_GET_DATA 11
#define ERTS_P2P_SIG_TYPE_BITS 4
#define ERTS_P2P_SIG_TYPE_MASK \
@@ -810,6 +811,7 @@ struct binary;
#define ERTS_P2P_SIG_DATA_FLG_BAD_OUTPUT ERTS_P2P_SIG_DATA_FLG(4)
#define ERTS_P2P_SIG_DATA_FLG_BROKEN_LINK ERTS_P2P_SIG_DATA_FLG(5)
#define ERTS_P2P_SIG_DATA_FLG_SCHED ERTS_P2P_SIG_DATA_FLG(6)
+#define ERTS_P2P_SIG_DATA_FLG_ASYNC ERTS_P2P_SIG_DATA_FLG(7)
struct ErtsProc2PortSigData_ {
int flags;
@@ -856,10 +858,6 @@ struct ErtsProc2PortSigData_ {
struct {
Eterm from;
} unlink;
- struct {
- ErlHeapFragment *bp;
- Eterm data;
- } set_data;
} u;
} ;
@@ -919,6 +917,7 @@ erts_schedule_proc2port_signal(Process *,
Eterm *,
ErtsProc2PortSigData *,
int,
+ ErtsPortTaskHandle *,
ErtsProc2PortSigCallback);
int erts_deliver_port_exit(Port *, Eterm, Eterm, int);
@@ -932,6 +931,7 @@ int erts_deliver_port_exit(Port *, Eterm, Eterm, int);
#define ERTS_PORT_SIG_FLG_BROKEN_LINK ERTS_P2P_SIG_DATA_FLG_BROKEN_LINK
#define ERTS_PORT_SIG_FLG_BAD_OUTPUT ERTS_P2P_SIG_DATA_FLG_BAD_OUTPUT
#define ERTS_PORT_SIG_FLG_FORCE_SCHED ERTS_P2P_SIG_DATA_FLG_SCHED
+#define ERTS_PORT_SIG_FLG_ASYNC ERTS_P2P_SIG_DATA_FLG_ASYNC
/* ERTS_PORT_SIG_FLG_FORCE_IMM_CALL only when crash dumping... */
#define ERTS_PORT_SIG_FLG_FORCE_IMM_CALL ERTS_P2P_SIG_DATA_FLG_BAD_OUTPUT
@@ -953,7 +953,5 @@ ErtsPortOpResult erts_port_unlink(Process *, Port *, Eterm, Eterm *);
ErtsPortOpResult erts_port_control(Process *, Port *, unsigned int, Eterm, Eterm *);
ErtsPortOpResult erts_port_call(Process *, Port *, unsigned int, Eterm, Eterm *);
ErtsPortOpResult erts_port_info(Process *, Port *, Eterm, Eterm *);
-ErtsPortOpResult erts_port_set_data(Process *, Port *, Eterm, Eterm *);
-ErtsPortOpResult erts_port_get_data(Process *, Port *, Eterm *);
#endif
diff --git a/erts/emulator/beam/erl_port_task.c b/erts/emulator/beam/erl_port_task.c
index 0ed08bee01..53cb01a8c6 100644
--- a/erts/emulator/beam/erl_port_task.c
+++ b/erts/emulator/beam/erl_port_task.c
@@ -552,6 +552,19 @@ set_handle(ErtsPortTask *ptp, ErtsPortTaskHandle *pthp)
}
}
+static ERTS_INLINE void
+set_tmp_handle(ErtsPortTask *ptp, ErtsPortTaskHandle *pthp)
+{
+ ptp->u.alive.handle = NULL;
+ if (pthp) {
+ /*
+ * IMPORTANT! Task either need to be aborted, or task handle
+ * need to be detached before thread progress has been made.
+ */
+ erts_smp_atomic_set_relb(pthp, (erts_aint_t) ptp);
+ }
+}
+
/*
* Busy port queue management
@@ -1182,6 +1195,13 @@ erl_drv_consume_timeslice(ErlDrvPort dprt, int percent)
return 1;
}
+void
+erts_port_task_tmp_handle_detach(ErtsPortTaskHandle *pthp)
+{
+ ERTS_SMP_LC_ASSERT(erts_thr_progress_lc_is_delaying());
+ reset_port_task_handle(pthp);
+}
+
/*
* Abort a scheduled task.
*/
@@ -1206,7 +1226,7 @@ erts_port_task_abort(ErtsPortTaskHandle *pthp)
ERTS_SMP_READ_MEMORY_BARRIER;
old_state = erts_smp_atomic32_read_nob(&ptp->state);
if (old_state == ERTS_PT_STATE_SCHEDULED) {
- ASSERT(saved_pthp == pthp);
+ ASSERT(!saved_pthp || saved_pthp == pthp);
}
#endif
@@ -1227,9 +1247,6 @@ erts_port_task_abort(ErtsPortTaskHandle *pthp)
&erts_port_task_outstanding_io_tasks) > 0);
erts_smp_atomic_dec_relb(&erts_port_task_outstanding_io_tasks);
break;
- case ERTS_PORT_TASK_PROC_SIG:
- ERTS_INTERNAL_ERROR("Aborted process to port signal");
- break;
default:
break;
}
@@ -1404,7 +1421,6 @@ erts_port_task_schedule(Eterm id,
}
case ERTS_PORT_TASK_PROC_SIG: {
va_list argp;
- ASSERT(!pthp);
va_start(argp, type);
sigdp = va_arg(argp, ErtsProc2PortSigData *);
ptp = p2p_sig_data_to_task(sigdp);
@@ -1412,7 +1428,7 @@ erts_port_task_schedule(Eterm id,
ptp->u.alive.flags |= va_arg(argp, int);
va_end(argp);
if (!(ptp->u.alive.flags & ERTS_PT_FLG_NOSUSPEND))
- set_handle(ptp, pthp);
+ set_tmp_handle(ptp, pthp);
else {
ns_pthlp = erts_alloc(ERTS_ALC_T_PT_HNDL_LIST,
sizeof(ErtsPortTaskHandleList));
diff --git a/erts/emulator/beam/erl_port_task.h b/erts/emulator/beam/erl_port_task.h
index ae6cd69ae2..d35a15c27b 100644
--- a/erts/emulator/beam/erl_port_task.h
+++ b/erts/emulator/beam/erl_port_task.h
@@ -243,7 +243,9 @@ int erts_port_task_execute(ErtsRunQueue *, Port **);
void erts_port_task_init(void);
#endif
+void erts_port_task_tmp_handle_detach(ErtsPortTaskHandle *);
int erts_port_task_abort(ErtsPortTaskHandle *);
+
void erts_port_task_abort_nosuspend_tasks(Port *);
int erts_port_task_schedule(Eterm,
diff --git a/erts/emulator/beam/erl_process.c b/erts/emulator/beam/erl_process.c
index f9ef4eac65..7415a5721f 100644
--- a/erts/emulator/beam/erl_process.c
+++ b/erts/emulator/beam/erl_process.c
@@ -1882,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);
@@ -4670,6 +4670,8 @@ erts_init_scheduling(int no_schedulers, int no_schedulers_online)
esdp->reductions = 0;
init_sched_wall_time(&esdp->sched_wall_time);
+
+ erts_port_task_handle_init(&esdp->nosuspend_port_task_handle);
}
init_misc_aux_work();
diff --git a/erts/emulator/beam/erl_process.h b/erts/emulator/beam/erl_process.h
index 3d3579fa7e..5a1f6bbe8d 100644
--- a/erts/emulator/beam/erl_process.h
+++ b/erts/emulator/beam/erl_process.h
@@ -507,6 +507,7 @@ struct ErtsSchedulerData_ {
Uint64 reductions;
ErtsSchedWallTime sched_wall_time;
+ ErtsPortTaskHandle nosuspend_port_task_handle;
#ifdef ERTS_DO_VERIFY_UNUSED_TEMP_ALLOC
erts_alloc_verify_func_t verify_unused_temp_alloc;
@@ -1421,6 +1422,8 @@ Eterm erts_debug_reader_groups_map(Process *c_p, int groups);
Uint erts_debug_nbalance(void);
int erts_debug_wait_deallocations(Process *c_p);
+Uint erts_process_memory(Process *c_p);
+
#ifdef ERTS_SMP
# define ERTS_GET_SCHEDULER_DATA_FROM_PROC(PROC) ((PROC)->scheduler_data)
# define ERTS_PROC_GET_SCHDATA(PROC) ((PROC)->scheduler_data)
diff --git a/erts/emulator/beam/erl_process_dump.c b/erts/emulator/beam/erl_process_dump.c
index a93229c473..6cd0d23b97 100644
--- a/erts/emulator/beam/erl_process_dump.c
+++ b/erts/emulator/beam/erl_process_dump.c
@@ -76,6 +76,43 @@ erts_deep_process_dump(int to, void *to_arg)
dump_binaries(to, to_arg, all_binaries);
}
+Uint erts_process_memory(Process *p) {
+ ErlMessage *mp;
+ Uint size = 0;
+ struct saved_calls *scb;
+ size += sizeof(Process);
+
+ ERTS_SMP_MSGQ_MV_INQ2PRIVQ(p);
+
+ erts_doforall_links(ERTS_P_LINKS(p), &erts_one_link_size, &size);
+ erts_doforall_monitors(ERTS_P_MONITORS(p), &erts_one_mon_size, &size);
+ size += (p->heap_sz + p->mbuf_sz) * sizeof(Eterm);
+ if (p->old_hend && p->old_heap)
+ size += (p->old_hend - p->old_heap) * sizeof(Eterm);
+
+ size += p->msg.len * sizeof(ErlMessage);
+
+ for (mp = p->msg.first; mp; mp = mp->next)
+ if (mp->data.attached)
+ size += erts_msg_attached_data_size(mp)*sizeof(Eterm);
+
+ if (p->arg_reg != p->def_arg_reg) {
+ size += p->arity * sizeof(p->arg_reg[0]);
+ }
+
+ if (p->psd)
+ size += sizeof(ErtsPSD);
+
+ scb = ERTS_PROC_GET_SAVED_CALLS_BUF(p);
+ if (scb) {
+ size += (sizeof(struct saved_calls)
+ + (scb->len-1) * sizeof(scb->ct[0]));
+ }
+
+ size += erts_dicts_mem_size(p);
+ return size;
+}
+
static void
dump_process_info(int to, void *to_arg, Process *p)
{
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/external.c b/erts/emulator/beam/external.c
index 5ce0d97c74..8420cfae24 100644
--- a/erts/emulator/beam/external.c
+++ b/erts/emulator/beam/external.c
@@ -3147,17 +3147,6 @@ encode_size_struct2(ErtsAtomCacheMap *acmp, Eterm obj, unsigned dflags)
return result;
}
-static int is_valid_utf8_atom(byte* bytes, Uint nbytes)
-{
- byte* err_pos;
- Uint num_chars;
-
- /*SVERK Do we really need to validate correct utf8? */
- return nbytes <= MAX_ATOM_SZ_LIMIT
- && erts_analyze_utf8(bytes, nbytes, &err_pos, &num_chars, NULL) == ERTS_UTF8_OK
- && num_chars <= MAX_ATOM_CHARACTERS;
-}
-
static Sint
decoded_size(byte *ep, byte* endp, int internal_tags)
{
@@ -3235,7 +3224,7 @@ decoded_size(byte *ep, byte* endp, int internal_tags)
CHKSIZE(2);
n = get_int16(ep);
ep += 2;
- if (!is_valid_utf8_atom(ep, n)) {
+ if (n > MAX_ATOM_SZ_LIMIT) {
return -1;
}
SKIP(n+atom_extra_skip);
@@ -3254,7 +3243,7 @@ decoded_size(byte *ep, byte* endp, int internal_tags)
CHKSIZE(1);
n = get_int8(ep);
ep++;
- if (!is_valid_utf8_atom(ep, n)) {
+ if (n > MAX_ATOM_SZ_LIMIT) {
return -1;
}
SKIP(n+atom_extra_skip);
diff --git a/erts/emulator/beam/io.c b/erts/emulator/beam/io.c
index 43918a7141..b6b7b47bd6 100644
--- a/erts/emulator/beam/io.c
+++ b/erts/emulator/beam/io.c
@@ -364,9 +364,8 @@ static Port *create_port(char *name,
ERTS_P_LINKS(prt) = NULL;
ERTS_P_MONITORS(prt) = NULL;
prt->linebuf = NULL;
- prt->bp = NULL;
prt->suspended = NULL;
- prt->data = am_undefined;
+ erts_init_port_data(prt);
prt->port_data_lock = NULL;
prt->control_flags = 0;
prt->bytes_in = 0;
@@ -1442,6 +1441,7 @@ erts_schedule_proc2port_signal(Process *c_p,
Eterm *refp,
ErtsProc2PortSigData *sigdp,
int task_flags,
+ ErtsPortTaskHandle *pthp,
ErtsProc2PortSigCallback callback)
{
int sched_res;
@@ -1491,7 +1491,7 @@ erts_schedule_proc2port_signal(Process *c_p,
/* Schedule port close call for later execution... */
sched_res = erts_port_task_schedule(prt->common.id,
- NULL,
+ pthp,
ERTS_PORT_TASK_PROC_SIG,
sigdp,
callback,
@@ -1629,6 +1629,7 @@ bad_port_signal(Process *c_p,
refp,
sigdp,
0,
+ NULL,
port_badsig);
}
@@ -1838,8 +1839,11 @@ erts_port_output(Process *c_p,
ErlIOVec *evp = NULL;
char *buf = NULL;
int force_immediate_call = (flags & ERTS_PORT_SIG_FLG_FORCE_IMM_CALL);
+ int async_nosuspend;
+ ErtsPortTaskHandle *ns_pthp;
ASSERT((flags & ~(ERTS_PORT_SIG_FLG_BANG_OP
+ | ERTS_PORT_SIG_FLG_ASYNC
| ERTS_PORT_SIG_FLG_NOSUSPEND
| ERTS_PORT_SIG_FLG_FORCE
| ERTS_PORT_SIG_FLG_FORCE_IMM_CALL)) == 0);
@@ -1861,6 +1865,12 @@ erts_port_output(Process *c_p,
? ERTS_PORT_OP_DROPPED
: ERTS_PORT_OP_BUSY);
+ async_nosuspend = ((flags & (ERTS_PORT_SIG_FLG_ASYNC
+ | ERTS_PORT_SIG_FLG_NOSUSPEND
+ | ERTS_PORT_SIG_FLG_FORCE))
+ == (ERTS_PORT_SIG_FLG_ASYNC
+ | ERTS_PORT_SIG_FLG_NOSUSPEND));
+
try_call = (force_immediate_call /* crash dumping */
|| !(sched_flags & (invalid_flags
| ERTS_PTS_FLGS_FORCE_SCHEDULE_OP)));
@@ -1995,6 +2005,15 @@ erts_port_output(Process *c_p,
return ERTS_PORT_OP_DONE;
case ERTS_TRY_IMM_DRV_CALL_INVALID_SCHED_FLAGS:
sched_flags = try_call_state.sched_flags;
+ if (async_nosuspend
+ && (sched_flags & (busy_flgs|ERTS_PTS_FLG_EXIT))) {
+ driver_free_binary(cbin);
+ if (evp != &ev)
+ erts_free(ERTS_ALC_T_TMP, evp);
+ return ((sched_flags & ERTS_PTS_FLG_EXIT)
+ ? ERTS_PORT_OP_DROPPED
+ : ERTS_PORT_OP_BUSY);
+ }
case ERTS_TRY_IMM_DRV_CALL_BUSY_LOCK:
/* Schedule outputv() call instead... */
break;
@@ -2142,6 +2161,13 @@ erts_port_output(Process *c_p,
return ERTS_PORT_OP_DONE;
case ERTS_TRY_IMM_DRV_CALL_INVALID_SCHED_FLAGS:
sched_flags = try_call_state.sched_flags;
+ if (async_nosuspend
+ && (sched_flags & (busy_flgs|ERTS_PTS_FLG_EXIT))) {
+ erts_free(ERTS_ALC_T_TMP, buf);
+ return ((sched_flags & ERTS_PTS_FLG_EXIT)
+ ? ERTS_PORT_OP_DROPPED
+ : ERTS_PORT_OP_BUSY);
+ }
case ERTS_TRY_IMM_DRV_CALL_BUSY_LOCK:
/* Schedule outputv() call instead... */
break;
@@ -2163,20 +2189,33 @@ erts_port_output(Process *c_p,
task_flags = ERTS_PT_FLG_WAIT_BUSY;
sigdp->flags |= flags;
+ ns_pthp = NULL;
if (flags & (ERTS_P2P_SIG_DATA_FLG_FORCE|ERTS_P2P_SIG_DATA_FLG_NOSUSPEND)) {
task_flags = 0;
if (flags & ERTS_P2P_SIG_DATA_FLG_FORCE)
sigdp->flags &= ~ERTS_P2P_SIG_DATA_FLG_NOSUSPEND;
+ else if (async_nosuspend) {
+ ErtsSchedulerData *esdp = (c_p
+ ? ERTS_PROC_GET_SCHDATA(c_p)
+ : erts_get_scheduler_data());
+ ASSERT(esdp);
+ ns_pthp = &esdp->nosuspend_port_task_handle;
+ sigdp->flags &= ~ERTS_P2P_SIG_DATA_FLG_NOSUSPEND;
+ }
else if (flags & ERTS_P2P_SIG_DATA_FLG_NOSUSPEND)
task_flags = ERTS_PT_FLG_NOSUSPEND;
}
+ ASSERT(ns_pthp || !async_nosuspend);
+ ASSERT(async_nosuspend || !ns_pthp);
+
res = erts_schedule_proc2port_signal(c_p,
prt,
c_p ? c_p->common.id : ERTS_INVALID_PID,
refp,
sigdp,
task_flags,
+ ns_pthp,
port_sig_callback);
if (res != ERTS_PORT_OP_SCHEDULED) {
@@ -2187,9 +2226,23 @@ erts_port_output(Process *c_p,
return res;
}
- if (!(sched_flags & ERTS_PTS_FLG_EXIT) && (sched_flags & busy_flgs))
- return ERTS_PORT_OP_BUSY_SCHEDULED;
-
+ if (!(flags & ERTS_PORT_SIG_FLG_FORCE)) {
+ sched_flags = erts_smp_atomic32_read_acqb(&prt->sched.flags);
+ if (!(sched_flags & ERTS_PTS_FLG_BUSY_PORT)) {
+ if (async_nosuspend)
+ erts_port_task_tmp_handle_detach(ns_pthp);
+ }
+ else {
+ if (!async_nosuspend)
+ return ERTS_PORT_OP_BUSY_SCHEDULED;
+ else {
+ if (erts_port_task_abort(ns_pthp) == 0)
+ return ERTS_PORT_OP_BUSY;
+ else
+ erts_port_task_tmp_handle_detach(ns_pthp);
+ }
+ }
+ }
return res;
bad_value:
@@ -2285,6 +2338,7 @@ erts_port_exit(Process *c_p,
ErlHeapFragment *bp = NULL;
ASSERT((flags & ~(ERTS_PORT_SIG_FLG_BANG_OP
+ | ERTS_PORT_SIG_FLG_ASYNC
| ERTS_PORT_SIG_FLG_BROKEN_LINK
| ERTS_PORT_SIG_FLG_FORCE_SCHED)) == 0);
@@ -2345,6 +2399,7 @@ erts_port_exit(Process *c_p,
refp,
sigdp,
0,
+ NULL,
port_sig_exit);
if (res == ERTS_PORT_OP_DROPPED) {
@@ -2460,7 +2515,8 @@ erts_port_connect(Process *c_p,
!refp,
am_connect);
- ASSERT((flags & ~ERTS_PORT_SIG_FLG_BANG_OP) == 0);
+ ASSERT((flags & ~(ERTS_PORT_SIG_FLG_BANG_OP
+ | ERTS_PORT_SIG_FLG_ASYNC)) == 0);
if (is_not_internal_pid(connect))
connect_id = NIL; /* Fail in op (for signal order) */
@@ -2499,6 +2555,7 @@ erts_port_connect(Process *c_p,
refp,
sigdp,
0,
+ NULL,
port_sig_connect);
}
@@ -2555,6 +2612,7 @@ erts_port_unlink(Process *c_p, Port *prt, Eterm from, Eterm *refp)
refp,
sigdp,
0,
+ NULL,
port_sig_unlink);
}
@@ -2644,6 +2702,7 @@ erts_port_link(Process *c_p, Port *prt, Eterm to, Eterm *refp)
refp,
sigdp,
0,
+ NULL,
port_sig_link);
}
@@ -3371,11 +3430,8 @@ terminate_port(Port *prt)
erts_free(ERTS_ALC_T_LINEBUF, (void *) prt->linebuf);
prt->linebuf = NULL;
}
- if (prt->bp != NULL) {
- free_message_buffer(prt->bp);
- prt->bp = NULL;
- prt->data = am_undefined;
- }
+
+ erts_cleanup_port_data(prt);
if (prt->psd)
erts_free(ERTS_ALC_T_PRTSD, prt->psd);
@@ -3625,6 +3681,10 @@ erts_port_command(Process *c_p,
ASSERT(port);
flags |= ERTS_PORT_SIG_FLG_BANG_OP;
+ if (!erts_port_synchronous_ops) {
+ flags |= ERTS_PORT_SIG_FLG_ASYNC;
+ refp = NULL;
+ }
if (is_tuple_arity(command, 2)) {
Eterm cntd;
@@ -3632,21 +3692,14 @@ erts_port_command(Process *c_p,
cntd = tp[1];
if (is_internal_pid(cntd)) {
if (tp[2] == am_close) {
- if (!erts_port_synchronous_ops)
- refp = NULL;
flags &= ~ERTS_PORT_SIG_FLG_NOSUSPEND;
return erts_port_exit(c_p, flags, port, cntd, am_normal, refp);
} else if (is_tuple_arity(tp[2], 2)) {
tp = tuple_val(tp[2]);
if (tp[1] == am_command) {
- if (!(flags & ERTS_PORT_SIG_FLG_NOSUSPEND)
- && !erts_port_synchronous_ops)
- refp = NULL;
return erts_port_output(c_p, flags, port, cntd, tp[2], refp);
}
else if (tp[1] == am_connect) {
- if (!erts_port_synchronous_ops)
- refp = NULL;
flags &= ~ERTS_PORT_SIG_FLG_NOSUSPEND;
return erts_port_connect(c_p, flags, port, cntd, tp[2], refp);
}
@@ -3655,8 +3708,6 @@ erts_port_command(Process *c_p,
}
/* badsig */
- if (!erts_port_synchronous_ops)
- refp = NULL;
flags &= ~ERTS_PORT_SIG_FLG_NOSUSPEND;
return bad_port_signal(c_p, flags, port, c_p->common.id, refp, am_command);
}
@@ -4053,6 +4104,7 @@ erts_port_control(Process* c_p,
retvalp,
sigdp,
0,
+ NULL,
port_sig_control);
if (res != ERTS_PORT_OP_SCHEDULED) {
cleanup_scheduled_control(binp, bufp);
@@ -4147,7 +4199,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)
@@ -4264,7 +4316,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;
@@ -4333,6 +4385,7 @@ erts_port_call(Process* c_p,
retvalp,
sigdp,
0,
+ NULL,
port_sig_call);
if (res != ERTS_PORT_OP_SCHEDULED) {
cleanup_scheduled_call(bufp);
@@ -4499,228 +4552,10 @@ erts_port_info(Process* c_p,
retvalp,
sigdp,
0,
+ NULL,
port_sig_info);
}
-static int
-port_sig_set_data(Port *prt,
- erts_aint32_t state,
- int op,
- ErtsProc2PortSigData *sigdp)
-{
- ASSERT(sigdp->flags & ERTS_P2P_SIG_DATA_FLG_REPLY);
-
- if (op == ERTS_PROC2PORT_SIG_EXEC) {
- if (prt->bp)
- free_message_buffer(prt->bp);
- prt->bp = sigdp->u.set_data.bp;
- prt->data = sigdp->u.set_data.data;
- port_sched_op_reply(sigdp->caller, sigdp->ref, am_true);
- }
- else {
- if (sigdp->u.set_data.bp)
- free_message_buffer(sigdp->u.set_data.bp);
- port_sched_op_reply(sigdp->caller, sigdp->ref, am_badarg);
- }
- return ERTS_PORT_REDS_SET_DATA;
-}
-
-ErtsPortOpResult
-erts_port_set_data(Process* c_p,
- Port *prt,
- Eterm data,
- Eterm *refp)
-{
- ErtsPortOpResult res;
- Eterm set_data;
- ErlHeapFragment *bp;
- ErtsProc2PortSigData *sigdp;
- ErtsTryImmDrvCallResult try_call_res;
- ErtsTryImmDrvCallState try_call_state
- = ERTS_INIT_TRY_IMM_DRV_CALL_STATE(
- c_p,
- prt,
- ERTS_PORT_SFLGS_INVALID_LOOKUP,
- 0,
- !refp,
- am_set_data);
-
- if (is_immed(data)) {
- set_data = data;
- bp = NULL;
- }
- else {
- Eterm *hp;
- Uint sz = size_object(data);
- bp = new_message_buffer(sz);
- hp = bp->mem;
- set_data = copy_struct(data, sz, &hp, &bp->off_heap);
- }
-
- try_call_res = try_imm_drv_call(&try_call_state);
- switch (try_call_res) {
- case ERTS_TRY_IMM_DRV_CALL_OK:
- if (prt->bp)
- free_message_buffer(prt->bp);
- prt->bp = bp;
- prt->data = set_data;
- finalize_imm_drv_call(&try_call_state);
- BUMP_REDS(c_p, ERTS_PORT_REDS_SET_DATA);
- return ERTS_PORT_OP_DONE;
- case ERTS_TRY_IMM_DRV_CALL_INVALID_PORT:
- return ERTS_PORT_OP_DROPPED;
- case ERTS_TRY_IMM_DRV_CALL_INVALID_SCHED_FLAGS:
- case ERTS_TRY_IMM_DRV_CALL_BUSY_LOCK:
- /* Schedule call instead... */
- break;
- }
-
- sigdp = erts_port_task_alloc_p2p_sig_data();
- sigdp->flags = ERTS_P2P_SIG_TYPE_SET_DATA;
- sigdp->u.set_data.data = set_data;
- sigdp->u.set_data.bp = bp;
-
- res = erts_schedule_proc2port_signal(c_p,
- prt,
- c_p->common.id,
- refp,
- sigdp,
- 0,
- port_sig_set_data);
- if (res != ERTS_PORT_OP_SCHEDULED && bp)
- free_message_buffer(bp);
- return res;
-}
-
-static int
-port_sig_get_data(Port *prt,
- erts_aint32_t state,
- int op,
- ErtsProc2PortSigData *sigdp)
-{
- ASSERT(sigdp->flags & ERTS_P2P_SIG_DATA_FLG_REPLY);
- if (op != ERTS_PROC2PORT_SIG_EXEC)
- port_sched_op_reply(sigdp->caller, sigdp->ref, am_badarg);
- else {
- Process *rp;
- ErtsProcLocks rp_locks = 0;
-
- rp = erts_proc_lookup_raw(sigdp->caller);
- if (rp) {
- Uint hsz;
- Eterm *hp, *hp_start;
- Eterm data, msg;
- ErlHeapFragment *bp;
- ErlOffHeap *ohp;
-
- hsz = ERTS_QUEUE_PORT_SCHED_OP_REPLY_SIZE;
- hsz += 3;
- if (prt->bp)
- hsz += prt->bp->used_size;
-
- hp_start = hp = erts_alloc_message_heap(hsz,
- &bp,
- &ohp,
- rp,
- &rp_locks);
-
- if (is_immed(prt->data))
- data = prt->data;
- else
- data = copy_struct(prt->data,
- prt->bp->used_size,
- &hp,
- &bp->off_heap);
-
-
-
- msg = TUPLE2(hp, am_ok, data);
- hp += 3;
-
- queue_port_sched_op_reply(rp,
- &rp_locks,
- hp_start,
- hp,
- hsz,
- bp,
- sigdp->ref,
- msg);
- if (rp_locks)
- erts_smp_proc_unlock(rp, rp_locks);
- }
- }
- return ERTS_PORT_REDS_GET_DATA;
-}
-
-ErtsPortOpResult
-erts_port_get_data(Process* c_p,
- Port *prt,
- Eterm *retvalp)
-{
- ErtsProc2PortSigData *sigdp;
- ErtsTryImmDrvCallResult try_call_res;
- ErtsTryImmDrvCallState try_call_state
- = ERTS_INIT_TRY_IMM_DRV_CALL_STATE(
- c_p,
- prt,
- ERTS_PORT_SFLGS_INVALID_LOOKUP,
- 0,
- 0,
- am_get_data);
-
- try_call_res = try_imm_drv_call(&try_call_state);
- switch (try_call_res) {
- case ERTS_TRY_IMM_DRV_CALL_OK: {
- Eterm *hp;
- Eterm data;
- ErlHeapFragment *bp;
- Uint sz;
- if (is_immed(prt->data)) {
- bp = NULL;
- data = prt->data;
- }
- else {
- bp = new_message_buffer(prt->bp->used_size);
- data = copy_struct(prt->data,
- prt->bp->used_size,
- &hp,
- &bp->off_heap);
- }
- finalize_imm_drv_call(&try_call_state);
- if (is_immed(data))
- sz = 0;
- else
- sz = bp->used_size;
-
- hp = HAlloc(c_p, sz + 3);
- if (is_not_immed(data)) {
- data = copy_struct(data, bp->used_size, &hp, &MSO(c_p));
- free_message_buffer(bp);
- }
- *retvalp = TUPLE2(hp, am_ok, data);
- BUMP_REDS(c_p, ERTS_PORT_REDS_GET_DATA);
- return ERTS_PORT_OP_DONE;
- }
- case ERTS_TRY_IMM_DRV_CALL_INVALID_PORT:
- return ERTS_PORT_OP_DROPPED;
- case ERTS_TRY_IMM_DRV_CALL_INVALID_SCHED_FLAGS:
- case ERTS_TRY_IMM_DRV_CALL_BUSY_LOCK:
- /* Schedule call instead... */
- break;
- }
-
- sigdp = erts_port_task_alloc_p2p_sig_data();
- sigdp->flags = ERTS_P2P_SIG_TYPE_GET_DATA;
-
- return erts_schedule_proc2port_signal(c_p,
- prt,
- c_p->common.id,
- retvalp,
- sigdp,
- 0,
- port_sig_get_data);
-}
-
typedef struct {
int to;
void *arg;
@@ -5941,10 +5776,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;
@@ -5967,7 +5798,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;
}
@@ -6412,7 +6243,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;
}
@@ -6477,7 +6308,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;
}
@@ -6536,7 +6367,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;
diff --git a/erts/emulator/drivers/common/efile_drv.c b/erts/emulator/drivers/common/efile_drv.c
index 69acfc9dfd..6cc1295973 100644
--- a/erts/emulator/drivers/common/efile_drv.c
+++ b/erts/emulator/drivers/common/efile_drv.c
@@ -397,7 +397,6 @@ struct t_pwritev {
ErlDrvPort port;
ErlDrvPDL q_mtx;
size_t size;
- size_t free_size;
unsigned cnt;
unsigned n;
struct t_pbuf_spec specs[1];
@@ -462,7 +461,6 @@ struct t_data
ErlDrvPort port;
ErlDrvPDL q_mtx;
size_t size;
- size_t free_size;
size_t reply_size;
} writev;
struct t_pwritev pwritev;
@@ -1346,7 +1344,7 @@ static void invoke_preadv(void *data)
= efile_pread(&d->errInfo,
(int) d->fd,
c->offsets[c->cnt] + c->size,
- ev->iov[1 + c->cnt].iov_base + c->size,
+ ((char *)ev->iov[1 + c->cnt].iov_base) + c->size,
read_size,
&bytes_read))) {
bytes_read_so_far += bytes_read;
@@ -1532,26 +1530,24 @@ static void invoke_writev(void *data) {
}
EF_FREE(iov);
- d->c.writev.free_size = size;
- d->c.writev.size -= size;
if (! d->result_ok) {
d->again = 0;
+ MUTEX_LOCK(d->c.writev.q_mtx);
+ driver_deq(d->c.writev.port, d->c.writev.size);
+ MUTEX_UNLOCK(d->c.writev.q_mtx);
} else {
if (! segment) {
d->again = 0;
}
+ d->c.writev.size -= size;
TRACE_F(("w%lu", (unsigned long)size));
-
+ MUTEX_LOCK(d->c.writev.q_mtx);
+ driver_deq(d->c.writev.port, size);
+ MUTEX_UNLOCK(d->c.writev.q_mtx);
}
- DTRACE_INVOKE_RETURN(FILE_WRITE);
-}
-static void free_writev(void *data) {
- struct t_data *d = data;
- MUTEX_LOCK(d->c.writev.q_mtx);
- driver_deq(d->c.writev.port, d->c.writev.size + d->c.writev.free_size);
- MUTEX_UNLOCK(d->c.writev.q_mtx);
- EF_FREE(d);
+
+ DTRACE_INVOKE_RETURN(FILE_WRITE);
}
static void invoke_pwd(void *data)
@@ -1602,7 +1598,7 @@ static void invoke_pwritev(void *data) {
struct t_pwritev *c = &d->c.pwritev;
size_t p;
int segment;
- size_t size, write_size;
+ size_t size, write_size, written;
DTRACE_INVOKE_SETUP(FILE_PWRITEV);
segment = d->again && c->size >= 2*FILE_SEGMENT_WRITE;
@@ -1622,39 +1618,35 @@ static void invoke_pwritev(void *data) {
if (iovlen < 0)
goto error; /* Port terminated */
- for (iovcnt = 0, c->free_size = 0;
- c->cnt < c->n && iovcnt < iovlen && c->free_size < size;
+ for (iovcnt = 0, written = 0;
+ c->cnt < c->n && iovcnt < iovlen && written < size;
c->cnt++) {
int chop;
write_size = c->specs[c->cnt].size;
if (iov[iovcnt].iov_len - p < write_size) {
- /* Mismatch between pos/size spec and what is queued */
- d->errInfo.posix_errno = EINVAL;
- d->result_ok = 0;
- d->again = 0;
- goto done;
+ goto error;
}
- chop = segment && c->free_size + write_size >= 2*FILE_SEGMENT_WRITE;
+ chop = segment && written + write_size >= 2*FILE_SEGMENT_WRITE;
if (chop) {
- ASSERT(c->free_size < FILE_SEGMENT_WRITE);
+ ASSERT(written < FILE_SEGMENT_WRITE);
write_size = FILE_SEGMENT_WRITE + FILE_SEGMENT_WRITE/2
- - c->free_size;
+ - written;
}
d->result_ok = efile_pwrite(&d->errInfo, (int) d->fd,
- iov[iovcnt].iov_base + p,
+ (char *)(iov[iovcnt].iov_base) + p,
write_size,
c->specs[c->cnt].offset);
if (! d->result_ok) {
d->again = 0;
- goto done;
+ goto deq_error;
}
- c->free_size += write_size;
+ written += write_size;
c->size -= write_size;
if (chop) {
c->specs[c->cnt].offset += write_size;
c->specs[c->cnt].size -= write_size;
/* Schedule out (d->again != 0) */
- goto done;
+ break;
}
/* Move forward in buffer */
p += write_size;
@@ -1676,25 +1668,28 @@ static void invoke_pwritev(void *data) {
d->errInfo.posix_errno = EINVAL;
d->result_ok = 0;
d->again = 0;
+ deq_error:
+ MUTEX_LOCK(d->c.writev.q_mtx);
+ driver_deq(d->c.pwritev.port, c->size);
+ MUTEX_UNLOCK(d->c.writev.q_mtx);
+
+ goto done;
} else {
- ASSERT(c->free_size == size);
+ ASSERT(written == size);
d->again = 0;
}
- }
+ } else
+ ASSERT(written == FILE_SEGMENT_WRITE);
+
+ MUTEX_LOCK(d->c.writev.q_mtx);
+ driver_deq(d->c.pwritev.port, size);
+ MUTEX_UNLOCK(d->c.writev.q_mtx);
done:
EF_FREE(iov); /* Free our copy of the vector, nothing to restore */
+
DTRACE_INVOKE_RETURN(FILE_PWRITEV);
}
-static void free_pwritev(void *data) {
- struct t_data *d = data;
-
- MUTEX_LOCK(d->c.writev.q_mtx);
- driver_deq(d->c.pwritev.port, d->c.pwritev.free_size + d->c.pwritev.size);
- MUTEX_UNLOCK(d->c.writev.q_mtx);
- EF_FREE(d);
-}
-
static void invoke_flstat(void *data)
{
struct t_data *d = (struct t_data *) data;
@@ -2008,21 +2003,8 @@ static void try_free_read_bin(file_descriptor *desc) {
static int try_again(file_descriptor *desc, struct t_data *d) {
- if (! d->again) {
+ if (! d->again)
return 0;
- }
- switch (d->command) {
- case FILE_WRITE:
- MUTEX_LOCK(d->c.writev.q_mtx);
- driver_deq(d->c.writev.port, d->c.writev.free_size);
- MUTEX_UNLOCK(d->c.writev.q_mtx);
- break;
- case FILE_PWRITEV:
- MUTEX_LOCK(d->c.writev.q_mtx);
- driver_deq(d->c.pwritev.port, d->c.pwritev.free_size);
- MUTEX_UNLOCK(d->c.writev.q_mtx);
- break;
- }
if (desc->timer_state != timer_idle) {
driver_cancel_timer(desc->port);
}
@@ -2078,10 +2060,9 @@ static struct t_data *async_write(file_descriptor *desc, int *errp,
}
#endif
d->reply = reply;
- d->c.writev.free_size = 0;
d->c.writev.reply_size = reply_size;
d->invoke = invoke_writev;
- d->free = free_writev;
+ d->free = free_data;
d->level = 1;
cq_enq(desc, d);
desc->write_buffered = 0;
@@ -2394,7 +2375,7 @@ file_async_ready(ErlDrvData e, ErlDrvThreadData data)
desc->write_errInfo = d->errInfo;
}
}
- free_writev(data);
+ free_data(data);
break;
case FILE_LSEEK:
if (d->reply) {
@@ -2524,7 +2505,7 @@ file_async_ready(ErlDrvData e, ErlDrvThreadData data)
} else {
reply_Uint(desc, d->c.pwritev.n);
}
- free_pwritev(data);
+ free_data(data);
break;
case FILE_PREADV:
if (!d->result_ok) {
@@ -2559,7 +2540,7 @@ file_async_ready(ErlDrvData e, ErlDrvThreadData data)
reply_Sint64(desc, d->c.sendfile.written);
desc->sendfile_state = not_sending;
free_sendfile(data);
- } else if (d->result_ok == 1) { // If we are using select to send the rest of the data
+ } else if (d->result_ok == 1) { /* If we are using select to send the rest of the data */
desc->sendfile_state = sending;
desc->d = d;
driver_select(desc->port, (ErlDrvEvent)(long)d->c.sendfile.out_fd,
@@ -2581,7 +2562,7 @@ file_async_ready(ErlDrvData e, ErlDrvThreadData data)
}
DTRACE6(efile_drv_return, sched_i1, sched_i2, sched_utag,
command, result_ok, posix_errno);
- if (desc->write_buffered != 0 && desc->timer_state == timer_idle) {
+ if (desc->write_buffered != 0 && desc->timer_state == timer_idle ) {
desc->timer_state = timer_write;
driver_set_timer(desc->port, desc->write_delay);
}
@@ -3651,7 +3632,6 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) {
#ifdef USE_VM_PROBES
dt_i3 = d->c.pwritev.size;
#endif
- d->c.pwritev.free_size = 0;
if (j == 0) {
/* Trivial case - nothing to write */
EF_FREE(d);
@@ -3675,7 +3655,7 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) {
MUTEX_UNLOCK(desc->q_mtx);
/* Execute the command */
d->invoke = invoke_pwritev;
- d->free = free_pwritev;
+ d->free = free_data;
d->level = 1;
cq_enq(desc, d);
}
@@ -3813,7 +3793,7 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) {
res_ev->iov[0].iov_base = res_ev->binv[0]->orig_bytes;
/* Fill in the number of buffers in the header */
put_int32(0, res_ev->iov[0].iov_base);
- put_int32(n, res_ev->iov[0].iov_base+4);
+ put_int32(n, (char *)(res_ev->iov[0].iov_base) + 4);
/**/
res_ev->size = res_ev->iov[0].iov_len;
if (n == 0) {
@@ -4114,7 +4094,7 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) {
}
if (hd_len != 0 || tl_len != 0 || flags != 0) {
- // We do not allow header, trailers and/or flags right now
+ /* We do not allow header, trailers and/or flags right now */
reply_posix_error(desc, EINVAL);
goto done;
}
diff --git a/erts/emulator/drivers/common/erl_efile.h b/erts/emulator/drivers/common/erl_efile.h
index b29b4f971c..bd85e43b8c 100644
--- a/erts/emulator/drivers/common/erl_efile.h
+++ b/erts/emulator/drivers/common/erl_efile.h
@@ -67,7 +67,7 @@
#define FILENAMES_16BIT 1
#endif
-// We use sendfilev if it exist on solaris
+/* We use sendfilev if it exist on solaris */
#if !defined(HAVE_SENDFILE) && defined(HAVE_SENDFILEV)
#define HAVE_SENDFILE
#endif
@@ -88,20 +88,6 @@ typedef struct _Efile_error {
} Efile_error;
/*
- * This structure contains date and time.
- */
-
-//typedef struct _Efile_time {
-// unsigned year; /* (4 digits). */
-// unsigned month; /* (1..12). */
-// unsigned day; /* (1..31). */
-// unsigned hour; /* (0..23). */
-// unsigned minute; /* (0..59). */
-// unsigned second; /* (0..59). */
-//} Efile_time;
-
-
-/*
* Describes what is returned by file:file_info/1.
*/
diff --git a/erts/emulator/drivers/common/inet_drv.c b/erts/emulator/drivers/common/inet_drv.c
index fb128fff7d..301ce2d0e2 100644
--- a/erts/emulator/drivers/common/inet_drv.c
+++ b/erts/emulator/drivers/common/inet_drv.c
@@ -678,8 +678,8 @@ static int my_strncasecmp(const char *s1, const char *s2, size_t n)
#define INET_LOPT_UDP_READ_PACKETS 33 /* Number of packets to read */
#define INET_OPT_RAW 34 /* Raw socket options */
#define INET_LOPT_TCP_SEND_TIMEOUT_CLOSE 35 /* auto-close on send timeout or not */
-#define INET_LOPT_TCP_MSGQ_HIWTRMRK 36 /* set local high watermark */
-#define INET_LOPT_TCP_MSGQ_LOWTRMRK 37 /* set local low watermark */
+#define INET_LOPT_MSGQ_HIWTRMRK 36 /* set local msgq high watermark */
+#define INET_LOPT_MSGQ_LOWTRMRK 37 /* set local msgq low watermark */
/* SCTP options: a separate range, from 100: */
#define SCTP_OPT_RTOINFO 100
#define SCTP_OPT_ASSOCINFO 101
@@ -3854,8 +3854,10 @@ static void desc_close(inet_descriptor* desc)
desc->forced_events = 0;
desc->send_would_block = 0;
#endif
- // We should close the fd here, but the other driver might still
- // be selecting on it.
+ /*
+ * We should close the fd here, but the other driver might still
+ * be selecting on it.
+ */
if (!desc->is_ignored)
driver_select(desc->port,(ErlDrvEvent)(long)desc->event,
ERL_DRV_USE, 0);
@@ -5474,27 +5476,25 @@ static int inet_set_opts(inet_descriptor* desc, char* ptr, int len)
}
continue;
- case INET_LOPT_TCP_MSGQ_HIWTRMRK:
- if (desc->stype == SOCK_STREAM) {
- ErlDrvSizeT high;
- if (ival < ERL_DRV_BUSY_MSGQ_LIM_MIN
- || ERL_DRV_BUSY_MSGQ_LIM_MAX < ival)
- return -1;
- high = (ErlDrvSizeT) ival;
- erl_drv_busy_msgq_limits(desc->port, NULL, &high);
- }
+ case INET_LOPT_MSGQ_HIWTRMRK: {
+ ErlDrvSizeT high;
+ if (ival < ERL_DRV_BUSY_MSGQ_LIM_MIN
+ || ERL_DRV_BUSY_MSGQ_LIM_MAX < ival)
+ return -1;
+ high = (ErlDrvSizeT) ival;
+ erl_drv_busy_msgq_limits(desc->port, NULL, &high);
continue;
+ }
- case INET_LOPT_TCP_MSGQ_LOWTRMRK:
- if (desc->stype == SOCK_STREAM) {
- ErlDrvSizeT low;
- if (ival < ERL_DRV_BUSY_MSGQ_LIM_MIN
- || ERL_DRV_BUSY_MSGQ_LIM_MAX < ival)
- return -1;
- low = (ErlDrvSizeT) ival;
- erl_drv_busy_msgq_limits(desc->port, &low, NULL);
- }
+ case INET_LOPT_MSGQ_LOWTRMRK: {
+ ErlDrvSizeT low;
+ if (ival < ERL_DRV_BUSY_MSGQ_LIM_MIN
+ || ERL_DRV_BUSY_MSGQ_LIM_MAX < ival)
+ return -1;
+ low = (ErlDrvSizeT) ival;
+ erl_drv_busy_msgq_limits(desc->port, &low, NULL);
continue;
+ }
case INET_LOPT_TCP_SEND_TIMEOUT:
if (desc->stype == SOCK_STREAM) {
@@ -6396,31 +6396,23 @@ static ErlDrvSSizeT inet_fill_opts(inet_descriptor* desc,
}
continue;
- case INET_LOPT_TCP_MSGQ_HIWTRMRK:
- if (desc->stype == SOCK_STREAM) {
- ErlDrvSizeT high = ERL_DRV_BUSY_MSGQ_READ_ONLY;
- *ptr++ = opt;
- erl_drv_busy_msgq_limits(desc->port, NULL, &high);
- ival = high > INT_MAX ? INT_MAX : (int) high;
- put_int32(ival, ptr);
- }
- else {
- TRUNCATE_TO(0,ptr);
- }
+ case INET_LOPT_MSGQ_HIWTRMRK: {
+ ErlDrvSizeT high = ERL_DRV_BUSY_MSGQ_READ_ONLY;
+ *ptr++ = opt;
+ erl_drv_busy_msgq_limits(desc->port, NULL, &high);
+ ival = high > INT_MAX ? INT_MAX : (int) high;
+ put_int32(ival, ptr);
continue;
+ }
- case INET_LOPT_TCP_MSGQ_LOWTRMRK:
- if (desc->stype == SOCK_STREAM) {
- ErlDrvSizeT low = ERL_DRV_BUSY_MSGQ_READ_ONLY;
- *ptr++ = opt;
- erl_drv_busy_msgq_limits(desc->port, &low, NULL);
- ival = low > INT_MAX ? INT_MAX : (int) low;
- put_int32(ival, ptr);
- }
- else {
- TRUNCATE_TO(0,ptr);
- }
+ case INET_LOPT_MSGQ_LOWTRMRK: {
+ ErlDrvSizeT low = ERL_DRV_BUSY_MSGQ_READ_ONLY;
+ *ptr++ = opt;
+ erl_drv_busy_msgq_limits(desc->port, &low, NULL);
+ ival = low > INT_MAX ? INT_MAX : (int) low;
+ put_int32(ival, ptr);
continue;
+ }
case INET_LOPT_TCP_SEND_TIMEOUT:
if (desc->stype == SOCK_STREAM) {
@@ -7469,6 +7461,20 @@ static void inet_stop(inet_descriptor* desc)
FREE(desc);
}
+static void set_default_msgq_limits(ErlDrvPort port)
+{
+ ErlDrvSizeT q_high = INET_HIGH_MSGQ_WATERMARK;
+ ErlDrvSizeT q_low = INET_LOW_MSGQ_WATERMARK;
+ if (q_low < ERL_DRV_BUSY_MSGQ_LIM_MIN)
+ q_low = ERL_DRV_BUSY_MSGQ_LIM_MIN;
+ else if (q_low > ERL_DRV_BUSY_MSGQ_LIM_MAX)
+ q_low = ERL_DRV_BUSY_MSGQ_LIM_MAX;
+ if (q_high < ERL_DRV_BUSY_MSGQ_LIM_MIN)
+ q_high = ERL_DRV_BUSY_MSGQ_LIM_MIN;
+ else if (q_high > ERL_DRV_BUSY_MSGQ_LIM_MAX)
+ q_high = ERL_DRV_BUSY_MSGQ_LIM_MAX;
+ erl_drv_busy_msgq_limits(port, &q_low, &q_high);
+}
/* Allocate descriptor */
static ErlDrvData inet_start(ErlDrvPort port, int size, int protocol)
@@ -8089,9 +8095,8 @@ static int tcp_inet_init(void)
/* initialize the TCP descriptor */
-static ErlDrvData tcp_inet_start(ErlDrvPort port, char* args)
+static ErlDrvData prep_tcp_inet_start(ErlDrvPort port, char* args)
{
- ErlDrvSizeT q_low, q_high;
tcp_descriptor* desc;
DEBUGF(("tcp_inet_start(%ld) {\r\n", (long)port));
@@ -8101,17 +8106,6 @@ static ErlDrvData tcp_inet_start(ErlDrvPort port, char* args)
return ERL_DRV_ERROR_ERRNO;
desc->high = INET_HIGH_WATERMARK;
desc->low = INET_LOW_WATERMARK;
- q_high = INET_HIGH_MSGQ_WATERMARK;
- q_low = INET_LOW_MSGQ_WATERMARK;
- if (q_low < ERL_DRV_BUSY_MSGQ_LIM_MIN)
- q_low = ERL_DRV_BUSY_MSGQ_LIM_MIN;
- else if (q_low > ERL_DRV_BUSY_MSGQ_LIM_MAX)
- q_low = ERL_DRV_BUSY_MSGQ_LIM_MAX;
- if (q_high < ERL_DRV_BUSY_MSGQ_LIM_MIN)
- q_high = ERL_DRV_BUSY_MSGQ_LIM_MIN;
- else if (q_high > ERL_DRV_BUSY_MSGQ_LIM_MAX)
- q_high = ERL_DRV_BUSY_MSGQ_LIM_MAX;
- erl_drv_busy_msgq_limits(port, &q_low, &q_high);
desc->send_timeout = INET_INFINITY;
desc->send_timeout_close = 0;
desc->busy_on_send = 0;
@@ -8128,6 +8122,12 @@ static ErlDrvData tcp_inet_start(ErlDrvPort port, char* args)
return (ErlDrvData) desc;
}
+static ErlDrvData tcp_inet_start(ErlDrvPort port, char* args)
+{
+ ErlDrvData data = prep_tcp_inet_start(port, args);
+ set_default_msgq_limits(port);
+ return data;
+}
/* Copy a descriptor, by creating a new port with same settings
* as the descriptor desc.
* return NULL on error (SYSTEM_LIMIT no ports avail)
@@ -8139,7 +8139,7 @@ static tcp_descriptor* tcp_inet_copy(tcp_descriptor* desc,SOCKET s,
ErlDrvPort port = desc->inet.port;
tcp_descriptor* copy_desc;
- copy_desc = (tcp_descriptor*) tcp_inet_start(port, NULL);
+ copy_desc = (tcp_descriptor*) prep_tcp_inet_start(port, NULL);
/* Setup event if needed */
if ((copy_desc->inet.s = s) != INVALID_SOCKET) {
@@ -9862,12 +9862,15 @@ static int should_use_so_bsdcompat(void)
* as the descriptor desc.
* return NULL on error (ENFILE no ports avail)
*/
+static ErlDrvData packet_inet_start(ErlDrvPort port, char* args, int protocol);
+
static udp_descriptor* sctp_inet_copy(udp_descriptor* desc, SOCKET s, int* err)
{
+ ErlDrvSizeT q_low, q_high;
ErlDrvPort port = desc->inet.port;
udp_descriptor* copy_desc;
- copy_desc = (udp_descriptor*) sctp_inet_start(port, NULL);
+ copy_desc = (udp_descriptor*) packet_inet_start(port, NULL, IPPROTO_SCTP);
/* Setup event if needed */
if ((copy_desc->inet.s = s) != INVALID_SOCKET) {
@@ -9898,9 +9901,17 @@ static udp_descriptor* sctp_inet_copy(udp_descriptor* desc, SOCKET s, int* err)
FREE(copy_desc);
return NULL;
}
+
+ /* Read busy msgq limits of parent */
+ q_low = q_high = ERL_DRV_BUSY_MSGQ_READ_ONLY;
+ erl_drv_busy_msgq_limits(desc->inet.port, &q_low, &q_high);
+ /* Write same busy msgq limits to child */
+ erl_drv_busy_msgq_limits(port, &q_low, &q_high);
+
copy_desc->inet.port = port;
copy_desc->inet.dport = driver_mk_port(port);
*err = 0;
+
return copy_desc;
}
#endif
@@ -9933,13 +9944,17 @@ static ErlDrvData packet_inet_start(ErlDrvPort port, char* args, int protocol)
static ErlDrvData udp_inet_start(ErlDrvPort port, char *args)
{
- return packet_inet_start(port, args, IPPROTO_UDP);
+ ErlDrvData data = packet_inet_start(port, args, IPPROTO_UDP);
+ set_default_msgq_limits(port);
+ return data;
}
#ifdef HAVE_SCTP
static ErlDrvData sctp_inet_start(ErlDrvPort port, char *args)
{
- return packet_inet_start(port, args, IPPROTO_SCTP);
+ ErlDrvData data = packet_inet_start(port, args, IPPROTO_SCTP);
+ set_default_msgq_limits(port);
+ return data;
}
#endif
diff --git a/erts/emulator/drivers/common/zlib_drv.c b/erts/emulator/drivers/common/zlib_drv.c
index 60394b610b..89b7be14f2 100644
--- a/erts/emulator/drivers/common/zlib_drv.c
+++ b/erts/emulator/drivers/common/zlib_drv.c
@@ -119,7 +119,7 @@ static int zlib_deflate(ZLibData* d, int flush);
#if defined(__WIN32__)
static int i32(char* buf)
#else
-static inline int i32(char* buf)
+static __inline__ int i32(char* buf)
#endif
{
return (int) (
diff --git a/erts/emulator/drivers/unix/ttsl_drv.c b/erts/emulator/drivers/unix/ttsl_drv.c
index 8912d148a5..d76401a790 100644
--- a/erts/emulator/drivers/unix/ttsl_drv.c
+++ b/erts/emulator/drivers/unix/ttsl_drv.c
@@ -42,6 +42,9 @@ static ErlDrvData ttysl_start(ErlDrvPort, char*);
#include <locale.h>
#include <unistd.h>
#include <termios.h>
+#ifdef HAVE_WCWIDTH
+#include <wchar.h>
+#endif
#ifdef HAVE_FCNTL_H
#include <fcntl.h>
#endif
@@ -95,6 +98,9 @@ static int lpos; /* The current "cursor position" in the line buf
*/
#define CONTROL_TAG 0x10000000U /* Control character, value in first position */
#define ESCAPED_TAG 0x01000000U /* Escaped character, value in first position */
+#ifdef HAVE_WCWIDTH
+#define WIDE_TAG 0x02000000U /* Wide character, value in first position */
+#endif
#define TAG_MASK 0xFF000000U
#define MAXSIZE (1 << 16)
@@ -597,12 +603,20 @@ static int check_buf_size(byte *s, int n)
}
if (utf8_mode) { /* That is, terminal is UTF8 compliant */
if (ch >= 128 || isprint(ch)) {
- DEBUGLOG(("Printable(UTF-8:%d):%d",(pos - opos),ch));
- size++; /* Buffer contains wide characters... */
+#ifdef HAVE_WCWIDTH
+ int width;
+#endif
+ DEBUGLOG(("Printable(UTF-8:%d):%d",pos,ch));
+ size++;
+#ifdef HAVE_WCWIDTH
+ if ((width = wcwidth(ch)) > 1) {
+ size += width - 1;
+ }
+#endif
} else if (ch == '\t') {
size += 8;
} else {
- DEBUGLOG(("Magic(UTF-8:%d):%d",(pos - opos),ch));
+ DEBUGLOG(("Magic(UTF-8:%d):%d",pos,ch));
size += 2;
}
} else {
@@ -823,7 +837,7 @@ static int del_chars(int n)
r = llen - lpos - l; /* Characters after deleted */
/* Fix up buffer and buffer pointers. */
if (r > 0)
- memcpy(lbuf + lpos, lbuf + pos, r * sizeof(Uint32));
+ memmove(lbuf + lpos, lbuf + pos, r * sizeof(Uint32));
llen -= l;
/* Write out characters after, blank the tail and jump back to lpos. */
write_buf(lbuf + lpos, r);
@@ -842,7 +856,7 @@ static int del_chars(int n)
move_cursor(lpos, lpos-l); /* Move back */
/* Fix up buffer and buffer pointers. */
if (r > 0)
- memcpy(lbuf + pos, lbuf + lpos, r * sizeof(Uint32));
+ memmove(lbuf + pos, lbuf + lpos, r * sizeof(Uint32));
lpos -= l;
llen -= l;
/* Write out characters after, blank the tail and jump back to lpos. */
@@ -868,12 +882,22 @@ static int step_over_chars(int n)
end = lbuf + llen;
c = lbuf + lpos;
for ( ; n > 0 && c < end; --n) {
+#ifdef HAVE_WCWIDTH
+ while (*c & WIDE_TAG) {
+ c++;
+ }
+#endif
c++;
while (c < end && (*c & TAG_MASK) && ((*c & ~TAG_MASK) == 0))
c++;
}
for ( ; n < 0 && c > beg; n++) {
--c;
+#ifdef HAVE_WCWIDTH
+ while (c > beg + 1 && (c[-1] & WIDE_TAG)) {
+ --c;
+ }
+#endif
while (c > beg && (*c & TAG_MASK) && ((*c & ~TAG_MASK) == 0))
--c;
}
@@ -899,6 +923,15 @@ static int insert_buf(byte *s, int n)
++pos;
}
if ((utf8_mode && (ch >= 128 || isprint(ch))) || (ch <= 255 && isprint(ch))) {
+#ifdef HAVE_WCWIDTH
+ int width;
+ if ((width = wcwidth(ch)) > 1) {
+ while (--width) {
+ DEBUGLOG(("insert_buf: Wide(UTF-8):%d,%d",width,ch));
+ lbuf[lpos++] = (WIDE_TAG | ((Uint32) ch));
+ }
+ }
+#endif
DEBUGLOG(("insert_buf: Printable(UTF-8):%d",ch));
lbuf[lpos++] = (Uint32) ch;
} else if (ch >= 128) { /* not utf8 mode */
@@ -1006,6 +1039,8 @@ static int write_buf(Uint32 *s, int n)
if (octbuff != octtmp) {
driver_free(octbuff);
}
+ } else if (*s & WIDE_TAG) {
+ --n; s++;
} else {
DEBUGLOG(("Very unexpected character %d",(int) *s));
++n;
diff --git a/erts/emulator/drivers/unix/unix_efile.c b/erts/emulator/drivers/unix/unix_efile.c
index 558651fff9..2bd5177be1 100644
--- a/erts/emulator/drivers/unix/unix_efile.c
+++ b/erts/emulator/drivers/unix/unix_efile.c
@@ -629,7 +629,7 @@ efile_writev(Efile_error* errInfo, /* Where to return error codes */
if (w < iov[cnt].iov_len) {
/* Adjust the buffer for next write */
iov[cnt].iov_len -= w;
- iov[cnt].iov_base += w;
+ iov[cnt].iov_base = ((char *)iov[cnt].iov_base) + w;
w = 0;
break;
} else {
diff --git a/erts/emulator/drivers/win32/ttsl_drv.c b/erts/emulator/drivers/win32/ttsl_drv.c
index 1a74d21e99..8b5e3eeefd 100644
--- a/erts/emulator/drivers/win32/ttsl_drv.c
+++ b/erts/emulator/drivers/win32/ttsl_drv.c
@@ -414,12 +414,12 @@ static int check_buf_size(byte *s, int n)
}
if (utf8_mode) { /* That is, terminal is UTF8 compliant */
if (ch >= 128 || isprint(ch)) {
- DEBUGLOG(("Printable(UTF-8:%d):%d",(pos - opos),ch));
+ DEBUGLOG(("Printable(UTF-8:%d):%d",pos,ch));
size++; /* Buffer contains wide characters... */
} else if (ch == '\t') {
size += 8;
} else {
- DEBUGLOG(("Magic(UTF-8:%d):%d",(pos - opos),ch));
+ DEBUGLOG(("Magic(UTF-8:%d):%d",pos,ch));
size += 2;
}
} else {
diff --git a/erts/emulator/hipe/hipe_native_bif.c b/erts/emulator/hipe/hipe_native_bif.c
index ae2c650bd2..1f76268934 100644
--- a/erts/emulator/hipe/hipe_native_bif.c
+++ b/erts/emulator/hipe/hipe_native_bif.c
@@ -238,7 +238,7 @@ void hipe_handle_exception(Process *c_p)
if (c_p->mbuf) {
erts_printf("%s line %u: p==%p, p->mbuf==%p\n", __FUNCTION__, __LINE__, c_p, c_p->mbuf);
- //erts_garbage_collect(c_p, 0, NULL, 0);
+ /* erts_garbage_collect(c_p, 0, NULL, 0); */
}
/*
@@ -270,7 +270,7 @@ void hipe_handle_exception(Process *c_p)
c_p->def_arg_reg[0] = exception_tag[GET_EXC_CLASS(c_p->freason)];
if (c_p->mbuf) {
- //erts_printf("%s line %u: p==%p, p->mbuf==%p, p->lastbif==%p\n", __FUNCTION__, __LINE__, c_p, c_p->mbuf, c_p->hipe.lastbif);
+ /* erts_printf("%s line %u: p==%p, p->mbuf==%p, p->lastbif==%p\n", __FUNCTION__, __LINE__, c_p, c_p->mbuf, c_p->hipe.lastbif); */
erts_garbage_collect(c_p, 0, NULL, 0);
}
diff --git a/erts/emulator/hipe/hipe_x86_gc.h b/erts/emulator/hipe/hipe_x86_gc.h
index ccb0d2ffb8..ac6b4f70bb 100644
--- a/erts/emulator/hipe/hipe_x86_gc.h
+++ b/erts/emulator/hipe/hipe_x86_gc.h
@@ -25,7 +25,7 @@
#include "hipe_x86_asm.h" /* for NR_ARG_REGS */
/* uncomment to simulate & test what the initial PowerPC port will do */
-//#define SKIP_YOUNGEST_FRAME
+/* #define SKIP_YOUNGEST_FRAME */
struct nstack_walk_state {
#ifdef SKIP_YOUNGEST_FRAME
diff --git a/erts/emulator/hipe/hipe_x86_signal.c b/erts/emulator/hipe/hipe_x86_signal.c
index 64c0e0da3e..19fc448742 100644
--- a/erts/emulator/hipe/hipe_x86_signal.c
+++ b/erts/emulator/hipe/hipe_x86_signal.c
@@ -183,6 +183,7 @@ static void do_init(void)
#include <dlfcn.h>
static int (*__next_sigaction)(int, const struct sigaction*, struct sigaction*);
#define init_done() (__next_sigaction != 0)
+extern int _sigaction(int, const struct sigaction*, struct sigaction*);
#define __SIGACTION _sigaction
static void do_init(void)
{
diff --git a/erts/emulator/internal_doc/dec.erl b/erts/emulator/internal_doc/dec.erl
index 0315f2a52d..255018abe0 100644
--- a/erts/emulator/internal_doc/dec.erl
+++ b/erts/emulator/internal_doc/dec.erl
@@ -1,3 +1,4 @@
+%% -*- coding: utf-8 -*-
%%
%% %CopyrightBegin%
%%
@@ -25,10 +26,10 @@
%% {RevList,Translation}
%% Where 'RevList' is a reversed list of the denormalized repressentation of
%% the character 'Translation'. An example would be the swedish character
-%% '�', which would be represented in the file as:
+%% 'ö', which would be represented in the file as:
%% {[776,111],246}, as the denormalized representation of codepoint 246
%% is [111,776] (i.e an 'o' followed by the "double dot accent character 776),
-%% while '�' instead is represented as {[776,97],228}, as the denormalized
+%% while 'ä' instead is represented as {[776,97],228}, as the denormalized
%% form would be [97,776] (same accent but an 'a' instead).
%% The datafile is generated from the table on Apple's developer connection
%% http://developer.apple.com/library/mac/#technotes/tn/tn1150table.html
diff --git a/erts/emulator/pcre/pcre_exec.c b/erts/emulator/pcre/pcre_exec.c
index 3fe13ca32e..26cb219ef1 100644
--- a/erts/emulator/pcre/pcre_exec.c
+++ b/erts/emulator/pcre/pcre_exec.c
@@ -36,7 +36,7 @@ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
-----------------------------------------------------------------------------
*/
-//#define ERLANG_DEBUG 1
+/* #define ERLANG_DEBUG 1 */
/* This module contains erts_pcre_exec(), the externally visible function that does
pattern matching using an NFA algorithm, trying to mimic Perl as closely as
diff --git a/erts/emulator/sys/common/erl_mseg.c b/erts/emulator/sys/common/erl_mseg.c
index bd8ba82a5f..b6e2c9382b 100644
--- a/erts/emulator/sys/common/erl_mseg.c
+++ b/erts/emulator/sys/common/erl_mseg.c
@@ -350,7 +350,7 @@ schedule_cache_check(ErtsMsegAllctr_t *ma) {
static ERTS_INLINE void *
mmap_align(ErtsMsegAllctr_t *ma, void *addr, size_t length, int prot, int flags, int fd, off_t offset) {
- void *p, *q;
+ char *p, *q;
UWord d;
p = mmap(addr, length, prot, flags, fd, offset);
@@ -366,14 +366,14 @@ mmap_align(ErtsMsegAllctr_t *ma, void *addr, size_t length, int prot, int flags,
if ((p = mmap(addr, length + MSEG_ALIGNED_SIZE, prot, flags, fd, offset)) == MAP_FAILED)
return MAP_FAILED;
- q = (void *)ALIGNED_CEILING(p);
- d = q - p;
+ q = (void *)ALIGNED_CEILING((char *)p);
+ d = (UWord)(q - p);
if (d > 0)
munmap(p, d);
if (MSEG_ALIGNED_SIZE - d > 0)
- munmap((void *) (q + length), MSEG_ALIGNED_SIZE - d);
+ munmap((void *)(q + length), MSEG_ALIGNED_SIZE - d);
return q;
}
@@ -439,7 +439,7 @@ mseg_destroy(ErtsMsegAllctr_t *ma, MemKind* mk, void *seg, Uint size) {
}
#if HAVE_MSEG_RECREATE
-#if defined(__NetBsd__)
+#if defined(__NetBSD__)
#define MREMAP_FLAGS (0)
#else
#define MREMAP_FLAGS (MREMAP_MAYMOVE)
@@ -708,7 +708,7 @@ static ERTS_INLINE void *cache_get_segment(MemKind *mk, Uint *size_p, Uint flags
/* Use current cache placement for remaining segment space */
- best->seg = seg + size;
+ best->seg = ((char *)seg) + size;
best->size = csize - size;
ASSERT((size % GET_PAGE_SIZE) == 0);
@@ -1028,7 +1028,7 @@ mseg_realloc(ErtsMsegAllctr_t *ma, ErtsAlcType_t atype, void *seg,
sys_memcpy(((char *) new_seg),
((char *) seg),
MIN(new_size, old_size));
- mseg_dealloc(ma, atype, seg, old_size, opt);
+ mseg_dealloc(ma, atype, seg, old_size, flags, opt);
}
#endif
}
diff --git a/erts/emulator/sys/unix/sys_float.c b/erts/emulator/sys/unix/sys_float.c
index f2f4de869d..689be98969 100644
--- a/erts/emulator/sys/unix/sys_float.c
+++ b/erts/emulator/sys/unix/sys_float.c
@@ -152,7 +152,7 @@ static int mask_sse2(void)
#if defined(__x86_64__)
-static inline int cpu_has_sse2(void) { return 1; }
+static ERTS_INLINE int cpu_has_sse2(void) { return 1; }
#else /* !__x86_64__ */
@@ -179,7 +179,7 @@ static unsigned int xor_eflags(unsigned int mask)
return eax;
}
-static __inline__ unsigned int cpuid_eax(unsigned int op)
+static ERTS_INLINE unsigned int cpuid_eax(unsigned int op)
{
unsigned int eax, save_ebx;
@@ -195,7 +195,7 @@ static __inline__ unsigned int cpuid_eax(unsigned int op)
return eax;
}
-static __inline__ unsigned int cpuid_edx(unsigned int op)
+static ERTS_INLINE unsigned int cpuid_edx(unsigned int op)
{
unsigned int eax, edx, save_ebx;
@@ -215,7 +215,7 @@ static __inline__ unsigned int cpuid_edx(unsigned int op)
* register on the Intel486 processor to generate alignment
* faults. This bit cannot be set on the Intel386 processor.
*/
-static __inline__ int is_386(void)
+static ERTS_INLINE int is_386(void)
{
return ((xor_eflags(1<<18) >> 18) & 1) == 0;
}
@@ -223,7 +223,7 @@ static __inline__ int is_386(void)
/* Newer x86 processors have a CPUID instruction, as indicated by
* the ID bit (#21) in EFLAGS being modifiable.
*/
-static __inline__ int has_CPUID(void)
+static ERTS_INLINE int has_CPUID(void)
{
return (xor_eflags(1<<21) >> 21) & 1;
}
@@ -832,6 +832,8 @@ sys_chars_to_double(char* buf, double* fp)
return 0;
}
+#ifdef USE_MATHERR
+
int
matherr(struct exception *exc)
{
@@ -842,3 +844,5 @@ matherr(struct exception *exc)
#endif
return 1;
}
+
+#endif
diff --git a/erts/emulator/sys/win32/sys.c b/erts/emulator/sys/win32/sys.c
index e0422de026..922967c698 100755
--- a/erts/emulator/sys/win32/sys.c
+++ b/erts/emulator/sys/win32/sys.c
@@ -399,11 +399,12 @@ int* pBuild; /* Pointer to build number. */
* Definitions for driver flags.
*/
-#define DF_OVR_READY 1 /* Overlapped result is ready. */
-#define DF_EXIT_THREAD 2 /* The thread should exit. */
-#define DF_XLAT_CR 4 /* The thread should translate CRs. */
-#define DF_DROP_IF_INVH 8 /* Drop packages instead of crash if
+#define DF_OVR_READY 1 /* Overlapped result is ready. */
+#define DF_EXIT_THREAD 2 /* The thread should exit. */
+#define DF_XLAT_CR 4 /* The thread should translate CRs. */
+#define DF_DROP_IF_INVH 8 /* Drop packages instead of crash if
invalid handle (stderr) */
+#define DF_THREAD_FLUSHED 16 /* The thread should exit. */
#define OV_BUFFER_PTR(dp) ((LPVOID) ((dp)->ov.Internal))
#define OV_NUM_TO_READ(dp) ((dp)->ov.InternalHigh)
@@ -2141,8 +2142,9 @@ threaded_writer(LPVOID param)
for (;;) {
handle = WaitForMultipleObjects(2, handles, FALSE, INFINITE);
- if (aio->flags & DF_EXIT_THREAD)
+ if (aio->flags & DF_EXIT_THREAD) {
break;
+ }
buf = OV_BUFFER_PTR(aio);
numToWrite = OV_NUM_TO_READ(aio);
@@ -2150,6 +2152,7 @@ threaded_writer(LPVOID param)
if (handle == (WAIT_OBJECT_0 + 1) && numToWrite == 0) {
SetEvent(aio->flushReplyEvent);
+ aio->flags |= DF_THREAD_FLUSHED;
continue;
}
@@ -2197,6 +2200,7 @@ threaded_writer(LPVOID param)
if (aio->flags & DF_EXIT_THREAD)
break;
}
+ aio->flags |= DF_THREAD_FLUSHED;
CloseHandle(aio->fd);
aio->fd = INVALID_HANDLE_VALUE;
unrefer_driver_data(aio->dp);
@@ -2340,9 +2344,11 @@ static void fd_stop(ErlDrvData data)
(void) driver_select(dp->port_num,
(ErlDrvEvent)dp->out.ov.hEvent,
ERL_DRV_WRITE, 0);
- ASSERT(dp->out.flushEvent);
- SetEvent(dp->out.flushEvent);
- WaitForSingleObject(dp->out.flushReplyEvent, INFINITE);
+ do {
+ ASSERT(dp->out.flushEvent);
+ SetEvent(dp->out.flushEvent);
+ } while (WaitForSingleObject(dp->out.flushReplyEvent, 10) == WAIT_TIMEOUT
+ || !(dp->out.flags & DF_THREAD_FLUSHED));
}
}
@@ -2433,12 +2439,12 @@ threaded_exiter(LPVOID param)
*/
i = 0;
if (dp->out.thread != (HANDLE) -1) {
- dp->out.flags = DF_EXIT_THREAD;
+ dp->out.flags |= DF_EXIT_THREAD;
SetEvent(dp->out.ioAllowed);
handles[i++] = dp->out.thread;
}
if (dp->in.thread != (HANDLE) -1) {
- dp->in.flags = DF_EXIT_THREAD;
+ dp->in.flags |= DF_EXIT_THREAD;
SetEvent(dp->in.ioAllowed);
handles[i++] = dp->in.thread;
}
diff --git a/erts/emulator/sys/win32/sys_float.c b/erts/emulator/sys/win32/sys_float.c
index fb1ffc3089..e2a777d182 100644
--- a/erts/emulator/sys/win32/sys_float.c
+++ b/erts/emulator/sys/win32/sys_float.c
@@ -133,6 +133,8 @@ sys_double_to_chars_ext(double fp, char *buffer, size_t buffer_size, size_t deci
return s-buffer; /* i.e strlen(buffer) */
}
+#ifdef USE_MATHERR
+
int
matherr(struct _exception *exc)
{
@@ -141,6 +143,8 @@ matherr(struct _exception *exc)
return 1;
}
+#endif
+
static void
fpe_exception(int sig)
{
diff --git a/erts/emulator/test/busy_port_SUITE.erl b/erts/emulator/test/busy_port_SUITE.erl
index 2c63296b83..4b4af0babe 100644
--- a/erts/emulator/test/busy_port_SUITE.erl
+++ b/erts/emulator/test/busy_port_SUITE.erl
@@ -170,6 +170,7 @@ send_3(Config) when is_list(Config) ->
?line {Owner,Slave} = get_slave(),
?line ok = erlang:send(Slave, {Owner,{command,"set busy"}},
[nosuspend]),
+ receive after 100 -> ok end, % ensure command reached port
?line nosuspend = erlang:send(Slave, {Owner,{command,"busy"}},
[nosuspend]),
?line unlock_slave(),
@@ -563,6 +564,7 @@ scheduling_delay_busy_nosuspend(Config) ->
{2,{call,[{var,1},open_port]}},
{0,{cast,[{var,1},{command,1,100}]}},
{0,{cast,[{var,1},{busy,2}]}},
+ {0,{timer,sleep,[200]}}, % ensure reached port
{10,{call,[{var,1},{command,3,[nosuspend]}]}},
{0,{timer,sleep,[200]}},
{0,{erlang,port_command,[{var,2},<<$N>>,[force]]}},
diff --git a/erts/emulator/test/code_parallel_load_SUITE.erl b/erts/emulator/test/code_parallel_load_SUITE.erl
index aa9e4c96c6..d2c80c1ca0 100644
--- a/erts/emulator/test/code_parallel_load_SUITE.erl
+++ b/erts/emulator/test/code_parallel_load_SUITE.erl
@@ -16,7 +16,6 @@
%%
%% %CopyrightEnd%
%%
-%% Author: Björn-Egil Dahlberg
-module(code_parallel_load_SUITE).
-export([