aboutsummaryrefslogtreecommitdiffstats
path: root/erts/emulator/beam
diff options
context:
space:
mode:
Diffstat (limited to 'erts/emulator/beam')
-rw-r--r--erts/emulator/beam/atom.names9
-rw-r--r--erts/emulator/beam/beam_emu.c3
-rw-r--r--erts/emulator/beam/beam_load.c16
-rw-r--r--erts/emulator/beam/bif.c37
-rw-r--r--erts/emulator/beam/bif.tab7
-rw-r--r--erts/emulator/beam/big.c8
-rw-r--r--erts/emulator/beam/binary.c11
-rw-r--r--erts/emulator/beam/break.c7
-rw-r--r--erts/emulator/beam/dist.c8
-rw-r--r--erts/emulator/beam/erl_alloc.c131
-rw-r--r--erts/emulator/beam/erl_alloc.h10
-rw-r--r--erts/emulator/beam/erl_alloc_util.c187
-rw-r--r--erts/emulator/beam/erl_alloc_util.h54
-rw-r--r--erts/emulator/beam/erl_ao_firstfit_alloc.c3
-rw-r--r--erts/emulator/beam/erl_bestfit_alloc.c3
-rw-r--r--erts/emulator/beam/erl_bif_binary.c3
-rwxr-xr-xerts/emulator/beam/erl_bif_info.c12
-rw-r--r--erts/emulator/beam/erl_bif_os.c22
-rw-r--r--erts/emulator/beam/erl_bif_port.c103
-rw-r--r--erts/emulator/beam/erl_bif_re.c469
-rw-r--r--erts/emulator/beam/erl_bif_timer.c2
-rw-r--r--erts/emulator/beam/erl_binary.h8
-rw-r--r--erts/emulator/beam/erl_bits.c111
-rw-r--r--erts/emulator/beam/erl_db.c11
-rw-r--r--erts/emulator/beam/erl_db.h2
-rw-r--r--erts/emulator/beam/erl_db_hash.c2
-rw-r--r--erts/emulator/beam/erl_db_util.h2
-rw-r--r--erts/emulator/beam/erl_driver.h14
-rw-r--r--erts/emulator/beam/erl_gc.c2
-rw-r--r--erts/emulator/beam/erl_lock_check.c5
-rw-r--r--erts/emulator/beam/erl_message.c2
-rw-r--r--erts/emulator/beam/erl_nif.c38
-rw-r--r--erts/emulator/beam/erl_nif.h15
-rw-r--r--erts/emulator/beam/erl_node_container_utils.h10
-rw-r--r--erts/emulator/beam/erl_port_task.h11
-rw-r--r--erts/emulator/beam/erl_process.c4
-rw-r--r--erts/emulator/beam/erl_process.h4
-rw-r--r--erts/emulator/beam/erl_process_dump.c46
-rw-r--r--erts/emulator/beam/erl_trace.c38
-rw-r--r--erts/emulator/beam/erl_unicode.c157
-rw-r--r--erts/emulator/beam/erl_utils.h10
-rw-r--r--erts/emulator/beam/erl_vm.h14
-rw-r--r--erts/emulator/beam/external.c12
-rw-r--r--erts/emulator/beam/external.h4
-rwxr-xr-xerts/emulator/beam/global.h27
-rw-r--r--erts/emulator/beam/io.c7
-rw-r--r--erts/emulator/beam/sys.h64
-rw-r--r--erts/emulator/beam/utils.c18
48 files changed, 1238 insertions, 505 deletions
diff --git a/erts/emulator/beam/atom.names b/erts/emulator/beam/atom.names
index 8433fd826a..eee4badfb8 100644
--- a/erts/emulator/beam/atom.names
+++ b/erts/emulator/beam/atom.names
@@ -71,6 +71,7 @@ atom ac
atom active
atom all
atom all_but_first
+atom all_names
atom alloc_info
atom alloc_sizes
atom allocated
@@ -323,6 +324,8 @@ atom low
atom Lt='<'
atom machine
atom match
+atom match_limit
+atom match_limit_recursion
atom match_spec
atom max
atom maximum
@@ -352,11 +355,13 @@ atom multi_scheduling
atom multiline
atom name
atom named_table
+atom namelist
atom native_addresses
atom Neq='=/='
atom Neqeq='/='
atom net_kernel
atom net_kernel_terminated
+atom never_utf
atom new
atom new_index
atom new_uniq
@@ -382,6 +387,7 @@ atom nosuspend
atom no_float
atom no_integer
atom no_network
+atom no_start_optimize
atom not
atom not_a_list
atom not_loaded
@@ -392,6 +398,7 @@ atom notalive
atom notbol
atom noteol
atom notempty
+atom notempty_atstart
atom notify
atom notsup
atom nouse_stdio
@@ -476,6 +483,7 @@ atom register
atom registered_name
atom reload
atom rem
+atom report_errors
atom reset
atom restart
atom return_from
@@ -558,6 +566,7 @@ atom true
atom tuple
atom type
atom ucompile
+atom ucp
atom undef
atom ungreedy
atom unicode
diff --git a/erts/emulator/beam/beam_emu.c b/erts/emulator/beam/beam_emu.c
index da36c4437e..78ab6fa30f 100644
--- a/erts/emulator/beam/beam_emu.c
+++ b/erts/emulator/beam/beam_emu.c
@@ -5654,7 +5654,6 @@ build_stacktrace(Process* c_p, Eterm exc) {
return res;
}
-
static BeamInstr*
call_error_handler(Process* p, BeamInstr* fi, Eterm* reg, Eterm func)
{
@@ -5702,7 +5701,6 @@ call_error_handler(Process* p, BeamInstr* fi, Eterm* reg, Eterm func)
return ep->addressv[erts_active_code_ix()];
}
-
static Export*
apply_setup_error_handler(Process* p, Eterm module, Eterm function, Uint arity, Eterm* reg)
{
@@ -6208,7 +6206,6 @@ new_fun(Process* p, Eterm* reg, ErlFunEntry* fe, int num_free)
return make_fun(funp);
}
-
int catchlevel(Process *p)
{
diff --git a/erts/emulator/beam/beam_load.c b/erts/emulator/beam/beam_load.c
index 4193eb4f3f..938fd8f2c9 100644
--- a/erts/emulator/beam/beam_load.c
+++ b/erts/emulator/beam/beam_load.c
@@ -535,7 +535,6 @@ static int must_swap_floats;
Uint erts_total_code_size;
/**********************************************************************/
-
void init_load(void)
{
FloatDef f;
@@ -1209,7 +1208,6 @@ verify_chunks(LoaderState* stp)
return 0;
}
-
static int
load_atom_table(LoaderState* stp)
{
@@ -1255,7 +1253,6 @@ load_atom_table(LoaderState* stp)
return 0;
}
-
static int
load_import_table(LoaderState* stp)
{
@@ -1308,7 +1305,6 @@ load_import_table(LoaderState* stp)
return 0;
}
-
static int
read_export_table(LoaderState* stp)
{
@@ -1641,7 +1637,6 @@ read_line_table(LoaderState* stp)
return 0;
}
-
static int
read_code_header(LoaderState* stp)
{
@@ -1711,7 +1706,6 @@ read_code_header(LoaderState* stp)
return 0;
}
-
#define VerifyTag(Stp, Actual, Expected) \
if (Actual != Expected) { \
LoadError2(Stp, "bad tag %d; expected %d", Actual, Expected); \
@@ -1730,7 +1724,6 @@ read_code_header(LoaderState* stp)
#define TermWords(t) (((t) / (sizeof(BeamInstr)/sizeof(Eterm))) + !!((t) % (sizeof(BeamInstr)/sizeof(Eterm))))
-
static int
load_code(LoaderState* stp)
{
@@ -2512,7 +2505,6 @@ load_code(LoaderState* stp)
return retval;
}
-
#define succ(St, X, Y) ((X).type == (Y).type && (X).val + 1 == (Y).val)
#define succ2(St, X, Y) ((X).type == (Y).type && (X).val + 2 == (Y).val)
#define succ3(St, X, Y) ((X).type == (Y).type && (X).val + 3 == (Y).val)
@@ -3958,7 +3950,6 @@ tuple_append_put(LoaderState* stp, GenOpArg Arity, GenOpArg Dst,
}
-
/*
* Freeze the code in memory, move the string table into place,
* resolve all labels.
@@ -4276,7 +4267,6 @@ freeze_code(LoaderState* stp)
return 0;
}
-
static void
final_touch(LoaderState* stp)
{
@@ -4378,7 +4368,6 @@ final_touch(LoaderState* stp)
}
}
-
static int
transform_engine(LoaderState* st)
{
@@ -4716,7 +4705,6 @@ transform_engine(LoaderState* st)
return rval;
}
-
static void
short_file(int line, LoaderState* stp, unsigned needed)
{
@@ -4724,7 +4712,6 @@ short_file(int line, LoaderState* stp, unsigned needed)
stp->file_name, needed);
}
-
static void
load_printf(int line, LoaderState* context, char *fmt,...)
{
@@ -5190,7 +5177,6 @@ native_addresses(Process* p, Eterm mod)
return result;
}
-
/*
* Builds a list of all exported functions in the given module:
* [{Name, Arity},...]
@@ -5240,7 +5226,6 @@ exported_from_module(Process* p, /* Process whose heap to use. */
return result;
}
-
/*
* Returns a list of all attributes for the module.
*
@@ -5281,7 +5266,6 @@ attributes_for_module(Process* p, /* Process whose heap to use. */
return result;
}
-
/*
* Returns a list containing compilation information.
*
diff --git a/erts/emulator/beam/bif.c b/erts/emulator/beam/bif.c
index 58bd6aac0b..96666d98ed 100644
--- a/erts/emulator/beam/bif.c
+++ b/erts/emulator/beam/bif.c
@@ -160,7 +160,10 @@ BIF_RETTYPE link_1(BIF_ALIST_1)
if (is_internal_port(BIF_ARG_1)) {
int send_link_signal = 0;
- Port *prt = erts_port_lookup(BIF_ARG_1, ERTS_PORT_SFLGS_INVALID_LOOKUP);
+ Port *prt = erts_port_lookup(BIF_ARG_1,
+ (erts_port_synchronous_ops
+ ? ERTS_PORT_SFLGS_INVALID_DRIVER_LOOKUP
+ : ERTS_PORT_SFLGS_INVALID_LOOKUP));
if (!prt) {
goto res_no_proc;
}
@@ -1363,11 +1366,22 @@ BIF_RETTYPE exit_2(BIF_ALIST_2)
*/
if (is_internal_port(BIF_ARG_1)) {
- Port *prt = erts_port_lookup(BIF_ARG_1, ERTS_PORT_SFLGS_INVALID_LOOKUP);
+ Eterm ref, *refp;
+ Uint32 invalid_flags;
+ Port *prt;
+
+ if (erts_port_synchronous_ops) {
+ refp = &ref;
+ invalid_flags = ERTS_PORT_SFLGS_INVALID_DRIVER_LOOKUP;
+ }
+ else {
+ refp = NULL;
+ invalid_flags = ERTS_PORT_SFLGS_INVALID_LOOKUP;
+ }
+
+ prt = erts_port_lookup(BIF_ARG_1, invalid_flags);
if (prt) {
- Eterm ref;
- Eterm *refp = erts_port_synchronous_ops ? &ref : NULL;
ErtsPortOpResult res;
#ifdef DEBUG
@@ -1875,7 +1889,10 @@ do_send(Process *p, Eterm to, Eterm msg, int suspend, Eterm *refp) {
if (rp)
goto send_message;
- pt = erts_port_lookup(id, ERTS_PORT_SFLGS_INVALID_LOOKUP);
+ pt = erts_port_lookup(id,
+ (erts_port_synchronous_ops
+ ? ERTS_PORT_SFLGS_INVALID_DRIVER_LOOKUP
+ : ERTS_PORT_SFLGS_INVALID_LOOKUP));
if (pt) {
portid = id;
goto port_common;
@@ -1905,7 +1922,10 @@ do_send(Process *p, Eterm to, Eterm msg, int suspend, Eterm *refp) {
int ret_val;
portid = to;
- pt = erts_port_lookup(portid, ERTS_PORT_SFLGS_INVALID_LOOKUP);
+ pt = erts_port_lookup(portid,
+ (erts_port_synchronous_ops
+ ? ERTS_PORT_SFLGS_INVALID_DRIVER_LOOKUP
+ : ERTS_PORT_SFLGS_INVALID_LOOKUP));
port_common:
ret_val = 0;
@@ -1994,7 +2014,10 @@ do_send(Process *p, Eterm to, Eterm msg, int suspend, Eterm *refp) {
rp = erts_proc_lookup_raw(id);
if (rp)
goto send_message;
- pt = erts_port_lookup(id, ERTS_PORT_SFLGS_INVALID_LOOKUP);
+ pt = erts_port_lookup(id,
+ (erts_port_synchronous_ops
+ ? ERTS_PORT_SFLGS_INVALID_DRIVER_LOOKUP
+ : ERTS_PORT_SFLGS_INVALID_LOOKUP));
if (pt) {
portid = id;
goto port_common;
diff --git a/erts/emulator/beam/bif.tab b/erts/emulator/beam/bif.tab
index 3b7bb56885..dd50df636c 100644
--- a/erts/emulator/beam/bif.tab
+++ b/erts/emulator/beam/bif.tab
@@ -574,6 +574,13 @@ bif erlang:float_to_binary/2
bif erlang:binary_to_float/1
bif io:printable_range/0
+bif os:unsetenv/1
+
+#
+# New in R17A
+#
+
+bif re:inspect/2
#
# Obsolete
diff --git a/erts/emulator/beam/big.c b/erts/emulator/beam/big.c
index 6b43c53985..2b27b111d8 100644
--- a/erts/emulator/beam/big.c
+++ b/erts/emulator/beam/big.c
@@ -1325,9 +1325,9 @@ static dsize_t I_lshift(ErtsDigit* x, dsize_t xl, Sint y,
return 1;
}
else {
- SWord ay = (y < 0) ? -y : y;
- int bw = ay / D_EXP;
- int sw = ay % D_EXP;
+ Uint ay = (y < 0) ? -y : y;
+ Uint bw = ay / D_EXP;
+ Uint sw = ay % D_EXP;
dsize_t rl;
ErtsDigit a1=0;
ErtsDigit a0=0;
@@ -1368,7 +1368,7 @@ static dsize_t I_lshift(ErtsDigit* x, dsize_t xl, Sint y,
}
if (sign) {
- int zl = bw;
+ Uint zl = bw;
ErtsDigit* z = x;
while(zl--) {
diff --git a/erts/emulator/beam/binary.c b/erts/emulator/beam/binary.c
index 33abac2f3d..c7926f18af 100644
--- a/erts/emulator/beam/binary.c
+++ b/erts/emulator/beam/binary.c
@@ -447,6 +447,7 @@ BIF_RETTYPE bitstring_to_list_1(BIF_ALIST_1)
BIF_RETTYPE erts_list_to_binary_bif(Process *p, Eterm arg)
{
Eterm bin;
+ Eterm h,t;
ErlDrvSizeT size;
byte* bytes;
#ifdef DEBUG
@@ -459,6 +460,16 @@ BIF_RETTYPE erts_list_to_binary_bif(Process *p, Eterm arg)
if (is_not_list(arg)) {
goto error;
}
+ /* check for [binary()] case */
+ h = CAR(list_val(arg));
+ t = CDR(list_val(arg));
+ if (is_binary(h) && is_nil(t) && !(
+ HEADER_SUB_BIN == *(binary_val(h)) && (
+ ((ErlSubBin *)binary_val(h))->bitoffs != 0 ||
+ ((ErlSubBin *)binary_val(h))->bitsize != 0
+ ))) {
+ return h;
+ }
switch (erts_iolist_size(arg, &size)) {
case ERTS_IOLIST_OVERFLOW: BIF_ERROR(p, SYSTEM_LIMIT);
case ERTS_IOLIST_TYPE: goto error;
diff --git a/erts/emulator/beam/break.c b/erts/emulator/beam/break.c
index acbd700cc4..7d4f52ee23 100644
--- a/erts/emulator/beam/break.c
+++ b/erts/emulator/beam/break.c
@@ -76,7 +76,10 @@ process_info(int to, void *to_arg)
for (i = 0; i < max; i++) {
Process *p = erts_pix2proc(i);
if (p && p->i != ENULL) {
- if (!ERTS_PROC_IS_EXITING(p))
+ /* Do not include processes with no heap,
+ * they are most likely just created and has invalid data
+ */
+ if (!ERTS_PROC_IS_EXITING(p) && p->heap != NULL)
print_process_info(to, to_arg, p);
}
}
@@ -756,7 +759,7 @@ erl_crash_dump_v(char *file, int line, char* fmt, va_list args)
return; /* Can't create the crash dump, skip it */
time(&now);
- erts_fdprintf(fd, "=erl_crash_dump:0.2\n%s", ctime(&now));
+ erts_fdprintf(fd, "=erl_crash_dump:0.3\n%s", ctime(&now));
if (file != NULL)
erts_fdprintf(fd, "The error occurred in file %s, line %d\n", file, line);
diff --git a/erts/emulator/beam/dist.c b/erts/emulator/beam/dist.c
index 44f4eb9d43..6ecf3f0722 100644
--- a/erts/emulator/beam/dist.c
+++ b/erts/emulator/beam/dist.c
@@ -353,7 +353,7 @@ static void doit_link_net_exits_sub(ErtsLink *sublnk, void *vlnecp)
static void doit_link_net_exits(ErtsLink *lnk, void *vnecp)
{
LinkNetExitsContext lnec = {(NetExitsContext *) vnecp, lnk};
- ASSERT(lnk->type == LINK_PID)
+ ASSERT(lnk->type == LINK_PID);
erts_sweep_links(ERTS_LINK_ROOT(lnk), &doit_link_net_exits_sub, (void *) &lnec);
#ifdef DEBUG
ERTS_LINK_ROOT(lnk) = NULL;
@@ -369,7 +369,7 @@ static void doit_node_link_net_exits(ErtsLink *lnk, void *vnecp)
Process *rp;
ErtsLink *rlnk;
Uint i,n;
- ASSERT(lnk->type == LINK_NODE)
+ ASSERT(lnk->type == LINK_NODE);
if (is_internal_pid(lnk->pid)) {
ErtsProcLocks rp_locks = ERTS_PROC_LOCK_LINK;
rp = erts_pid2proc(NULL, 0, lnk->pid, rp_locks);
@@ -1509,12 +1509,12 @@ int erts_net_message(Port *prt,
break;
}
rp = erts_pid2proc(NULL, 0, mon->pid, rp_locks);
+
+ erts_destroy_monitor(mon);
if (rp == NULL) {
break;
}
- erts_destroy_monitor(mon);
-
mon = erts_remove_monitor(&ERTS_P_MONITORS(rp), ref);
if (mon == NULL) {
diff --git a/erts/emulator/beam/erl_alloc.c b/erts/emulator/beam/erl_alloc.c
index 5eacff8829..b5ba9bb94a 100644
--- a/erts/emulator/beam/erl_alloc.c
+++ b/erts/emulator/beam/erl_alloc.c
@@ -100,6 +100,8 @@ static Uint install_debug_functions(void);
#endif
#endif
+static int lock_all_physical_memory = 0;
+
ErtsAllocatorFunctions_t erts_allctrs[ERTS_ALC_A_MAX+1];
ErtsAllocatorInfo_t erts_allctrs_info[ERTS_ALC_A_MAX+1];
ErtsAllocatorThrSpec_t erts_allctr_thr_spec[ERTS_ALC_A_MAX+1];
@@ -267,7 +269,6 @@ set_default_sl_alloc_opts(struct au_init *ip)
ip->atype = GOODFIT;
#endif
ip->init.util.name_prefix = "sl_";
- ip->init.util.mmmbc = 5;
ip->init.util.alloc_no = ERTS_ALC_A_SHORT_LIVED;
#ifndef SMALL_MEMORY
ip->init.util.mmbcs = 128*1024; /* Main carrier size */
@@ -295,7 +296,6 @@ set_default_std_alloc_opts(struct au_init *ip)
ip->atype = BESTFIT;
#endif
ip->init.util.name_prefix = "std_";
- ip->init.util.mmmbc = 5;
ip->init.util.alloc_no = ERTS_ALC_A_STANDARD;
#ifndef SMALL_MEMORY
ip->init.util.mmbcs = 128*1024; /* Main carrier size */
@@ -319,7 +319,6 @@ set_default_ll_alloc_opts(struct au_init *ip)
#endif
ip->init.util.ramv = 0;
ip->init.util.mmsbc = 0;
- ip->init.util.mmmbc = 0;
ip->init.util.sbct = ~((UWord) 0);
ip->init.util.name_prefix = "ll_";
ip->init.util.alloc_no = ERTS_ALC_A_LONG_LIVED;
@@ -370,7 +369,6 @@ set_default_eheap_alloc_opts(struct au_init *ip)
ip->thr_spec = 1;
ip->atype = GOODFIT;
#endif
- ip->init.util.mmmbc = 100;
ip->init.util.name_prefix = "eheap_";
ip->init.util.alloc_no = ERTS_ALC_A_EHEAP;
#ifndef SMALL_MEMORY
@@ -397,7 +395,6 @@ set_default_binary_alloc_opts(struct au_init *ip)
ip->thr_spec = 1;
ip->atype = BESTFIT;
#endif
- ip->init.util.mmmbc = 50;
ip->init.util.name_prefix = "binary_";
ip->init.util.alloc_no = ERTS_ALC_A_BINARY;
#ifndef SMALL_MEMORY
@@ -419,7 +416,6 @@ set_default_ets_alloc_opts(struct au_init *ip)
ip->thr_spec = 1;
ip->atype = BESTFIT;
#endif
- ip->init.util.mmmbc = 100;
ip->init.util.name_prefix = "ets_";
ip->init.util.alloc_no = ERTS_ALC_A_ETS;
#ifndef SMALL_MEMORY
@@ -495,13 +491,6 @@ adjust_tpref(struct au_init *ip, int no_sched)
/* ... shrink smallest multi-block carrier size */
if (ip->default_.smbcs)
ip->init.util.smbcs /= ERTS_MIN(4, no_sched);
- /* ... and more than three allocators shrink
- max mseg multi-block carriers */
- if (ip->default_.mmmbc && no_sched > 2) {
- ip->init.util.mmmbc /= ERTS_MIN(4, no_sched - 1);
- if (ip->init.util.mmmbc < 3)
- ip->init.util.mmmbc = 3;
- }
}
}
@@ -631,6 +620,8 @@ erts_alloc_init(int *argc, char **argv, ErtsAllocInitOpts *eaiop)
hdbg_init();
#endif
+ lock_all_physical_memory = 0;
+
ncpu = eaiop->ncpu;
if (ncpu < 1)
ncpu = 1;
@@ -654,6 +645,20 @@ erts_alloc_init(int *argc, char **argv, ErtsAllocInitOpts *eaiop)
if (argc && argv)
handle_args(argc, argv, &init);
+ if (lock_all_physical_memory) {
+#ifdef HAVE_MLOCKALL
+ errno = 0;
+ if (mlockall(MCL_CURRENT|MCL_FUTURE) != 0) {
+ int err = errno;
+ char *errstr = err ? strerror(err) : "unknown";
+ erl_exit(-1, "Failed to lock physical memory: %s (%d)\n",
+ errstr, err);
+ }
+#else
+ erl_exit(-1, "Failed to lock physical memory: Not supported\n");
+#endif
+ }
+
#ifndef ERTS_SMP
init.sl_alloc.thr_spec = 0;
init.std_alloc.thr_spec = 0;
@@ -731,6 +736,7 @@ erts_alloc_init(int *argc, char **argv, ErtsAllocInitOpts *eaiop)
init.mseg.nos = erts_no_schedulers;
erts_mseg_init(&init.mseg);
#endif
+
erts_alcu_init(&init.alloc_util);
erts_afalc_init();
erts_bfalc_init();
@@ -1187,6 +1193,25 @@ get_kb_value(char *param_end, char** argv, int* ip)
return ((Uint) tmp)*1024;
}
+static UWord
+get_mb_value(char *param_end, char** argv, int* ip)
+{
+ SWord tmp;
+ UWord max = ((~((UWord) 0))/(1024*1024)) + 1;
+ char *rest;
+ char *param = argv[*ip]+1;
+ char *value = get_value(param_end, argv, ip);
+ errno = 0;
+ tmp = (SWord) ErtsStrToSint(value, &rest, 10);
+ if (errno != 0 || rest == value || tmp < 0 || max < ((UWord) tmp))
+ bad_value(param, param_end, value);
+ if (max == (UWord) tmp)
+ return ~((UWord) 0);
+ else
+ return ((UWord) tmp)*1024*1024;
+}
+
+
#if 0
static Uint
get_byte_value(char *param_end, char** argv, int* ip)
@@ -1461,6 +1486,30 @@ handle_args(int *argc, char **argv, erts_alc_hndl_args_init_t *init)
#endif
get_amount_value(argv[i]+6, argv, &i);
}
+ else if (has_prefix("scs", argv[i]+3)) {
+#if HAVE_ERTS_MSEG
+ init->mseg.mmap.scs =
+#endif
+ get_mb_value(argv[i]+6, argv, &i);
+ }
+ else if (has_prefix("sco", argv[i]+3)) {
+#if HAVE_ERTS_MSEG
+ init->mseg.mmap.sco =
+#endif
+ get_bool_value(argv[i]+6, argv, &i);
+ }
+ else if (has_prefix("scrpm", argv[i]+3)) {
+#if HAVE_ERTS_MSEG
+ init->mseg.mmap.scrpm =
+#endif
+ get_bool_value(argv[i]+8, argv, &i);
+ }
+ else if (has_prefix("scrfsd", argv[i]+3)) {
+#if HAVE_ERTS_MSEG
+ init->mseg.mmap.scrfsd =
+#endif
+ get_amount_value(argv[i]+9, argv, &i);
+ }
else {
bad_param(param, param+2);
}
@@ -1560,7 +1609,6 @@ handle_args(int *argc, char **argv, erts_alc_hndl_args_init_t *init)
aui[a]->thr_spec = 0;
check_disable_carrier_migration(aui[a]);
aui[a]->init.util.ramv = 0;
- aui[a]->init.util.mmmbc = 10;
aui[a]->init.util.lmbcs = 5*1024*1024;
}
}
@@ -1600,6 +1648,19 @@ handle_args(int *argc, char **argv, erts_alc_hndl_args_init_t *init)
bad_param(param, param+2);
}
break;
+ case 'l':
+ if (has_prefix("pm", param+2)) {
+ arg = get_value(argv[i]+5, argv, &i);
+ if (strcmp("all", arg) == 0)
+ lock_all_physical_memory = 1;
+ else if (strcmp("no", arg) == 0)
+ lock_all_physical_memory = 0;
+ else
+ bad_value(param, param+4, arg);
+ break;
+ }
+ bad_param(param, param+2);
+ break;
case 'u':
if (has_prefix("ycs", argv[i]+3)) {
init->alloc_util.ycs
@@ -1609,6 +1670,10 @@ handle_args(int *argc, char **argv, erts_alc_hndl_args_init_t *init)
init->alloc_util.mmc
= get_amount_value(argv[i]+6, argv, &i);
}
+ else if (has_prefix("sac", argv[i]+3)) {
+ init->alloc_util.sac
+ = get_bool_value(argv[i]+6, argv, &i);
+ }
else {
int a;
int start = i;
@@ -2682,6 +2747,7 @@ erts_allocator_info(int to, void *arg)
#if HAVE_ERTS_MSEG
{
+ struct erts_mmap_info_struct emis;
#ifdef ERTS_SMP
int max = (int) erts_no_schedulers;
#else
@@ -2692,6 +2758,8 @@ erts_allocator_info(int to, void *arg)
erts_print(to, arg, "=allocator:mseg_alloc[%d]\n", i);
erts_mseg_info(i, &to, arg, 0, NULL, NULL);
}
+ erts_print(to, arg, "=allocator:mseg_alloc.erts_mmap\n");
+ erts_mmap_info(&to, arg, NULL, NULL, &emis);
}
#endif
@@ -2716,8 +2784,8 @@ erts_allocator_options(void *proc)
#endif
Uint sz, *szp, *hp, **hpp;
Eterm res, features, settings;
- Eterm atoms[ERTS_ALC_A_MAX-ERTS_ALC_A_MIN+5];
- Uint terms[ERTS_ALC_A_MAX-ERTS_ALC_A_MIN+5];
+ Eterm atoms[ERTS_ALC_A_MAX-ERTS_ALC_A_MIN+7];
+ Uint terms[ERTS_ALC_A_MAX-ERTS_ALC_A_MIN+7];
int a, length;
SysAllocStat sas;
Uint *endp = NULL;
@@ -2815,6 +2883,11 @@ erts_allocator_options(void *proc)
terms[length++] = erts_bld_2tup_list(hpp, szp, 3, o, v);
}
+ atoms[length] = am_atom_put("lock_physical_memory", 20);
+ terms[length++] = (lock_all_physical_memory
+ ? am_atom_put("all", 3)
+ : am_atom_put("no", 2));
+
settings = erts_bld_2tup_list(hpp, szp, length, atoms, terms);
length = 0;
@@ -2830,6 +2903,9 @@ erts_allocator_options(void *proc)
if (use_mseg)
terms[length++] = am_atom_put("mseg_alloc", 10);
#endif
+#if ERTS_HAVE_ERTS_SYS_ALIGNED_ALLOC
+ terms[length++] = am_atom_put("sys_aligned_alloc", 17);
+#endif
features = length ? erts_bld_list(hpp, szp, length, terms) : NIL;
@@ -2915,6 +2991,7 @@ reply_alloc_info(void *vair)
Uint sz, *szp;
ErlOffHeap *ohp = NULL;
ErlHeapFragment *bp = NULL;
+ struct erts_mmap_info_struct emis;
int i;
Eterm (*info_func)(Allctr_t *,
int,
@@ -3027,15 +3104,23 @@ reply_alloc_info(void *vair)
? NIL
: erts_mseg_info(0, NULL, NULL, hpp != NULL,
hpp, szp));
- ainfo = erts_bld_tuple(hpp, szp, 3,
- alloc_atom,
- make_small(0),
- ainfo);
+ ainfo = erts_bld_tuple3(hpp, szp,
+ alloc_atom,
+ make_small(0),
+ ainfo);
+
+ ai_list = erts_bld_cons(hpp, szp,
+ ainfo, ai_list);
+ ainfo = (air->only_sz ? NIL : erts_mmap_info(NULL, NULL, hpp, szp, &emis));
+ ainfo = erts_bld_tuple3(hpp, szp,
+ alloc_atom,
+ erts_bld_atom(hpp,szp,"erts_mmap"),
+ ainfo);
#else
- ainfo = erts_bld_tuple(hpp, szp, 2, alloc_atom,
- am_false);
+ ainfo = erts_bld_tuple2(hpp, szp, alloc_atom,
+ am_false);
#endif
- break;
+ break;
default:
alloc_atom = erts_bld_atom(hpp, szp,
(char *) ERTS_ALC_A2AD(ai));
diff --git a/erts/emulator/beam/erl_alloc.h b/erts/emulator/beam/erl_alloc.h
index b5975c6c32..f83f6b39cf 100644
--- a/erts/emulator/beam/erl_alloc.h
+++ b/erts/emulator/beam/erl_alloc.h
@@ -54,6 +54,16 @@ void erts_sys_alloc_init(void);
void *erts_sys_alloc(ErtsAlcType_t, void *, Uint);
void *erts_sys_realloc(ErtsAlcType_t, void *, void *, Uint);
void erts_sys_free(ErtsAlcType_t, void *, void *);
+#if ERTS_HAVE_ERTS_SYS_ALIGNED_ALLOC
+/*
+ * Note 'alignment' must remain the same in calls to
+ * 'erts_sys_aligned_realloc()' and 'erts_sys_aligned_free()'
+ * as in the initial call to 'erts_sys_aligned_alloc()'.
+ */
+void *erts_sys_aligned_alloc(UWord alignment, UWord size);
+void *erts_sys_aligned_realloc(UWord alignment, void *ptr, UWord size, UWord old_size);
+void erts_sys_aligned_free(UWord alignment, void *ptr);
+#endif
Eterm erts_memory(int *, void *, void *, Eterm);
Eterm erts_allocated_areas(int *, void *, void *);
diff --git a/erts/emulator/beam/erl_alloc_util.c b/erts/emulator/beam/erl_alloc_util.c
index e6d9f83aed..c6cea0185f 100644
--- a/erts/emulator/beam/erl_alloc_util.c
+++ b/erts/emulator/beam/erl_alloc_util.c
@@ -81,16 +81,12 @@
static int atoms_initialized = 0;
static int initialized = 0;
-
#define INV_SYS_ALLOC_CARRIER_MASK ((UWord) (sys_alloc_carrier_size - 1))
#define SYS_ALLOC_CARRIER_MASK (~INV_SYS_ALLOC_CARRIER_MASK)
#define SYS_ALLOC_CARRIER_FLOOR(X) ((X) & SYS_ALLOC_CARRIER_MASK)
#define SYS_ALLOC_CARRIER_CEILING(X) \
SYS_ALLOC_CARRIER_FLOOR((X) + INV_SYS_ALLOC_CARRIER_MASK)
-#undef ASSERT
-#define ASSERT ASSERT_EXPR
-
#if 0
/* Can be useful for debugging */
#define MBC_REALLOC_ALWAYS_MOVES
@@ -102,6 +98,7 @@ static Uint sys_alloc_carrier_size;
#if HAVE_ERTS_MSEG
static Uint max_mseg_carriers;
#endif
+static int allow_sys_alloc_carriers;
#define ONE_GIGA (1000000000)
@@ -194,9 +191,9 @@ MBC after deallocating first block:
#if MBC_ABLK_OFFSET_BITS
-# define MBC_SZ_MAX_LIMIT ((((UWord)1 << MBC_ABLK_OFFSET_BITS) - 1) << MSEG_ALIGN_BITS)
+# define MBC_SZ_MAX_LIMIT ((((UWord)1 << MBC_ABLK_OFFSET_BITS) - 1) << ERTS_SUPER_ALIGN_BITS)
-# define BLK_CARRIER_OFFSET(B, C) (((char*)(B) - (char*)(C)) >> MSEG_UNIT_SHIFT)
+# define BLK_CARRIER_OFFSET(B, C) (((char*)(B) - (char*)(C)) >> ERTS_SACRR_UNIT_SHIFT)
# define SET_MBC_ABLK_HDR(B, Sz, F, C) \
(ASSERT(((Sz) & ~MBC_ABLK_SZ_MASK) == 0), \
@@ -210,7 +207,7 @@ MBC after deallocating first block:
(B)->u.carrier = (C))
# define IS_MBC_FIRST_ABLK(AP,B) \
- ((((UWord)(B) & ~MSEG_UNIT_MASK) == MBC_HEADER_SIZE(AP)) \
+ ((((UWord)(B) & ~ERTS_SACRR_UNIT_MASK) == MBC_HEADER_SIZE(AP)) \
&& ((B)->bhdr & MBC_ABLK_OFFSET_MASK) == 0)
# define IS_MBC_FIRST_FBLK(AP,B) \
@@ -376,6 +373,8 @@ do { \
#define ERTS_CRR_ALCTR_FLG_IN_POOL (((erts_aint_t) 1) << 0)
#define ERTS_CRR_ALCTR_FLG_BUSY (((erts_aint_t) 1) << 1)
+#define ERTS_CRR_ALCTR_FLG_MASK (ERTS_CRR_ALCTR_FLG_IN_POOL | \
+ ERTS_CRR_ALCTR_FLG_BUSY)
#ifdef ERTS_SMP
#define SBC_HEADER_SIZE \
@@ -760,8 +759,9 @@ static ERTS_INLINE void *
alcu_mseg_alloc(Allctr_t *allctr, Uint *size_p, Uint flags)
{
void *res;
-
- res = erts_mseg_alloc_opt(allctr->alloc_no, size_p, flags, &allctr->mseg_opt);
+ UWord size = (UWord) *size_p;
+ res = erts_mseg_alloc_opt(allctr->alloc_no, &size, flags, &allctr->mseg_opt);
+ *size_p = (Uint) size;
INC_CC(allctr->calls.mseg_alloc);
return res;
}
@@ -770,9 +770,10 @@ static ERTS_INLINE void *
alcu_mseg_realloc(Allctr_t *allctr, void *seg, Uint old_size, Uint *new_size_p)
{
void *res;
-
- res = erts_mseg_realloc_opt(allctr->alloc_no, seg, old_size, new_size_p,
+ UWord new_size = (UWord) *new_size_p;
+ res = erts_mseg_realloc_opt(allctr->alloc_no, seg, (UWord) old_size, &new_size,
ERTS_MSEG_FLG_NONE, &allctr->mseg_opt);
+ *new_size_p = (Uint) new_size;
INC_CC(allctr->calls.mseg_realloc);
return res;
}
@@ -780,18 +781,22 @@ alcu_mseg_realloc(Allctr_t *allctr, void *seg, Uint old_size, Uint *new_size_p)
static ERTS_INLINE void
alcu_mseg_dealloc(Allctr_t *allctr, void *seg, Uint size, Uint flags)
{
- erts_mseg_dealloc_opt(allctr->alloc_no, seg, size, flags, &allctr->mseg_opt);
+ erts_mseg_dealloc_opt(allctr->alloc_no, seg, (UWord) size, flags, &allctr->mseg_opt);
INC_CC(allctr->calls.mseg_dealloc);
}
#endif
static ERTS_INLINE void *
-alcu_sys_alloc(Allctr_t *allctr, Uint size)
+alcu_sys_alloc(Allctr_t *allctr, Uint size, int superalign)
{
void *res;
-
- res = erts_sys_alloc(0, NULL, size);
+#if ERTS_SA_MB_CARRIERS && ERTS_HAVE_ERTS_SYS_ALIGNED_ALLOC
+ if (superalign)
+ res = erts_sys_aligned_alloc(ERTS_SACRR_UNIT_SZ, size);
+ else
+#endif
+ res = erts_sys_alloc(0, NULL, size);
INC_CC(allctr->calls.sys_alloc);
if (erts_mtrace_enabled)
erts_mtrace_crr_alloc(res, allctr->alloc_no, ERTS_ALC_A_SYSTEM, size);
@@ -799,11 +804,16 @@ alcu_sys_alloc(Allctr_t *allctr, Uint size)
}
static ERTS_INLINE void *
-alcu_sys_realloc(Allctr_t *allctr, void *ptr, Uint size)
+alcu_sys_realloc(Allctr_t *allctr, void *ptr, Uint size, Uint old_size, int superalign)
{
void *res;
- res = erts_sys_realloc(0, NULL, ptr, size);
+#if ERTS_SA_MB_CARRIERS && ERTS_HAVE_ERTS_SYS_ALIGNED_ALLOC
+ if (superalign)
+ res = erts_sys_aligned_realloc(ERTS_SACRR_UNIT_SZ, ptr, size, old_size);
+ else
+#endif
+ res = erts_sys_realloc(0, NULL, ptr, size);
INC_CC(allctr->calls.sys_realloc);
if (erts_mtrace_enabled)
erts_mtrace_crr_realloc(res,
@@ -815,9 +825,14 @@ alcu_sys_realloc(Allctr_t *allctr, void *ptr, Uint size)
}
static ERTS_INLINE void
-alcu_sys_free(Allctr_t *allctr, void *ptr)
+alcu_sys_free(Allctr_t *allctr, void *ptr, int superalign)
{
- erts_sys_free(0, NULL, ptr);
+#if ERTS_SA_MB_CARRIERS && ERTS_HAVE_ERTS_SYS_ALIGNED_ALLOC
+ if (superalign)
+ erts_sys_aligned_free(ERTS_SACRR_UNIT_SZ, ptr);
+ else
+#endif
+ erts_sys_free(0, NULL, ptr);
INC_CC(allctr->calls.sys_free);
if (erts_mtrace_enabled)
erts_mtrace_crr_free(allctr->alloc_no, ERTS_ALC_A_SYSTEM, ptr);
@@ -1334,7 +1349,7 @@ erts_alcu_fix_alloc_shrink(Allctr_t *allctr, erts_aint32_t flgs)
return fix_nocpool_alloc_shrink(allctr, flgs);
}
-static void dealloc_carrier(Allctr_t *allctr, Carrier_t *crr, Uint mseg_flags);
+static void dealloc_carrier(Allctr_t *allctr, Carrier_t *crr, int superaligned);
#ifdef ERTS_SMP
@@ -1392,14 +1407,14 @@ get_used_allctr(Allctr_t *pref_allctr, int pref_lock, void *p, UWord *sizep,
if (ERTS_ALC_TS_PREF_LOCK_IF_USED == pref_lock
&& pref_allctr->thread_safe) {
- used_allctr = (Allctr_t *) (iallctr & ~FLG_MASK);
+ used_allctr = (Allctr_t *) (iallctr & ~ERTS_CRR_ALCTR_FLG_MASK);
if (pref_allctr == used_allctr) {
erts_mtx_lock(&pref_allctr->mutex);
locked_pref_allctr = 1;
}
}
- while ((iallctr & ((~FLG_MASK)|ERTS_CRR_ALCTR_FLG_IN_POOL))
+ while ((iallctr & ((~ERTS_CRR_ALCTR_FLG_MASK)|ERTS_CRR_ALCTR_FLG_IN_POOL))
== (((erts_aint_t) pref_allctr)|ERTS_CRR_ALCTR_FLG_IN_POOL)) {
erts_aint_t act;
@@ -1414,7 +1429,7 @@ get_used_allctr(Allctr_t *pref_allctr, int pref_lock, void *p, UWord *sizep,
iallctr = act;
}
- used_allctr = (Allctr_t *) (iallctr & ~FLG_MASK);
+ used_allctr = (Allctr_t *) (iallctr & ~ERTS_CRR_ALCTR_FLG_MASK);
if (ERTS_ALC_TS_PREF_LOCK_IF_USED == pref_lock) {
if (locked_pref_allctr && used_allctr != pref_allctr) {
@@ -1424,16 +1439,16 @@ get_used_allctr(Allctr_t *pref_allctr, int pref_lock, void *p, UWord *sizep,
}
ERTS_ALC_CPOOL_ASSERT(
- (((iallctr & ~FLG_MASK) == (erts_aint_t) pref_allctr)
- ? (((iallctr & FLG_MASK) == ERTS_CRR_ALCTR_FLG_IN_POOL)
- || ((iallctr & FLG_MASK) == 0))
+ (((iallctr & ~ERTS_CRR_ALCTR_FLG_MASK) == (erts_aint_t) pref_allctr)
+ ? (((iallctr & ERTS_CRR_ALCTR_FLG_MASK) == ERTS_CRR_ALCTR_FLG_IN_POOL)
+ || ((iallctr & ERTS_CRR_ALCTR_FLG_MASK) == 0))
: 1));
return used_allctr;
}
}
- used_allctr = (Allctr_t *) (iallctr & ~FLG_MASK);
+ used_allctr = (Allctr_t *) (iallctr & ~ERTS_CRR_ALCTR_FLG_MASK);
if (ERTS_ALC_TS_PREF_LOCK_IF_USED == pref_lock
&& used_allctr == pref_allctr
@@ -1764,7 +1779,7 @@ handle_delayed_dealloc(Allctr_t *allctr,
ERTS_ALC_CPOOL_ASSERT(allctr == crr->cpool.orig_allctr);
ERTS_ALC_CPOOL_ASSERT(((erts_aint_t) allctr)
!= (erts_smp_atomic_read_nob(&crr->allctr)
- & ~FLG_MASK));
+ & ~ERTS_CRR_ALCTR_FLG_MASK));
erts_smp_atomic_set_nob(&crr->allctr, ((erts_aint_t) allctr));
@@ -1942,7 +1957,7 @@ mbc_alloc_block(Allctr_t *allctr, Uint size, Uint *blk_szp)
if (!blk) {
blk = create_carrier(allctr, get_blk_sz, CFLG_MBC);
-#if !HALFWORD_HEAP && !HAVE_SUPER_ALIGNED_MB_CARRIERS
+#if !HALFWORD_HEAP && !ERTS_SUPER_ALIGNED_MSEG_ONLY
if (!blk) {
/* Emergency! We couldn't create the carrier as we wanted.
Try to place it in a sys_alloced sbc. */
@@ -2907,7 +2922,7 @@ cpool_fetch(Allctr_t *allctr, UWord size)
#ifdef ERTS_ALC_CPOOL_DEBUG
ERTS_ALC_CPOOL_ASSERT(erts_smp_atomic_xchg_nob(&crr->allctr,
((erts_aint_t) allctr))
- == (((erts_aint_t) allctr) & ~FLG_MASK));
+ == (((erts_aint_t) allctr) & ~ERTS_CRR_ALCTR_FLG_MASK));
#else
erts_smp_atomic_set_nob(&crr->allctr, ((erts_aint_t) allctr));
#endif
@@ -2949,7 +2964,7 @@ cpool_fetch(Allctr_t *allctr, UWord size)
(erts_aint_t) allctr,
exp);
if (act == exp) {
- cpool_delete(allctr, ((Allctr_t *) (act & ~FLG_MASK)), crr);
+ cpool_delete(allctr, ((Allctr_t *) (act & ~ERTS_CRR_ALCTR_FLG_MASK)), crr);
return crr;
}
}
@@ -2978,7 +2993,7 @@ check_pending_dealloc_carrier(Allctr_t *allctr,
dcrr = crr;
crr = crr->next;
- dealloc_carrier(allctr, dcrr, ERTS_MSEG_FLG_2POW);
+ dealloc_carrier(allctr, dcrr, 1);
i++;
} while (crr && i < ERTS_ALC_MAX_DEALLOC_CARRIER);
@@ -3013,7 +3028,7 @@ schedule_dealloc_carrier(Allctr_t *allctr, Carrier_t *crr)
erts_aint_t max_size;
if (!ERTS_ALC_IS_CPOOL_ENABLED(allctr)) {
- dealloc_carrier(allctr, crr, ERTS_MSEG_FLG_2POW);
+ dealloc_carrier(allctr, crr, 1);
return;
}
@@ -3044,7 +3059,7 @@ schedule_dealloc_carrier(Allctr_t *allctr, Carrier_t *crr)
ERTS_ALC_CPOOL_ASSERT(crr == FIRST_BLK_TO_MBC(allctr, blk));
ERTS_ALC_CPOOL_ASSERT(((erts_aint_t) allctr)
== (erts_smp_atomic_read_nob(&crr->allctr)
- & ~FLG_MASK));
+ & ~ERTS_CRR_ALCTR_FLG_MASK));
if (ddq_enqueue(&orig_allctr->dd.q, BLK2UMEM(blk), cinit))
erts_alloc_notify_delayed_dealloc(orig_allctr->ix);
@@ -3053,7 +3068,7 @@ schedule_dealloc_carrier(Allctr_t *allctr, Carrier_t *crr)
if (crr->cpool.thr_prgr == ERTS_THR_PRGR_INVALID
|| erts_thr_progress_has_reached(crr->cpool.thr_prgr)) {
- dealloc_carrier(allctr, crr, ERTS_MSEG_FLG_2POW);
+ dealloc_carrier(allctr, crr, 1);
return;
}
@@ -3188,10 +3203,10 @@ cpool_read_stat(Allctr_t *allctr, UWord *nocp, UWord *cszp, UWord *nobp, UWord *
#ifdef DEBUG
-#if HAVE_ERTS_MSEG
-#define ASSERT_MSEG_UNIT_SIZE_MULTIPLE(CSZ) ASSERT((CSZ) % MSEG_UNIT_SZ == 0)
+#if ERTS_SA_MB_CARRIERS
+#define ASSERT_ERTS_SACRR_UNIT_SIZE_MULTIPLE(CSZ) ASSERT((CSZ) % ERTS_SACRR_UNIT_SZ == 0)
#else
-#define ASSERT_MSEG_UNIT_SIZE_MULTIPLE(CSZ)
+#define ASSERT_ERTS_SACRR_UNIT_SIZE_MULTIPLE(CSZ)
#endif
static void CHECK_1BLK_CARRIER(Allctr_t* A, int SBC, int MSEGED, Carrier_t* C,
@@ -3213,10 +3228,12 @@ static void CHECK_1BLK_CARRIER(Allctr_t* A, int SBC, int MSEGED, Carrier_t* C,
ASSERT(IS_MBC_BLK((B)));
ASSERT(IS_MB_CARRIER((C)));
ASSERT(FBLK_TO_MBC(B) == (C));
+ if ((MSEGED)) {
+ ASSERT_ERTS_SACRR_UNIT_SIZE_MULTIPLE((CSZ));
+ }
}
if ((MSEGED)) {
ASSERT(IS_MSEG_CARRIER((C)));
- ASSERT_MSEG_UNIT_SIZE_MULTIPLE((CSZ));
}
else {
ASSERT(IS_SYS_ALLOC_CARRIER((C)));
@@ -3242,13 +3259,15 @@ create_carrier(Allctr_t *allctr, Uint umem_sz, UWord flags)
int is_mseg = 0;
#endif
-#if HALFWORD_HEAP
- flags |= CFLG_FORCE_MSEG;
-#elif HAVE_SUPER_ALIGNED_MB_CARRIERS
- if (flags & CFLG_MBC) {
+ if (HALFWORD_HEAP
+ || (ERTS_SUPER_ALIGNED_MSEG_ONLY && (flags & CFLG_MBC))
+ || !allow_sys_alloc_carriers) {
flags |= CFLG_FORCE_MSEG;
- }
+ flags &= ~CFLG_FORCE_SYS_ALLOC;
+#if !HAVE_ERTS_MSEG
+ return NULL;
#endif
+ }
ASSERT((flags & CFLG_SBC && !(flags & CFLG_MBC))
|| (flags & CFLG_MBC && !(flags & CFLG_SBC)));
@@ -3287,7 +3306,7 @@ create_carrier(Allctr_t *allctr, Uint umem_sz, UWord flags)
if (allctr->sbcs.curr.norm.mseg.no >= allctr->max_mseg_sbcs)
goto try_sys_alloc;
}
-#if !HAVE_SUPER_ALIGNED_MB_CARRIERS
+#if !ERTS_SUPER_ALIGNED_MSEG_ONLY
else {
if (allctr->mbcs.curr.norm.mseg.no >= allctr->max_mseg_mbcs)
goto try_sys_alloc;
@@ -3350,12 +3369,12 @@ create_carrier(Allctr_t *allctr, Uint umem_sz, UWord flags)
? UNIT_CEILING(bcrr_sz)
: SYS_ALLOC_CARRIER_CEILING(bcrr_sz));
- crr = (Carrier_t *) alcu_sys_alloc(allctr, crr_sz);
+ crr = (Carrier_t *) alcu_sys_alloc(allctr, crr_sz, flags & CFLG_MBC);
if (!crr) {
if (crr_sz > UNIT_CEILING(bcrr_sz)) {
crr_sz = UNIT_CEILING(bcrr_sz);
- crr = (Carrier_t *) alcu_sys_alloc(allctr, crr_sz);
+ crr = (Carrier_t *) alcu_sys_alloc(allctr, crr_sz, flags & CFLG_MBC);
}
if (!crr) {
#if HAVE_ERTS_MSEG
@@ -3453,7 +3472,7 @@ resize_carrier(Allctr_t *allctr, Block_t *old_blk, Uint umem_sz, UWord flags)
if (!(flags & CFLG_FORCE_SYS_ALLOC)) {
new_crr_sz = new_blk_sz + SBC_HEADER_SIZE;
- new_crr_sz = MSEG_UNIT_CEILING(new_crr_sz);
+ new_crr_sz = ERTS_SACRR_UNIT_CEILING(new_crr_sz);
new_crr = (Carrier_t *) alcu_mseg_realloc(allctr,
old_crr,
old_crr_sz,
@@ -3503,7 +3522,9 @@ resize_carrier(Allctr_t *allctr, Block_t *old_blk, Uint umem_sz, UWord flags)
new_crr = (Carrier_t *) alcu_sys_realloc(allctr,
(void *) old_crr,
- new_crr_sz);
+ new_crr_sz,
+ old_crr_sz,
+ 0);
if (new_crr) {
sys_realloc_success:
SET_CARRIER_SZ(new_crr, new_crr_sz);
@@ -3522,7 +3543,9 @@ resize_carrier(Allctr_t *allctr, Block_t *old_blk, Uint umem_sz, UWord flags)
new_crr_sz = UNIT_CEILING(new_crr_sz);
new_crr = (Carrier_t *) alcu_sys_realloc(allctr,
(void *) old_crr,
- new_crr_sz);
+ new_crr_sz,
+ old_crr_sz,
+ 0);
if (new_crr)
goto sys_realloc_success;
}
@@ -3541,27 +3564,29 @@ resize_carrier(Allctr_t *allctr, Block_t *old_blk, Uint umem_sz, UWord flags)
(void *) BLK2UMEM(old_blk),
MIN(new_blk_sz, old_blk_sz) - ABLK_HDR_SZ);
unlink_carrier(&allctr->sbc_list, old_crr);
- alcu_sys_free(allctr, old_crr);
+ alcu_sys_free(allctr, old_crr, 0);
}
else {
/* Old carrier unchanged; restore... */
STAT_SYS_ALLOC_SBC_ALLOC(allctr, old_crr_sz, old_blk_sz);
}
- DEBUG_SAVE_ALIGNMENT(new_crr);
return new_blk;
}
#endif
}
static void
-dealloc_carrier(Allctr_t *allctr, Carrier_t *crr, Uint mseg_flags)
+dealloc_carrier(Allctr_t *allctr, Carrier_t *crr, int superaligned)
{
#if HAVE_ERTS_MSEG
if (IS_MSEG_CARRIER(crr))
- alcu_mseg_dealloc(allctr, crr, CARRIER_SZ(crr), mseg_flags);
+ alcu_mseg_dealloc(allctr, crr, CARRIER_SZ(crr),
+ (superaligned
+ ? ERTS_MSEG_FLG_2POW
+ : ERTS_MSEG_FLG_NONE));
else
#endif
- alcu_sys_free(allctr, crr);
+ alcu_sys_free(allctr, crr, superaligned);
}
static void
@@ -3581,7 +3606,6 @@ destroy_carrier(Allctr_t *allctr, Block_t *blk, Carrier_t **busy_pcrr_pp)
#if HAVE_ERTS_MSEG
if (IS_MSEG_CARRIER(crr)) {
- ASSERT(crr_sz % MSEG_UNIT_SZ == 0);
STAT_MSEG_SBC_FREE(allctr, crr_sz, blk_sz);
}
else
@@ -3590,7 +3614,7 @@ destroy_carrier(Allctr_t *allctr, Block_t *blk, Carrier_t **busy_pcrr_pp)
unlink_carrier(&allctr->sbc_list, crr);
- dealloc_carrier(allctr, crr, ERTS_MSEG_FLG_NONE);
+ dealloc_carrier(allctr, crr, 0);
}
else {
ASSERT(IS_MBC_FIRST_FBLK(allctr, blk));
@@ -3624,7 +3648,7 @@ destroy_carrier(Allctr_t *allctr, Block_t *blk, Carrier_t **busy_pcrr_pp)
unlink_carrier(&allctr->mbc_list, crr);
#if HAVE_ERTS_MSEG
if (IS_MSEG_CARRIER(crr)) {
- ASSERT(crr_sz % MSEG_UNIT_SZ == 0);
+ ASSERT(crr_sz % ERTS_SACRR_UNIT_SZ == 0);
STAT_MSEG_MBC_FREE(allctr, crr_sz);
}
else
@@ -3635,10 +3659,9 @@ destroy_carrier(Allctr_t *allctr, Block_t *blk, Carrier_t **busy_pcrr_pp)
#ifdef ERTS_SMP
schedule_dealloc_carrier(allctr, crr);
#else
- dealloc_carrier(allctr, crr, ERTS_MSEG_FLG_2POW);
+ dealloc_carrier(allctr, crr, 1);
#endif
}
-
}
@@ -3678,6 +3701,7 @@ static struct {
Eterm mmc;
#endif
Eterm ycs;
+ Eterm sac;
Eterm fix_types;
@@ -3770,6 +3794,7 @@ init_atoms(Allctr_t *allctr)
AM_INIT(mmc);
#endif
AM_INIT(ycs);
+ AM_INIT(sac);
AM_INIT(fix_types);
@@ -4490,17 +4515,22 @@ erts_alcu_au_info_options(int *print_to_p, void *print_to_arg,
#if HAVE_ERTS_MSEG
"option mmc: %beu\n"
#endif
- "option ycs: %beu\n",
+ "option ycs: %beu\n"
+ "option sac: %s\n",
#if HAVE_ERTS_MSEG
max_mseg_carriers,
#endif
- sys_alloc_carrier_size);
+ sys_alloc_carrier_size,
+ allow_sys_alloc_carriers ? "true" : "false");
}
if (hpp || szp) {
res = NIL;
ensure_atoms_initialized(NULL);
add_2tup(hpp, szp, &res,
+ am.sac,
+ allow_sys_alloc_carriers ? am_true : am_false);
+ add_2tup(hpp, szp, &res,
am.ycs,
bld_uint(hpp, szp, sys_alloc_carrier_size));
#if HAVE_ERTS_MSEG
@@ -5086,7 +5116,7 @@ do_erts_alcu_realloc(ErtsAlcType_t type,
crr_sz = SYS_ALLOC_CARRIER_CEILING(used_sz);
#if HAVE_ERTS_MSEG
else
- crr_sz = MSEG_UNIT_CEILING(used_sz);
+ crr_sz = ERTS_SACRR_UNIT_CEILING(used_sz);
#endif
diff_sz_val = crr_sz - used_sz;
if (diff_sz_val < (~((Uint) 0) / 100))
@@ -5403,6 +5433,11 @@ erts_alcu_start(Allctr_t *allctr, AllctrInit_t *init)
{
/* erts_alcu_start assumes that allctr has been zeroed */
+ if (((UWord)allctr & ERTS_CRR_ALCTR_FLG_MASK) != 0) {
+ erl_exit(ERTS_ABORT_EXIT, "%s:%d:erts_alcu_start: Alignment error\n",
+ __FILE__, __LINE__);
+ }
+
if (!initialized)
goto error;
@@ -5454,7 +5489,7 @@ erts_alcu_start(Allctr_t *allctr, AllctrInit_t *init)
allctr->mbc_move_threshold = init->rmbcmt;
#if HAVE_ERTS_MSEG
allctr->max_mseg_sbcs = init->mmsbc;
-# if HAVE_SUPER_ALIGNED_MB_CARRIERS
+# if ERTS_SUPER_ALIGNED_MSEG_ONLY
allctr->max_mseg_mbcs = ~(Uint)0;
# else
allctr->max_mseg_mbcs = init->mmmbc;
@@ -5493,7 +5528,7 @@ erts_alcu_start(Allctr_t *allctr, AllctrInit_t *init)
erts_atomic_init_nob(&allctr->cpool.stat.carriers_size, 0);
erts_atomic_init_nob(&allctr->cpool.stat.no_carriers, 0);
allctr->cpool.check_limit_count = ERTS_ALC_CPOOL_CHECK_LIMIT_COUNT;
- allctr->cpool.util_limit = init->acul;
+ allctr->cpool.util_limit = init->ts ? 0 : init->acul;
#endif
allctr->sbc_threshold = init->sbct;
@@ -5570,12 +5605,19 @@ erts_alcu_start(Allctr_t *allctr, AllctrInit_t *init)
CFLG_MBC
| CFLG_FORCE_SIZE
| CFLG_NO_CPOOL
-#if !HALFWORD_HEAP && !HAVE_SUPER_ALIGNED_MB_CARRIERS
+#if !HALFWORD_HEAP && !ERTS_SUPER_ALIGNED_MSEG_ONLY
| CFLG_FORCE_SYS_ALLOC
#endif
| CFLG_MAIN_CARRIER);
- if (!blk)
- goto error;
+ if (!blk) {
+#ifdef USE_THREADS
+ if (allctr->thread_safe)
+ erts_mtx_destroy(&allctr->mutex);
+#endif
+ erl_exit(ERTS_ABORT_EXIT,
+ "Failed to create main carrier for %salloc\n",
+ init->name_prefix);
+ }
(*allctr->link_free_block)(allctr, blk);
@@ -5656,12 +5698,13 @@ erts_alcu_init(AlcUInit_t *init)
#endif
ASSERT(SBC_BLK_SZ_MASK == MBC_FBLK_SZ_MASK); /* see BLK_SZ */
#if HAVE_ERTS_MSEG
- ASSERT(erts_mseg_unit_size() == MSEG_UNIT_SZ);
+ ASSERT(erts_mseg_unit_size() == ERTS_SACRR_UNIT_SZ);
max_mseg_carriers = init->mmc;
- sys_alloc_carrier_size = MSEG_UNIT_CEILING(init->ycs);
+ sys_alloc_carrier_size = ERTS_SACRR_UNIT_CEILING(init->ycs);
#else /* #if HAVE_ERTS_MSEG */
sys_alloc_carrier_size = ((init->ycs + 4095) / 4096) * 4096;
#endif
+ allow_sys_alloc_carriers = init->sac;
#ifdef DEBUG
carrier_alignment = sizeof(Unit_t);
@@ -5819,7 +5862,7 @@ check_blk_carrier(Allctr_t *allctr, Block_t *iblk)
ASSERT(CARRIER_SZ(sbc) - SBC_HEADER_SIZE >= SBC_BLK_SZ(iblk));
#if HAVE_ERTS_MSEG
if (IS_MSEG_CARRIER(sbc)) {
- ASSERT(CARRIER_SZ(sbc) % MSEG_UNIT_SZ == 0);
+ ASSERT(CARRIER_SZ(sbc) % ERTS_SACRR_UNIT_SZ == 0);
}
#endif
crr = sbc;
@@ -5904,7 +5947,7 @@ check_blk_carrier(Allctr_t *allctr, Block_t *iblk)
#if HAVE_ERTS_MSEG
if (IS_MSEG_CARRIER(crr)) {
- ASSERT(CARRIER_SZ(crr) % MSEG_UNIT_SZ == 0);
+ ASSERT(CARRIER_SZ(crr) % ERTS_SACRR_UNIT_SZ == 0);
}
#endif
cl = &allctr->mbc_list;
diff --git a/erts/emulator/beam/erl_alloc_util.h b/erts/emulator/beam/erl_alloc_util.h
index 02cbe5c5d0..7be6b1ed9d 100644
--- a/erts/emulator/beam/erl_alloc_util.h
+++ b/erts/emulator/beam/erl_alloc_util.h
@@ -32,6 +32,7 @@ typedef struct Allctr_t_ Allctr_t;
typedef struct {
UWord ycs;
UWord mmc;
+ int sac;
} AlcUInit_t;
typedef struct {
@@ -75,7 +76,8 @@ typedef struct {
#define ERTS_DEFAULT_ALCU_INIT { \
1024*1024, /* (bytes) ycs: sys_alloc carrier size */\
- 1024 /* (amount) mmc: max mseg carriers */\
+ ~((UWord) 0), /* (amount) mmc: max mseg carriers */\
+ 1 /* (bool) sac: sys_alloc carriers */\
}
#define ERTS_DEFAULT_ALLCTR_INIT { \
@@ -95,7 +97,7 @@ typedef struct {
50, /* (%) rmbcmt: rel mbc move threshold */\
1024*1024, /* (bytes) mmbcs: main multiblock carrier size */\
256, /* (amount) mmsbc: max mseg sbcs */\
- 10, /* (amount) mmmbc: max mseg mbcs */\
+ ~((UWord) 0), /* (amount) mmmbc: max mseg mbcs */ \
10*1024*1024, /* (bytes) lmbcs: largest mbc size */\
1024*1024, /* (bytes) smbcs: smallest mbc size */\
10, /* (amount) mbcgs: mbc growth stages */\
@@ -109,7 +111,8 @@ typedef struct {
#define ERTS_DEFAULT_ALCU_INIT { \
128*1024, /* (bytes) ycs: sys_alloc carrier size */\
- 1024 /* (amount) mmc: max mseg carriers */\
+ 1024, /* (amount) mmc: max mseg carriers */\
+ 1 /* (bool) sac: sys_alloc carriers */\
}
#define ERTS_DEFAULT_ALLCTR_INIT { \
@@ -128,7 +131,7 @@ typedef struct {
80, /* (%) rsbcmt: rel sbc move threshold */\
128*1024, /* (bytes) mmbcs: main multiblock carrier size */\
256, /* (amount) mmsbc: max mseg sbcs */\
- 10, /* (amount) mmmbc: max mseg mbcs */\
+ ~((UWord) 0), /* (amount) mmmbc: max mseg mbcs */ \
1024*1024, /* (bytes) lmbcs: largest mbc size */\
128*1024, /* (bytes) smbcs: smallest mbc size */\
10, /* (amount) mbcgs: mbc growth stages */\
@@ -217,25 +220,34 @@ erts_aint32_t erts_alcu_fix_alloc_shrink(Allctr_t *, erts_aint32_t);
#define MBC_FBLK_SZ_MASK UNIT_MASK
#define CARRIER_SZ_MASK UNIT_MASK
-#if HAVE_ERTS_MSEG
-
-# define MSEG_UNIT_SHIFT MSEG_ALIGN_BITS
-# define MSEG_UNIT_SZ (1 << MSEG_UNIT_SHIFT)
-# define MSEG_UNIT_MASK ((~(UWord)0) << MSEG_UNIT_SHIFT)
-
-# define MSEG_UNIT_FLOOR(X) ((X) & MSEG_UNIT_MASK)
-# define MSEG_UNIT_CEILING(X) MSEG_UNIT_FLOOR((X) + ~MSEG_UNIT_MASK)
-
+#if ERTS_HAVE_MSEG_SUPER_ALIGNED \
+ || (!HAVE_ERTS_MSEG && ERTS_HAVE_ERTS_SYS_ALIGNED_ALLOC)
+# ifndef MSEG_ALIGN_BITS
+# define ERTS_SUPER_ALIGN_BITS MSEG_ALIGN_BITS
+# else
+# define ERTS_SUPER_ALIGN_BITS 18
+# endif
# ifdef ARCH_64
# define MBC_ABLK_OFFSET_BITS 24
-# elif HAVE_SUPER_ALIGNED_MB_CARRIERS
+# else
# define MBC_ABLK_OFFSET_BITS 9
/* Affects hard limits for sbct and lmbcs documented in erts_alloc.xml */
# endif
-#endif
-#ifndef MBC_ABLK_OFFSET_BITS
+# define ERTS_SACRR_UNIT_SHIFT ERTS_SUPER_ALIGN_BITS
+# define ERTS_SACRR_UNIT_SZ (1 << ERTS_SACRR_UNIT_SHIFT)
+# define ERTS_SACRR_UNIT_MASK ((~(UWord)0) << ERTS_SACRR_UNIT_SHIFT)
+# define ERTS_SACRR_UNIT_FLOOR(X) ((X) & ERTS_SACRR_UNIT_MASK)
+# define ERTS_SACRR_UNIT_CEILING(X) ERTS_SACRR_UNIT_FLOOR((X) + ~ERTS_SACRR_UNIT_MASK)
+# define ERTS_SA_MB_CARRIERS 1
+#else
+# define ERTS_SA_MB_CARRIERS 0
# define MBC_ABLK_OFFSET_BITS 0 /* no carrier offset in block header */
#endif
+#if ERTS_HAVE_MSEG_SUPER_ALIGNED && !ERTS_HAVE_ERTS_SYS_ALIGNED_ALLOC
+# define ERTS_SUPER_ALIGNED_MSEG_ONLY 1
+#else
+# define ERTS_SUPER_ALIGNED_MSEG_ONLY 0
+#endif
#if MBC_ABLK_OFFSET_BITS
# define MBC_ABLK_OFFSET_SHIFT (sizeof(UWord)*8 - MBC_ABLK_OFFSET_BITS)
@@ -245,9 +257,9 @@ erts_aint32_t erts_alcu_fix_alloc_shrink(Allctr_t *, erts_aint32_t);
# define MBC_ABLK_SZ_MASK (~FLG_MASK)
#endif
-#define MBC_ABLK_SZ(B) (ASSERT_EXPR(!is_sbc_blk(B)), (B)->bhdr & MBC_ABLK_SZ_MASK)
-#define MBC_FBLK_SZ(B) (ASSERT_EXPR(!is_sbc_blk(B)), (B)->bhdr & MBC_FBLK_SZ_MASK)
-#define SBC_BLK_SZ(B) (ASSERT_EXPR(is_sbc_blk(B)), (B)->bhdr & SBC_BLK_SZ_MASK)
+#define MBC_ABLK_SZ(B) (ASSERT(!is_sbc_blk(B)), (B)->bhdr & MBC_ABLK_SZ_MASK)
+#define MBC_FBLK_SZ(B) (ASSERT(!is_sbc_blk(B)), (B)->bhdr & MBC_FBLK_SZ_MASK)
+#define SBC_BLK_SZ(B) (ASSERT(is_sbc_blk(B)), (B)->bhdr & SBC_BLK_SZ_MASK)
#define CARRIER_SZ(C) \
((C)->chdr & CARRIER_SZ_MASK)
@@ -327,8 +339,8 @@ typedef struct {
(B)->u.carrier)
# define ABLK_TO_MBC(B) \
(ASSERT(IS_MBC_BLK(B) && !IS_FREE_BLK(B)), \
- (Carrier_t*)((MSEG_UNIT_FLOOR((UWord)(B)) - \
- (((B)->bhdr >> MBC_ABLK_OFFSET_SHIFT) << MSEG_UNIT_SHIFT))))
+ (Carrier_t*)((ERTS_SACRR_UNIT_FLOOR((UWord)(B)) - \
+ (((B)->bhdr >> MBC_ABLK_OFFSET_SHIFT) << ERTS_SACRR_UNIT_SHIFT))))
# define BLK_TO_MBC(B) (IS_FREE_BLK(B) ? FBLK_TO_MBC(B) : ABLK_TO_MBC(B))
#else
# define FBLK_TO_MBC(B) ((B)->carrier)
diff --git a/erts/emulator/beam/erl_ao_firstfit_alloc.c b/erts/emulator/beam/erl_ao_firstfit_alloc.c
index 4e6c8b317e..396aa88e0b 100644
--- a/erts/emulator/beam/erl_ao_firstfit_alloc.c
+++ b/erts/emulator/beam/erl_ao_firstfit_alloc.c
@@ -85,9 +85,6 @@
#define SET_RED(N) (((AOFF_RBTree_t *) (N))->flags |= RED_FLG)
#define SET_BLACK(N) (((AOFF_RBTree_t *) (N))->flags &= ~RED_FLG)
-#undef ASSERT
-#define ASSERT ASSERT_EXPR
-
#if 1
#define RBT_ASSERT ASSERT
#else
diff --git a/erts/emulator/beam/erl_bestfit_alloc.c b/erts/emulator/beam/erl_bestfit_alloc.c
index 41f449bb28..59c14899a2 100644
--- a/erts/emulator/beam/erl_bestfit_alloc.c
+++ b/erts/emulator/beam/erl_bestfit_alloc.c
@@ -75,9 +75,6 @@
#define BF_BLK_SZ(B) MBC_FBLK_SZ(&(B)->hdr)
-#undef ASSERT
-#define ASSERT ASSERT_EXPR
-
#if 1
#define RBT_ASSERT ASSERT
#else
diff --git a/erts/emulator/beam/erl_bif_binary.c b/erts/emulator/beam/erl_bif_binary.c
index 0db19a1ee6..ff775691b3 100644
--- a/erts/emulator/beam/erl_bif_binary.c
+++ b/erts/emulator/beam/erl_bif_binary.c
@@ -927,6 +927,9 @@ static int do_binary_match_compile(Eterm argument, Eterm *tag, Binary **binp)
if (binary_bitsize(b) != 0) {
goto badarg;
}
+ if (binary_size(b) == 0) {
+ goto badarg;
+ }
++words;
characters += binary_size(b);
}
diff --git a/erts/emulator/beam/erl_bif_info.c b/erts/emulator/beam/erl_bif_info.c
index f5893f9291..8fa3aa29eb 100755
--- a/erts/emulator/beam/erl_bif_info.c
+++ b/erts/emulator/beam/erl_bif_info.c
@@ -1771,7 +1771,11 @@ info_1_tuple(Process* BIF_P, /* Pointer to current process. */
#if defined(PURIFY)
BIF_RET(erts_make_integer(purify_new_leaks(), BIF_P));
#elif defined(VALGRIND)
+# ifdef VALGRIND_DO_ADDED_LEAK_CHECK
+ VALGRIND_DO_ADDED_LEAK_CHECK;
+# else
VALGRIND_DO_LEAK_CHECK;
+# endif
BIF_RET(make_small(0));
#endif
} else if (*tp == am_fd) {
@@ -2091,7 +2095,7 @@ BIF_RETTYPE system_info_1(BIF_ALIST_1)
BIF_RET(res);
} else if (BIF_ARG_1 == am_sequential_tracer) {
val = erts_get_system_seq_tracer();
- ASSERT(is_internal_pid(val) || is_internal_port(val) || val==am_false)
+ ASSERT(is_internal_pid(val) || is_internal_port(val) || val==am_false);
hp = HAlloc(BIF_P, 3);
res = TUPLE2(hp, am_sequential_tracer, val);
BIF_RET(res);
@@ -2636,6 +2640,9 @@ BIF_RETTYPE system_info_1(BIF_ALIST_1)
BIF_RET(res);
}
+ else if (ERTS_IS_ATOM_STR("ets_limit",BIF_ARG_1)) {
+ BIF_RET(make_small(erts_db_get_max_tabs()));
+ }
BIF_ERROR(BIF_P, BADARG);
}
@@ -3286,6 +3293,9 @@ BIF_RETTYPE erts_debug_get_internal_state_1(BIF_ALIST_1)
erts_smp_thr_progress_unblock();
BIF_RET(res);
}
+ else if (ERTS_IS_ATOM_STR("mmap", BIF_ARG_1)) {
+ BIF_RET(erts_mmap_debug_info(BIF_P));
+ }
}
else if (is_tuple(BIF_ARG_1)) {
Eterm* tp = tuple_val(BIF_ARG_1);
diff --git a/erts/emulator/beam/erl_bif_os.c b/erts/emulator/beam/erl_bif_os.c
index 1062d4379b..e07c622928 100644
--- a/erts/emulator/beam/erl_bif_os.c
+++ b/erts/emulator/beam/erl_bif_os.c
@@ -180,3 +180,25 @@ BIF_RETTYPE os_putenv_2(BIF_ALIST_2)
BIF_RET(am_true);
}
+BIF_RETTYPE os_unsetenv_1(BIF_ALIST_1)
+{
+ char *key_buf;
+ char buf[STATIC_BUF_SIZE];
+
+ key_buf = erts_convert_filename_to_native(BIF_ARG_1,buf,STATIC_BUF_SIZE,
+ ERTS_ALC_T_TMP,0,0,NULL);
+ if (!key_buf) {
+ BIF_ERROR(BIF_P, BADARG);
+ }
+
+ if (erts_sys_unsetenv(key_buf)) {
+ if (key_buf != buf) {
+ erts_free(ERTS_ALC_T_TMP, key_buf);
+ }
+ BIF_ERROR(BIF_P, BADARG);
+ }
+ if (key_buf != buf) {
+ erts_free(ERTS_ALC_T_TMP, key_buf);
+ }
+ BIF_RET(am_true);
+}
diff --git a/erts/emulator/beam/erl_bif_port.c b/erts/emulator/beam/erl_bif_port.c
index 109c54fd7f..864349491a 100644
--- a/erts/emulator/beam/erl_bif_port.c
+++ b/erts/emulator/beam/erl_bif_port.c
@@ -84,7 +84,7 @@ BIF_RETTYPE open_port_2(BIF_ALIST_2)
}
static ERTS_INLINE Port *
-lookup_port(Process *c_p, Eterm id_or_name)
+lookup_port(Process *c_p, Eterm id_or_name, Uint32 invalid_flags)
{
/* TODO: Implement nicer lookup in register... */
Eterm id;
@@ -92,7 +92,19 @@ lookup_port(Process *c_p, Eterm id_or_name)
id = erts_whereis_name_to_id(c_p, id_or_name);
else
id = id_or_name;
- return erts_port_lookup(id, ERTS_PORT_SFLGS_INVALID_LOOKUP);
+ return erts_port_lookup(id, invalid_flags);
+}
+
+static ERTS_INLINE Port *
+sig_lookup_port(Process *c_p, Eterm id_or_name)
+{
+ return lookup_port(c_p, id_or_name, ERTS_PORT_SFLGS_INVALID_DRIVER_LOOKUP);
+}
+
+static ERTS_INLINE Port *
+data_lookup_port(Process *c_p, Eterm id_or_name)
+{
+ return lookup_port(c_p, id_or_name, ERTS_PORT_SFLGS_INVALID_LOOKUP);
}
/*
@@ -125,7 +137,7 @@ BIF_RETTYPE erts_internal_port_command_3(BIF_ALIST_3)
BIF_RET(am_badarg);
}
- prt = lookup_port(BIF_P, BIF_ARG_1);
+ prt = sig_lookup_port(BIF_P, BIF_ARG_1);
if (!prt)
BIF_RET(am_badarg);
@@ -185,7 +197,7 @@ BIF_RETTYPE erts_internal_port_call_3(BIF_ALIST_3)
unsigned int op;
erts_aint32_t state;
- prt = lookup_port(BIF_P, BIF_ARG_1);
+ prt = sig_lookup_port(BIF_P, BIF_ARG_1);
if (!prt)
BIF_RET(am_badarg);
@@ -235,7 +247,7 @@ BIF_RETTYPE erts_internal_port_control_3(BIF_ALIST_3)
unsigned int op;
erts_aint32_t state;
- prt = lookup_port(BIF_P, BIF_ARG_1);
+ prt = sig_lookup_port(BIF_P, BIF_ARG_1);
if (!prt)
BIF_RET(am_badarg);
@@ -290,7 +302,7 @@ BIF_RETTYPE erts_internal_port_close_1(BIF_ALIST_1)
ref = NIL;
#endif
- prt = lookup_port(BIF_P, BIF_ARG_1);
+ prt = sig_lookup_port(BIF_P, BIF_ARG_1);
if (!prt)
BIF_RET(am_badarg);
@@ -320,7 +332,7 @@ BIF_RETTYPE erts_internal_port_connect_2(BIF_ALIST_2)
Eterm ref;
Port* prt;
- prt = lookup_port(BIF_P, BIF_ARG_1);
+ prt = sig_lookup_port(BIF_P, BIF_ARG_1);
if (!prt)
BIF_RET(am_badarg);
@@ -352,7 +364,7 @@ BIF_RETTYPE erts_internal_port_info_1(BIF_ALIST_1)
Port* prt;
if (is_internal_port(BIF_ARG_1) || is_atom(BIF_ARG_1)) {
- prt = lookup_port(BIF_P, BIF_ARG_1);
+ prt = sig_lookup_port(BIF_P, BIF_ARG_1);
if (!prt)
BIF_RET(am_undefined);
}
@@ -391,7 +403,7 @@ BIF_RETTYPE erts_internal_port_info_2(BIF_ALIST_2)
Port* prt;
if (is_internal_port(BIF_ARG_1) || is_atom(BIF_ARG_1)) {
- prt = lookup_port(BIF_P, BIF_ARG_1);
+ prt = sig_lookup_port(BIF_P, BIF_ARG_1);
if (!prt)
BIF_RET(am_undefined);
}
@@ -523,7 +535,7 @@ BIF_RETTYPE port_set_data_2(BIF_ALIST_2)
erts_aint_t data;
Port* prt;
- prt = lookup_port(BIF_P, BIF_ARG_1);
+ prt = data_lookup_port(BIF_P, BIF_ARG_1);
if (!prt)
BIF_ERROR(BIF_P, BADARG);
@@ -564,7 +576,7 @@ BIF_RETTYPE port_get_data_1(BIF_ALIST_1)
erts_aint_t data;
Port* prt;
- prt = lookup_port(BIF_P, BIF_ARG_1);
+ prt = data_lookup_port(BIF_P, BIF_ARG_1);
if (!prt)
BIF_ERROR(BIF_P, BADARG);
@@ -784,43 +796,29 @@ open_port(Process* p, Eterm name, Eterm settings, int *err_typep, int *err_nump)
goto badarg;
}
- if (*tp == am_spawn || *tp == am_spawn_driver) { /* A process port */
+ if (*tp == am_spawn || *tp == am_spawn_driver || *tp == am_spawn_executable) { /* A process port */
+ int encoding;
if (arity != make_arityval(2)) {
goto badarg;
}
name = tp[1];
- if (is_atom(name)) {
- name_buf = (char *) erts_alloc(ERTS_ALC_T_TMP,
- atom_tab(atom_val(name))->len+1);
- sys_memcpy((void *) name_buf,
- (void *) atom_tab(atom_val(name))->name,
- atom_tab(atom_val(name))->len);
- name_buf[atom_tab(atom_val(name))->len] = '\0';
- } else if ((i = is_string(name))) {
- name_buf = (char *) erts_alloc(ERTS_ALC_T_TMP, i + 1);
- if (intlist_to_buf(name, name_buf, i) != i)
- erl_exit(1, "%s:%d: Internal error\n", __FILE__, __LINE__);
- name_buf[i] = '\0';
- } else {
+ encoding = erts_get_native_filename_encoding();
+ /* Do not convert the command to utf-16le yet, do that in win32 specific code */
+ /* since the cmd is used for comparsion with drivers names and copied to port info */
+ if (encoding == ERL_FILENAME_WIN_WCHAR) {
+ encoding = ERL_FILENAME_UTF8;
+ }
+ if ((name_buf = erts_convert_filename_to_encoding(name, NULL, 0, ERTS_ALC_T_TMP,0,1, encoding, NULL))
+ == NULL) {
goto badarg;
}
+
if (*tp == am_spawn_driver) {
opts.spawn_type = ERTS_SPAWN_DRIVER;
+ } else if (*tp == am_spawn_executable) {
+ opts.spawn_type = ERTS_SPAWN_EXECUTABLE;
}
- driver = &spawn_driver;
- } else if (*tp == am_spawn_executable) { /* A program */
- /*
- * {spawn_executable,Progname}
- */
-
- if (arity != make_arityval(2)) {
- goto badarg;
- }
- name = tp[1];
- if ((name_buf = erts_convert_filename_to_native(name, NULL, 0, ERTS_ALC_T_TMP,0,1, NULL)) == NULL) {
- goto badarg;
- }
- opts.spawn_type = ERTS_SPAWN_EXECUTABLE;
+
driver = &spawn_driver;
} else if (*tp == am_fd) { /* An fd port */
int n;
@@ -861,29 +859,8 @@ open_port(Process* p, Eterm name, Eterm settings, int *err_typep, int *err_nump)
}
if (edir != NIL) {
- /* A working directory is expressed differently if spawn_executable, i.e. Unicode is handles
- for spawn_executable... */
- if (opts.spawn_type != ERTS_SPAWN_EXECUTABLE) {
- Eterm iolist;
- DeclareTmpHeap(heap,4,p);
- int r;
-
- UseTmpHeap(4,p);
- heap[0] = edir;
- heap[1] = make_list(heap+2);
- heap[2] = make_small(0);
- heap[3] = NIL;
- iolist = make_list(heap);
- r = erts_iolist_to_buf(iolist, (char*) dir, MAXPATHLEN);
- UnUseTmpHeap(4,p);
- if (ERTS_IOLIST_TO_BUF_FAILED(r)) {
- goto badarg;
- }
- opts.wd = (char *) dir;
- } else {
- if ((opts.wd = erts_convert_filename_to_native(edir, NULL, 0, ERTS_ALC_T_TMP,0,1,NULL)) == NULL) {
- goto badarg;
- }
+ if ((opts.wd = erts_convert_filename_to_native(edir, NULL, 0, ERTS_ALC_T_TMP,0,1,NULL)) == NULL) {
+ goto badarg;
}
}
@@ -961,11 +938,11 @@ static char **convert_args(Eterm l)
int n;
int i = 0;
Eterm str;
- /* We require at least one element in list (argv[0]) */
if (is_not_list(l) && is_not_nil(l)) {
return NULL;
}
n = list_length(l);
+ /* We require at least one element in argv[0] + NULL at end */
pp = erts_alloc(ERTS_ALC_T_TMP, (n + 2) * sizeof(char **));
pp[i++] = erts_default_arg0;
while (is_list(l)) {
diff --git a/erts/emulator/beam/erl_bif_re.c b/erts/emulator/beam/erl_bif_re.c
index 3d34c2a77f..99c31738a5 100644
--- a/erts/emulator/beam/erl_bif_re.c
+++ b/erts/emulator/beam/erl_bif_re.c
@@ -180,6 +180,9 @@ static Eterm make_signed_integer(int x, Process *p)
#define PARSE_FLAG_STARTOFFSET 8
#define PARSE_FLAG_CAPTURE_OPT 16
#define PARSE_FLAG_GLOBAL 32
+#define PARSE_FLAG_REPORT_ERRORS 64
+#define PARSE_FLAG_MATCH_LIMIT 128
+#define PARSE_FLAG_MATCH_LIMIT_RECURSION 256
#define CAPSPEC_VALUES 0
#define CAPSPEC_TYPE 1
@@ -192,7 +195,9 @@ parse_options(Eterm listp, /* in */
int *exec_options, /* out */
int *flags,/* out */
int *startoffset, /* out */
- Eterm *capture_spec) /* capture_spec[CAPSPEC_SIZE] */ /* out */
+ Eterm *capture_spec, /* capture_spec[CAPSPEC_SIZE] */ /* out */
+ int *match_limit, /* out */
+ int *match_limit_recursion) /* out */
{
int copt,eopt,fl;
Eterm item;
@@ -234,7 +239,7 @@ parse_options(Eterm listp, /* in */
case am_offset:
{
int tmp;
- if (!term_to_int(tp[2],&tmp)) {
+ if (!term_to_int(tp[2],&tmp) || tmp < 0) {
return -1;
}
if (startoffset != NULL) {
@@ -243,6 +248,31 @@ parse_options(Eterm listp, /* in */
}
fl |= (PARSE_FLAG_UNIQUE_EXEC_OPT|PARSE_FLAG_STARTOFFSET);
break;
+ case am_match_limit:
+ {
+ int tmp;
+ if (!term_to_int(tp[2],&tmp) || tmp < 0) {
+ return -1;
+ }
+ if (match_limit != NULL) {
+ *match_limit = tmp;
+ }
+ }
+ fl |= (PARSE_FLAG_UNIQUE_EXEC_OPT|PARSE_FLAG_MATCH_LIMIT);
+ break;
+ case am_match_limit_recursion:
+ {
+ int tmp;
+ if (!term_to_int(tp[2],&tmp) || tmp < 0) {
+ return -1;
+ }
+ if (match_limit_recursion != NULL) {
+ *match_limit_recursion = tmp;
+ }
+ }
+ fl |= (PARSE_FLAG_UNIQUE_EXEC_OPT|
+ PARSE_FLAG_MATCH_LIMIT_RECURSION);
+ break;
case am_newline:
if (!is_atom(tp[2])) {
return -1;
@@ -276,7 +306,7 @@ parse_options(Eterm listp, /* in */
default:
return -1;
}
- }else if (is_not_atom(item)) {
+ } else if (is_not_atom(item)) {
return -1;
} else {
switch(item) {
@@ -288,6 +318,10 @@ parse_options(Eterm listp, /* in */
eopt |= PCRE_NOTEMPTY;
fl |= PARSE_FLAG_UNIQUE_EXEC_OPT;
break;
+ case am_notempty_atstart:
+ eopt |= PCRE_NOTEMPTY_ATSTART;
+ fl |= PARSE_FLAG_UNIQUE_EXEC_OPT;
+ break;
case am_notbol:
eopt |= PCRE_NOTBOL;
fl |= PARSE_FLAG_UNIQUE_EXEC_OPT;
@@ -296,6 +330,10 @@ parse_options(Eterm listp, /* in */
eopt |= PCRE_NOTEOL;
fl |= PARSE_FLAG_UNIQUE_EXEC_OPT;
break;
+ case am_no_start_optimize:
+ copt |= PCRE_NO_START_OPTIMIZE;
+ fl |= PARSE_FLAG_UNIQUE_COMPILE_OPT;
+ break;
case am_caseless:
copt |= PCRE_CASELESS;
fl |= PARSE_FLAG_UNIQUE_COMPILE_OPT;
@@ -332,6 +370,18 @@ parse_options(Eterm listp, /* in */
copt |= PCRE_UNGREEDY;
fl |= PARSE_FLAG_UNIQUE_COMPILE_OPT;
break;
+ case am_ucp:
+ copt |= PCRE_UCP;
+ fl |= PARSE_FLAG_UNIQUE_COMPILE_OPT;
+ break;
+ case am_never_utf:
+ copt |= PCRE_NEVER_UTF;
+ fl |= PARSE_FLAG_UNIQUE_COMPILE_OPT;
+ break;
+ case am_report_errors:
+ fl |= (PARSE_FLAG_UNIQUE_EXEC_OPT |
+ PARSE_FLAG_REPORT_ERRORS);
+ break;
case am_unicode:
copt |= PCRE_UTF8;
fl |= (PARSE_FLAG_UNIQUE_COMPILE_OPT | PARSE_FLAG_UNICODE);
@@ -359,7 +409,7 @@ parse_options(Eterm listp, /* in */
if (compile_options != NULL) {
*compile_options = copt;
}
- if (exec_options != NULL) {
+ if (exec_options != NULL) {
*exec_options = eopt;
}
if (flags != NULL) {
@@ -373,34 +423,49 @@ parse_options(Eterm listp, /* in */
*/
static Eterm
-build_compile_result(Process *p, Eterm error_tag, pcre *result, int errcode, const char *errstr, int errofset, int unicode, int with_ok)
+build_compile_result(Process *p, Eterm error_tag, pcre *result, int errcode, const char *errstr, int errofset, int unicode, int with_ok, Eterm extra_err_tag)
{
Eterm *hp;
Eterm ret;
size_t pattern_size;
int capture_count;
+ int use_crlf;
+ unsigned long options;
if (!result) {
/* Return {error_tag, {Code, String, Offset}} */
int elen = sys_strlen(errstr);
int need = 3 /* tuple of 2 */ +
3 /* tuple of 2 */ +
- (2 * elen) /* The error string list */;
+ (2 * elen) /* The error string list */ +
+ ((extra_err_tag != NIL) ? 3 : 0);
hp = HAlloc(p, need);
ret = buf_to_intlist(&hp, (char *) errstr, elen, NIL);
ret = TUPLE2(hp, ret, make_small(errofset));
hp += 3;
+ if (extra_err_tag != NIL) {
+ /* Return {error_tag, {extra_tag,
+ {Code, String, Offset}}} instead */
+ ret = TUPLE2(hp, extra_err_tag, ret);
+ hp += 3;
+ }
ret = TUPLE2(hp, error_tag, ret);
} else {
erts_pcre_fullinfo(result, NULL, PCRE_INFO_SIZE, &pattern_size);
erts_pcre_fullinfo(result, NULL, PCRE_INFO_CAPTURECOUNT, &capture_count);
+ erts_pcre_fullinfo(result, NULL, PCRE_INFO_OPTIONS, &options);
+ options &= PCRE_NEWLINE_CR|PCRE_NEWLINE_LF | PCRE_NEWLINE_CRLF |
+ PCRE_NEWLINE_ANY | PCRE_NEWLINE_ANYCRLF;
+ use_crlf = (options == PCRE_NEWLINE_ANY ||
+ options == PCRE_NEWLINE_CRLF ||
+ options == PCRE_NEWLINE_ANYCRLF);
/* XXX: Optimize - keep in offheap binary to allow this to
be kept across traps w/o need of copying */
ret = new_binary(p, (byte *) result, pattern_size);
erts_pcre_free(result);
- hp = HAlloc(p, (with_ok) ? (3+5) : 5);
- ret = TUPLE4(hp,am_re_pattern, make_small(capture_count), make_small(unicode),ret);
+ hp = HAlloc(p, (with_ok) ? (3+6) : 6);
+ ret = TUPLE5(hp,am_re_pattern, make_small(capture_count), make_small(unicode),make_small(use_crlf),ret);
if (with_ok) {
- hp += 5;
+ hp += 6;
ret = TUPLE2(hp,am_ok,ret);
}
}
@@ -424,9 +489,12 @@ re_compile(Process* p, Eterm arg1, Eterm arg2)
int options = 0;
int pflags = 0;
int unicode = 0;
+#ifdef DEBUG
+ int buffres;
+#endif
- if (parse_options(arg2,&options,NULL,&pflags,NULL,NULL)
+ if (parse_options(arg2,&options,NULL,&pflags,NULL,NULL,NULL,NULL)
< 0) {
BIF_ERROR(p,BADARG);
}
@@ -445,16 +513,19 @@ re_compile(Process* p, Eterm arg1, Eterm arg2)
BIF_ERROR(p,BADARG);
}
expr = erts_alloc(ERTS_ALC_T_RE_TMP_BUF, slen + 1);
- if (erts_iolist_to_buf(arg1, expr, slen) != 0) {
- erts_free(ERTS_ALC_T_RE_TMP_BUF, expr);
- BIF_ERROR(p,BADARG);
- }
+#ifdef DEBUG
+ buffres =
+#endif
+ erts_iolist_to_buf(arg1, expr, slen);
+
+ ASSERT(buffres >= 0);
+
expr[slen]='\0';
result = erts_pcre_compile2(expr, options, &errcode,
&errstr, &errofset, default_table);
ret = build_compile_result(p, am_error, result, errcode,
- errstr, errofset, unicode, 1);
+ errstr, errofset, unicode, 1, NIL);
erts_free(ERTS_ALC_T_RE_TMP_BUF, expr);
BIF_RET(ret);
}
@@ -492,7 +563,7 @@ typedef struct _return_info {
} ReturnInfo;
typedef struct _restart_context {
- pcre_extra extra;
+ erts_pcre_extra extra;
void *restart_data;
Uint32 flags;
char *subject; /* to be able to free it when done */
@@ -502,6 +573,7 @@ typedef struct _restart_context {
} RestartContext;
#define RESTART_FLAG_SUBJECT_IN_BINARY 0x1
+#define RESTART_FLAG_REPORT_MATCH_LIMIT 0x2
static void cleanup_restart_context(RestartContext *rc)
{
@@ -542,13 +614,29 @@ static Eterm build_exec_return(Process *p, int rc, RestartContext *restartp, Ete
Eterm res;
Eterm *hp;
if (rc <= 0) {
- res = am_nomatch;
+ if (restartp->flags & RESTART_FLAG_REPORT_MATCH_LIMIT) {
+ if (rc == PCRE_ERROR_MATCHLIMIT) {
+ hp = HAlloc(p,3);
+ res = TUPLE2(hp,am_error,am_match_limit);
+ } else if (rc == PCRE_ERROR_RECURSIONLIMIT) {
+ hp = HAlloc(p,3);
+ res = TUPLE2(hp,am_error,am_match_limit_recursion);
+ } else {
+ res = am_nomatch;
+ }
+ } else {
+ res = am_nomatch;
+ }
} else {
- ReturnInfo *ri = restartp->ret_info;
+ ReturnInfo *ri;
ReturnInfo defri = {RetIndex,0,{0}};
- if (ri == NULL) {
+
+ if (restartp->ret_info == NULL) {
ri = &defri;
+ } else {
+ ri = restartp->ret_info;
}
+
if (ri->type == RetNone) {
res = am_match;
} else if (ri->type == RetIndex){
@@ -577,6 +665,17 @@ static Eterm build_exec_return(Process *p, int rc, RestartContext *restartp, Ete
ri->num_spec * 2 * sizeof(Eterm));
for (i = 0; i < ri->num_spec; ++i) {
x = ri->v[i];
+ if (x < -1) {
+ int n = i-x+1;
+ int j;
+ for (j = i+1; j < ri->num_spec && j < n; ++j) {
+ if (restartp->ovector[(ri->v[j])*2] >= 0) {
+ x = ri->v[j];
+ break;
+ }
+ }
+ i = n-1;
+ }
if (x < rc && x >= 0) {
tmp_vect[n*2] = make_signed_integer(restartp->ovector[x*2],p);
tmp_vect[n*2+1] = make_signed_integer(restartp->ovector[x*2+1]-restartp->ovector[x*2],p);
@@ -658,6 +757,17 @@ static Eterm build_exec_return(Process *p, int rc, RestartContext *restartp, Ete
ri->num_spec * sizeof(Eterm));
for (i = 0; i < ri->num_spec; ++i) {
x = ri->v[i];
+ if (x < -1) {
+ int n = i-x+1;
+ int j;
+ for (j = i+1; j < ri->num_spec && j < n; ++j) {
+ if (restartp->ovector[(ri->v[j])*2] >= 0) {
+ x = ri->v[j];
+ break;
+ }
+ }
+ i = n-1;
+ }
if (x < rc && x >= 0) {
char *cp;
int len;
@@ -722,6 +832,49 @@ static Eterm build_exec_return(Process *p, int rc, RestartContext *restartp, Ete
*/
#define RINFO_SIZ(Num) (sizeof(ReturnInfo) + (sizeof(int) * (Num - 1)))
+#define PICK_INDEX(NameEntry) \
+ ((int) ((((unsigned) ((unsigned char *) (NameEntry))[0]) << 8) + \
+ ((unsigned) ((unsigned char *) (NameEntry))[1])))
+
+
+static void build_one_capture(const pcre *code, ReturnInfo **ri, int *sallocated, int has_dupnames, char *name)
+{
+ ReturnInfo *r = (*ri);
+ if (has_dupnames) {
+ /* Build a sequence of positions, starting with -size if
+ more than one, otherwise just put the index there... */
+ char *first,*last;
+ int esize = erts_pcre_get_stringtable_entries(code,name,&first,&last);
+ if (esize == PCRE_ERROR_NOSUBSTRING) {
+ r->v[r->num_spec - 1] = -1;
+ } else if(last == first) {
+ r->v[r->num_spec - 1] = PICK_INDEX(first);
+ } else {
+ int num = ((last - first) / esize) + 1;
+ int i;
+ ASSERT(num > 1);
+ r->v[r->num_spec - 1] = -num; /* A value less than -1 means
+ multiple indexes for same name */
+ for (i = 0; i < num; ++i) {
+ ++(r->num_spec);
+ if(r->num_spec > (*sallocated)) {
+ (*sallocated) += 10;
+ r = erts_realloc(ERTS_ALC_T_RE_SUBJECT, r,
+ RINFO_SIZ((*sallocated)));
+ }
+ r->v[r->num_spec - 1] = PICK_INDEX(first);
+ first += esize;
+ }
+ }
+ } else {
+ /* Use the faster binary search if no duplicate names are present */
+ if ((r->v[r->num_spec - 1] = erts_pcre_get_stringnumber(code,name)) ==
+ PCRE_ERROR_NOSUBSTRING) {
+ r->v[r->num_spec - 1] = -1;
+ }
+ }
+ *ri = r;
+}
static ReturnInfo *
build_capture(Eterm capture_spec[CAPSPEC_SIZE], const pcre *code)
@@ -770,13 +923,58 @@ build_capture(Eterm capture_spec[CAPSPEC_SIZE], const pcre *code)
}
ri->v[ri->num_spec - 1] = 0;
break;
+ case am_all_names:
+ {
+ int rc,i,top;
+ int entrysize;
+ unsigned char *nametable, *last = NULL;
+ int has_dupnames;
+ unsigned long options;
+
+ if (erts_pcre_fullinfo(code, NULL, PCRE_INFO_OPTIONS, &options) != 0)
+ goto error;
+ if ((rc = erts_pcre_fullinfo(code, NULL, PCRE_INFO_NAMECOUNT, &top)) != 0)
+ goto error;
+ if (top <= 0) {
+ ri->num_spec = 0;
+ ri->type = RetNone;
+ break;
+ }
+ if (erts_pcre_fullinfo(code, NULL, PCRE_INFO_NAMEENTRYSIZE, &entrysize) != 0)
+ goto error;
+ if (erts_pcre_fullinfo(code, NULL, PCRE_INFO_NAMETABLE, &nametable) != 0)
+ goto error;
+
+ has_dupnames = ((options & PCRE_DUPNAMES) != 0);
+
+ for(i=0;i<top;++i) {
+ if (last == NULL || !has_dupnames || strcmp((char *) last+2,(char *) nametable+2)) {
+ ASSERT(ri->num_spec >= 0);
+ ++(ri->num_spec);
+ if(ri->num_spec > sallocated) {
+ sallocated += 10;
+ ri = erts_realloc(ERTS_ALC_T_RE_SUBJECT, ri, RINFO_SIZ(sallocated));
+ }
+ if (has_dupnames) {
+ /* This could be more effective, we actually have
+ the names and could fill in the vector
+ immediately. Now we lookup the name again. */
+ build_one_capture(code,&ri,&sallocated,has_dupnames,(char *) nametable+2);
+ } else {
+ ri->v[ri->num_spec - 1] = PICK_INDEX(nametable);
+ }
+ }
+ last = nametable;
+ nametable += entrysize;
+ }
+ break;
+ }
default:
if (is_list(capture_spec[CAPSPEC_VALUES])) {
for(l=capture_spec[CAPSPEC_VALUES];is_list(l);l = CDR(list_val(l))) {
int x;
Eterm val = CAR(list_val(l));
- if (ri->num_spec < 0)
- ri->num_spec = 0;
+ ASSERT(ri->num_spec >= 0);
++(ri->num_spec);
if(ri->num_spec > sallocated) {
sallocated += 10;
@@ -785,6 +983,11 @@ build_capture(Eterm capture_spec[CAPSPEC_SIZE], const pcre *code)
if (term_to_int(val,&x)) {
ri->v[ri->num_spec - 1] = x;
} else if (is_atom(val) || is_binary(val) || is_list(val)) {
+ int has_dupnames;
+ unsigned long options;
+ if (erts_pcre_fullinfo(code, NULL, PCRE_INFO_OPTIONS, &options) != 0)
+ goto error;
+ has_dupnames = ((options & PCRE_DUPNAMES) != 0);
if (is_atom(val)) {
Atom *ap = atom_tab(atom_val(val));
if ((ap->len + 1) > tmpbsiz) {
@@ -799,6 +1002,10 @@ build_capture(Eterm capture_spec[CAPSPEC_SIZE], const pcre *code)
tmpb[ap->len] = '\0';
} else {
ErlDrvSizeT slen;
+#ifdef DEBUG
+ int buffres;
+#endif
+
if (erts_iolist_size(val, &slen)) {
goto error;
}
@@ -810,15 +1017,15 @@ build_capture(Eterm capture_spec[CAPSPEC_SIZE], const pcre *code)
(tmpbsiz = slen + 1));
}
}
- if (erts_iolist_to_buf(val, tmpb, slen) != 0) {
- goto error;
- }
+
+#ifdef DEBUG
+ buffres =
+#endif
+ erts_iolist_to_buf(val, tmpb, slen);
+ ASSERT(buffres >= 0);
tmpb[slen] = '\0';
}
- if ((ri->v[ri->num_spec - 1] = erts_pcre_get_stringnumber(code,tmpb)) ==
- PCRE_ERROR_NOSUBSTRING) {
- ri->v[ri->num_spec - 1] = -1;
- }
+ build_one_capture(code,&ri,&sallocated,has_dupnames,tmpb);
} else {
goto error;
}
@@ -867,15 +1074,18 @@ re_run(Process *p, Eterm arg1, Eterm arg2, Eterm arg3)
unsigned long loop_count;
Eterm capture[CAPSPEC_SIZE] = CAPSPEC_INIT;
int is_list_cap;
+ int match_limit = 0;
+ int match_limit_recursion = 0;
- if (parse_options(arg3,&comp_options,&options,&pflags,&startoffset,capture)
+ if (parse_options(arg3,&comp_options,&options,&pflags,&startoffset,capture,
+ &match_limit,&match_limit_recursion)
< 0) {
BIF_ERROR(p,BADARG);
}
is_list_cap = ((pflags & PARSE_FLAG_CAPTURE_OPT) &&
(capture[CAPSPEC_TYPE] == am_list));
- if (is_not_tuple(arg2) || (arityval(*tuple_val(arg2)) != 4)) {
+ if (is_not_tuple(arg2) || (arityval(*tuple_val(arg2)) != 5)) {
if (is_binary(arg2) || is_list(arg2) || is_nil(arg2)) {
/* Compile from textual RE */
ErlDrvSizeT slen;
@@ -885,6 +1095,9 @@ re_run(Process *p, Eterm arg1, Eterm arg2, Eterm arg3)
const char *errstr = "";
int errofset = 0;
int capture_count;
+#ifdef DEBUG
+ int buffres;
+#endif
if (pflags & PARSE_FLAG_UNICODE &&
(!is_binary(arg2) || !is_binary(arg1) ||
@@ -897,18 +1110,32 @@ re_run(Process *p, Eterm arg1, Eterm arg2, Eterm arg3)
}
expr = erts_alloc(ERTS_ALC_T_RE_TMP_BUF, slen + 1);
- if (erts_iolist_to_buf(arg2, expr, slen) != 0) {
- erts_free(ERTS_ALC_T_RE_TMP_BUF, expr);
- BIF_ERROR(p,BADARG);
- }
+
+#ifdef DEBUG
+ buffres =
+#endif
+ erts_iolist_to_buf(arg2, expr, slen);
+
+ ASSERT(buffres >= 0);
+
expr[slen]='\0';
result = erts_pcre_compile2(expr, comp_options, &errcode,
&errstr, &errofset, default_table);
if (!result) {
- erts_free(ERTS_ALC_T_RE_TMP_BUF, expr);
/* Compilation error gives badarg except in the compile
- function */
- BIF_ERROR(p,BADARG);
+ function or if we have PARSE_FLAG_REPORT_ERRORS */
+ if (pflags & PARSE_FLAG_REPORT_ERRORS) {
+ res = build_compile_result(p, am_error, result, errcode,
+ errstr, errofset,
+ (pflags &
+ PARSE_FLAG_UNICODE) ? 1 : 0,
+ 1, am_compile);
+ erts_free(ERTS_ALC_T_RE_TMP_BUF, expr);
+ BIF_RET(res);
+ } else {
+ erts_free(ERTS_ALC_T_RE_TMP_BUF, expr);
+ BIF_ERROR(p,BADARG);
+ }
}
if (pflags & PARSE_FLAG_GLOBAL) {
Eterm precompiled =
@@ -917,7 +1144,7 @@ re_run(Process *p, Eterm arg1, Eterm arg2, Eterm arg3)
errstr, errofset,
(pflags &
PARSE_FLAG_UNICODE) ? 1 : 0,
- 0);
+ 0, NIL);
Eterm *hp,r;
erts_free(ERTS_ALC_T_RE_TMP_BUF, expr);
hp = HAlloc(p,4);
@@ -947,7 +1174,8 @@ re_run(Process *p, Eterm arg1, Eterm arg2, Eterm arg3)
tp = tuple_val(arg2);
if (tp[1] != am_re_pattern || is_not_small(tp[2]) ||
- is_not_small(tp[3]) || is_not_binary(tp[4])) {
+ is_not_small(tp[3]) || is_not_small(tp[4]) ||
+ is_not_binary(tp[5])) {
BIF_ERROR(p,BADARG);
}
@@ -967,9 +1195,9 @@ re_run(Process *p, Eterm arg1, Eterm arg2, Eterm arg3)
}
ovsize = 3*(unsigned_val(tp[2])+1);
- code_size = binary_size(tp[4]);
+ code_size = binary_size(tp[5]);
if ((code_tmp = (const pcre *)
- erts_get_aligned_binary_bytes(tp[4], &temp_alloc)) == NULL) {
+ erts_get_aligned_binary_bytes(tp[5], &temp_alloc)) == NULL) {
erts_free_aligned_binary_bytes(temp_alloc);
BIF_ERROR(p, BADARG);
}
@@ -994,6 +1222,16 @@ re_run(Process *p, Eterm arg1, Eterm arg2, Eterm arg3)
restart.extra.restart_flags = 0;
restart.extra.loop_counter_return = &loop_count;
restart.ret_info = NULL;
+
+ if (pflags & PARSE_FLAG_MATCH_LIMIT) {
+ restart.extra.flags |= PCRE_EXTRA_MATCH_LIMIT;
+ restart.extra.match_limit = match_limit;
+ }
+
+ if (pflags & PARSE_FLAG_MATCH_LIMIT_RECURSION) {
+ restart.extra.flags |= PCRE_EXTRA_MATCH_LIMIT_RECURSION;
+ restart.extra.match_limit_recursion = match_limit_recursion;
+ }
if (pflags & PARSE_FLAG_CAPTURE_OPT) {
if ((restart.ret_info = build_capture(capture,restart.code)) == NULL) {
@@ -1002,7 +1240,7 @@ re_run(Process *p, Eterm arg1, Eterm arg2, Eterm arg3)
BIF_ERROR(p,BADARG);
}
}
-
+
/* Optimized - if already in binary off heap, keep that and avoid
copying, also binary returns can be sub binaries in that case */
@@ -1029,6 +1267,9 @@ re_run(Process *p, Eterm arg1, Eterm arg2, Eterm arg3)
restart.subject = (char *) (pb->bytes+offset);
restart.flags |= RESTART_FLAG_SUBJECT_IN_BINARY;
} else {
+#ifdef DEBUG
+ int buffres;
+#endif
handle_iolist:
if (erts_iolist_size(arg1, &slength)) {
erts_free(ERTS_ALC_T_RE_SUBJECT, restart.ovector);
@@ -1040,24 +1281,30 @@ handle_iolist:
}
restart.subject = erts_alloc(ERTS_ALC_T_RE_SUBJECT, slength);
- if (erts_iolist_to_buf(arg1, restart.subject, slength) != 0) {
- erts_free(ERTS_ALC_T_RE_SUBJECT, restart.ovector);
- erts_free(ERTS_ALC_T_RE_SUBJECT, restart.code);
- erts_free(ERTS_ALC_T_RE_SUBJECT, restart.subject);
- if (restart.ret_info != NULL) {
- erts_free(ERTS_ALC_T_RE_SUBJECT, restart.ret_info);
- }
- BIF_ERROR(p,BADARG);
- }
+#ifdef DEBUG
+ buffres =
+#endif
+ erts_iolist_to_buf(arg1, restart.subject, slength);
+ ASSERT(buffres >= 0);
}
+ if (pflags & PARSE_FLAG_REPORT_ERRORS) {
+ restart.flags |= RESTART_FLAG_REPORT_MATCH_LIMIT;
+ }
#ifdef DEBUG
loop_count = 0xFFFFFFFF;
#endif
+
+ rc = erts_pcre_exec(restart.code, &(restart.extra), restart.subject,
+ slength, startoffset,
+ options, restart.ovector, ovsize);
+
+ if (rc == PCRE_ERROR_BADENDIANNESS || rc == PCRE_ERROR_BADMAGIC) {
+ cleanup_restart_context(&restart);
+ BIF_ERROR(p,BADARG);
+ }
- rc = erts_pcre_exec(restart.code, &(restart.extra), restart.subject, slength, startoffset,
- options, restart.ovector, ovsize);
ASSERT(loop_count != 0xFFFFFFFF);
BUMP_REDS(p, loop_count / LOOP_FACTOR);
if (rc == PCRE_ERROR_LOOP_LIMIT) {
@@ -1077,7 +1324,7 @@ handle_iolist:
arg2 /* To avoid GC of precompiled code, XXX: not utilized yet */,
magic_bin);
}
-
+
res = build_exec_return(p, rc, &restart, arg1);
cleanup_restart_context(&restart);
@@ -1149,6 +1396,120 @@ static BIF_RETTYPE re_exec_trap(BIF_ALIST_3)
BIF_RET(res);
}
+BIF_RETTYPE
+re_inspect_2(BIF_ALIST_2)
+{
+ Eterm *tp,*tmp_vec,*hp;
+ int i,top,j;
+ int entrysize;
+ unsigned char *nametable, *last,*name;
+ int has_dupnames;
+ unsigned long options;
+ int num_names;
+ Eterm res;
+ const pcre *code;
+ byte *temp_alloc = NULL;
+#ifdef DEBUG
+ int infores;
+#endif
+
+
+ if (is_not_tuple(BIF_ARG_1) || (arityval(*tuple_val(BIF_ARG_1)) != 5)) {
+ goto error;
+ }
+ tp = tuple_val(BIF_ARG_1);
+ if (tp[1] != am_re_pattern || is_not_small(tp[2]) ||
+ is_not_small(tp[3]) || is_not_small(tp[4]) ||
+ is_not_binary(tp[5])) {
+ goto error;
+ }
+ if (BIF_ARG_2 != am_namelist) {
+ goto error;
+ }
+ if ((code = (const pcre *)
+ erts_get_aligned_binary_bytes(tp[5], &temp_alloc)) == NULL) {
+ goto error;
+ }
+
+ /* OK, so let's try to get some info */
+
+ if (erts_pcre_fullinfo(code, NULL, PCRE_INFO_OPTIONS, &options) != 0)
+ goto error;
+
+#ifdef DEBUG
+ infores =
+#endif
+ erts_pcre_fullinfo(code, NULL, PCRE_INFO_NAMECOUNT, &top);
+
+ ASSERT(infores == 0);
+
+ if (top <= 0) {
+ hp = HAlloc(BIF_P, 3);
+ res = TUPLE2(hp,am_namelist,NIL);
+ erts_free_aligned_binary_bytes(temp_alloc);
+ BIF_RET(res);
+ }
+#ifdef DEBUG
+ infores =
+#endif
+ erts_pcre_fullinfo(code, NULL, PCRE_INFO_NAMEENTRYSIZE, &entrysize);
+
+ ASSERT(infores == 0);
+
+#ifdef DEBUG
+ infores =
+#endif
+ erts_pcre_fullinfo(code, NULL, PCRE_INFO_NAMETABLE, &nametable);
+
+ ASSERT(infores == 0);
+
+ has_dupnames = ((options & PCRE_DUPNAMES) != 0);
+ /* First, count the names */
+ num_names = 0;
+ last = NULL;
+ name = nametable;
+ for(i=0;i<top;++i) {
+ if (last == NULL || !has_dupnames || strcmp((char *) last+2,
+ (char *) name+2)) {
+ ++num_names;
+ }
+ last = name;
+ name += entrysize;
+ }
+ tmp_vec = erts_alloc(ERTS_ALC_T_RE_TMP_BUF,
+ num_names * sizeof(Eterm));
+ /* Re-iterate and fill tmp_vec */
+ last = NULL;
+ name = nametable;
+ j = 0;
+ for(i=0;i<top;++i) {
+ if (last == NULL || !has_dupnames || strcmp((char *) last+2,
+ (char *) name+2)) {
+ tmp_vec[j++] = new_binary(BIF_P, (byte *) name+2, strlen((char *) name+2));
+ }
+ last = name;
+ name += entrysize;
+ }
+ ASSERT(j == num_names);
+ hp = HAlloc(BIF_P, 3+2*j);
+ res = NIL;
+ for(i = j-1 ;i >= 0; --i) {
+ res = CONS(hp,tmp_vec[i],res);
+ hp += 2;
+ }
+ res = TUPLE2(hp,am_namelist,res);
+ erts_free_aligned_binary_bytes(temp_alloc);
+ erts_free(ERTS_ALC_T_RE_TMP_BUF, tmp_vec);
+ BIF_RET(res);
+
+ error:
+ /* tmp_vec never allocated when we reach here */
+ erts_free_aligned_binary_bytes(temp_alloc);
+ BIF_ERROR(BIF_P,BADARG);
+}
+
+
+
diff --git a/erts/emulator/beam/erl_bif_timer.c b/erts/emulator/beam/erl_bif_timer.c
index d67695e533..03ac97283c 100644
--- a/erts/emulator/beam/erl_bif_timer.c
+++ b/erts/emulator/beam/erl_bif_timer.c
@@ -616,7 +616,7 @@ erts_print_bif_timer_info(int to, void *to_arg)
: btm->receiver.proc.ess->common.id);
erts_print(to, to_arg, "=timer:%T\n", receiver);
erts_print(to, to_arg, "Message: %T\n", btm->message);
- erts_print(to, to_arg, "Time left: %u ms\n",
+ erts_print(to, to_arg, "Time left: %u\n",
erts_time_left(&btm->tm));
}
}
diff --git a/erts/emulator/beam/erl_binary.h b/erts/emulator/beam/erl_binary.h
index 506c4813fa..819b19e566 100644
--- a/erts/emulator/beam/erl_binary.h
+++ b/erts/emulator/beam/erl_binary.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2000-2011. All Rights Reserved.
+ * Copyright Ericsson AB 2000-2013. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -153,7 +153,7 @@ do { \
#define binary_bytes(Bin) \
(*binary_val(Bin) == HEADER_PROC_BIN ? \
((ProcBin *) binary_val(Bin))->bytes : \
- (ASSERT_EXPR(thing_subtag(*binary_val(Bin)) == HEAP_BINARY_SUBTAG), \
+ (ASSERT(thing_subtag(*binary_val(Bin)) == HEAP_BINARY_SUBTAG), \
(byte *)(&(((ErlHeapBin *) binary_val(Bin))->data))))
void erts_init_binary(void);
@@ -183,7 +183,7 @@ BIF_RETTYPE erts_binary_part(Process *p, Eterm binary, Eterm epos, Eterm elen);
#endif
#define ERTS_CHK_BIN_ALIGNMENT(B) \
- do { ASSERT(!(B) || (((UWord) &((Binary *)(B))->orig_bytes[0]) & ERTS_BIN_ALIGNMENT_MASK) == ((UWord) 0)) } while(0)
+ do { ASSERT(!(B) || (((UWord) &((Binary *)(B))->orig_bytes[0]) & ERTS_BIN_ALIGNMENT_MASK) == ((UWord) 0)); } while(0)
ERTS_GLB_INLINE byte* erts_get_aligned_binary_bytes(Eterm bin, byte** base_ptr);
ERTS_GLB_INLINE void erts_free_aligned_binary_bytes(byte* buf);
@@ -225,7 +225,7 @@ erts_free_aligned_binary_bytes(byte* buf)
** These extra bytes where earlier (< R13B04) added by an alignment-bug
** in this code. Do we dare remove this in some major release (R14?) maybe?
*/
-#ifdef DEBUG
+#if defined(DEBUG) || defined(VALGRIND)
# define CHICKEN_PAD 0
#else
# define CHICKEN_PAD (sizeof(void*) - 1)
diff --git a/erts/emulator/beam/erl_bits.c b/erts/emulator/beam/erl_bits.c
index 43eb691338..73765772c8 100644
--- a/erts/emulator/beam/erl_bits.c
+++ b/erts/emulator/beam/erl_bits.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1999-2012. All Rights Reserved.
+ * Copyright Ericsson AB 1999-2013. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -1491,7 +1491,7 @@ erts_bs_private_append(Process* p, Eterm bin, Eterm build_size_term, Uint unit)
bptr->flags = 0;
bptr->orig_size = new_size;
erts_refc_init(&bptr->refc, 1);
- sys_memcpy(bptr->orig_bytes, binp->orig_bytes, pb->size);
+ sys_memcpy(bptr->orig_bytes, binp->orig_bytes, binp->orig_size);
pb->flags |= PB_IS_WRITABLE | PB_ACTIVE_WRITER;
pb->val = bptr;
pb->bytes = (byte *) bptr->orig_bytes;
@@ -1810,6 +1810,11 @@ erts_cmp_bits(byte* a_ptr, size_t a_offs, byte* b_ptr, size_t b_offs, size_t siz
Uint rshift;
int cmp;
+ ASSERT(a_offs < 8 && b_offs < 8);
+
+ if (size == 0)
+ return 0;
+
if (((a_offs | b_offs | size) & 7) == 0) {
int byte_size = size >> 3;
return sys_memcmp(a_ptr, b_ptr, byte_size);
@@ -1818,58 +1823,72 @@ erts_cmp_bits(byte* a_ptr, size_t a_offs, byte* b_ptr, size_t b_offs, size_t siz
/* Compare bit by bit until a_ptr is aligned on byte boundary */
a = *a_ptr++;
b = *b_ptr++;
- while (size > 0) {
- a_bit = get_bit(a, a_offs);
- b_bit = get_bit(b, b_offs);
- if ((cmp = (a_bit-b_bit)) != 0) {
- return cmp;
- }
- size--;
- b_offs++;
- if (b_offs == 8) {
- b_offs = 0;
- b = *b_ptr++;
- }
- a_offs++;
- if (a_offs == 8) {
- a_offs = 0;
- a = *a_ptr++;
- break;
+ if (a_offs) {
+ for (;;) {
+ a_bit = get_bit(a, a_offs);
+ b_bit = get_bit(b, b_offs);
+ if ((cmp = (a_bit-b_bit)) != 0) {
+ return cmp;
+ }
+ if (--size == 0)
+ return 0;
+
+ b_offs++;
+ if (b_offs == 8) {
+ b_offs = 0;
+ b = *b_ptr++;
+ }
+ a_offs++;
+ if (a_offs == 8) {
+ a_offs = 0;
+ a = *a_ptr++;
+ break;
+ }
}
}
/* Compare byte by byte as long as at least 8 bits remain */
- lshift = b_offs;
- rshift = 8 - lshift;
- while (size >= 8) {
- byte b_cmp = (b << lshift);
- b = *b_ptr++;
- b_cmp |= b >> rshift;
- if ((cmp = (a - b_cmp)) != 0) {
- return cmp;
- }
+ if (size >= 8) {
+ lshift = b_offs;
+ rshift = 8 - lshift;
+ for (;;) {
+ byte b_cmp = (b << lshift);
+ b = *b_ptr++;
+ b_cmp |= b >> rshift;
+ if ((cmp = (a - b_cmp)) != 0) {
+ return cmp;
+ }
+ size -= 8;
+ if (size < 8)
+ break;
+ a = *a_ptr++;
+ }
+
+ if (size == 0)
+ return 0;
a = *a_ptr++;
- size -= 8;
}
/* Compare the remaining bits bit by bit */
- while (size > 0) {
- a_bit = get_bit(a, a_offs);
- b_bit = get_bit(b, b_offs);
- if ((cmp = (a_bit-b_bit)) != 0) {
- return cmp;
- }
- a_offs++;
- if (a_offs == 8) {
- a_offs = 0;
- a = *a_ptr++;
- }
- b_offs++;
- if (b_offs == 8) {
- b_offs = 0;
- b = *b_ptr++;
- }
- size--;
+ if (size > 0) {
+ for (;;) {
+ a_bit = get_bit(a, a_offs);
+ b_bit = get_bit(b, b_offs);
+ if ((cmp = (a_bit-b_bit)) != 0) {
+ return cmp;
+ }
+ if (--size == 0)
+ return 0;
+
+ a_offs++;
+ ASSERT(a_offs < 8);
+
+ b_offs++;
+ if (b_offs == 8) {
+ b_offs = 0;
+ b = *b_ptr++;
+ }
+ }
}
return 0;
diff --git a/erts/emulator/beam/erl_db.c b/erts/emulator/beam/erl_db.c
index 98c2988323..41e64fcd4f 100644
--- a/erts/emulator/beam/erl_db.c
+++ b/erts/emulator/beam/erl_db.c
@@ -2236,7 +2236,7 @@ static BIF_RETTYPE ets_select_trap_1(BIF_ALIST_1)
CHECK_TABLES();
tptr = tuple_val(a1);
- ASSERT(arityval(*tptr) >= 1)
+ ASSERT(arityval(*tptr) >= 1);
if ((tb = db_get_table(p, tptr[1], DB_READ, kind)) == NULL) {
BIF_ERROR(p, BADARG);
@@ -2403,7 +2403,7 @@ static BIF_RETTYPE ets_select_count_1(BIF_ALIST_1)
CHECK_TABLES();
tptr = tuple_val(a1);
- ASSERT(arityval(*tptr) >= 1)
+ ASSERT(arityval(*tptr) >= 1);
if ((tb = db_get_table(p, tptr[1], DB_READ, kind)) == NULL) {
BIF_ERROR(p, BADARG);
}
@@ -3811,6 +3811,13 @@ erts_db_foreach_offheap(DbTable *tb,
tb->common.meth->db_foreach_offheap(tb, func, arg);
}
+/* retrieve max number of ets tables */
+Uint
+erts_db_get_max_tabs()
+{
+ return db_max_tabs;
+}
+
/*
* For testing of meta tables only.
*
diff --git a/erts/emulator/beam/erl_db.h b/erts/emulator/beam/erl_db.h
index 6b62e10eb7..5b4681fc90 100644
--- a/erts/emulator/beam/erl_db.h
+++ b/erts/emulator/beam/erl_db.h
@@ -79,6 +79,8 @@ extern erts_smp_atomic_t erts_ets_misc_mem_size;
Eterm erts_ets_colliding_names(Process*, Eterm name, Uint cnt);
+Uint erts_db_get_max_tabs(void);
+
#endif
#if defined(ERTS_WANT_DB_INTERNAL__) && !defined(ERTS_HAVE_DB_INTERNAL__)
diff --git a/erts/emulator/beam/erl_db_hash.c b/erts/emulator/beam/erl_db_hash.c
index 2fea4671e1..06dac8f161 100644
--- a/erts/emulator/beam/erl_db_hash.c
+++ b/erts/emulator/beam/erl_db_hash.c
@@ -2106,7 +2106,7 @@ static void db_print_hash(int to, void *to_arg, int show, DbTable *tbl)
DbTableHash *tb = &tbl->hash;
int i;
- erts_print(to, to_arg, "Buckets: %d \n", NACTIVE(tb));
+ erts_print(to, to_arg, "Buckets: %d\n", NACTIVE(tb));
if (show) {
for (i = 0; i < NACTIVE(tb); i++) {
diff --git a/erts/emulator/beam/erl_db_util.h b/erts/emulator/beam/erl_db_util.h
index 90b79e6044..328b19dfc9 100644
--- a/erts/emulator/beam/erl_db_util.h
+++ b/erts/emulator/beam/erl_db_util.h
@@ -457,7 +457,7 @@ int erts_db_is_compiled_ms(Eterm term);
&& ERTS_MAGIC_BIN_DESTRUCTOR((BP)) == erts_db_match_prog_destructor)
#define Binary2MatchProg(BP) \
- (ASSERT_EXPR(IsMatchProgBinary((BP))), \
+ (ASSERT(IsMatchProgBinary((BP))), \
((MatchProg *) ERTS_MAGIC_BIN_DATA((BP))))
/*
** Debugging
diff --git a/erts/emulator/beam/erl_driver.h b/erts/emulator/beam/erl_driver.h
index b68fd46fcc..5cffae92be 100644
--- a/erts/emulator/beam/erl_driver.h
+++ b/erts/emulator/beam/erl_driver.h
@@ -365,17 +365,23 @@ typedef struct erl_drv_entry {
* It must initialize a ErlDrvEntry structure and return a pointer to it.
*/
+#ifdef STATIC_ERLANG_DRIVER
+# define ERLANG_DRIVER_NAME(NAME) NAME ## _driver_init
+#else
+# define ERLANG_DRIVER_NAME(NAME) driver_init
+#endif
+
/* For windows dynamic drivers */
#ifndef ERL_DRIVER_TYPES_ONLY
#if defined(__WIN32__)
# define DRIVER_INIT(DRIVER_NAME) \
- __declspec(dllexport) ErlDrvEntry* driver_init(void); \
- __declspec(dllexport) ErlDrvEntry* driver_init(void)
+ __declspec(dllexport) ErlDrvEntry* ERLANG_DRIVER_NAME(DRIVER_NAME)(void); \
+ __declspec(dllexport) ErlDrvEntry* ERLANG_DRIVER_NAME(DRIVER_NAME)(void)
#else
# define DRIVER_INIT(DRIVER_NAME) \
- ErlDrvEntry* driver_init(void); \
- ErlDrvEntry* driver_init(void)
+ ErlDrvEntry* ERLANG_DRIVER_NAME(DRIVER_NAME)(void); \
+ ErlDrvEntry* ERLANG_DRIVER_NAME(DRIVER_NAME)(void)
#endif
#define ERL_DRV_BUSY_MSGQ_DISABLED (~((ErlDrvSizeT) 0))
diff --git a/erts/emulator/beam/erl_gc.c b/erts/emulator/beam/erl_gc.c
index da254286c4..c5585d39e8 100644
--- a/erts/emulator/beam/erl_gc.c
+++ b/erts/emulator/beam/erl_gc.c
@@ -2781,7 +2781,7 @@ erts_check_off_heap2(Process *p, Eterm *htop)
refc = erts_refc_read(&u.ext->node->refc, 1);
break;
default:
- ASSERT(!!"erts_check_off_heap2: Invalid thing_word");
+ ASSERT(!"erts_check_off_heap2: Invalid thing_word");
}
ERTS_CHK_OFFHEAP_ASSERT(refc >= 1);
#ifdef ERTS_OFFHEAP_DEBUG_CHK_CIRCULAR_LIST
diff --git a/erts/emulator/beam/erl_lock_check.c b/erts/emulator/beam/erl_lock_check.c
index 2114d0c001..0dd83fa6ed 100644
--- a/erts/emulator/beam/erl_lock_check.c
+++ b/erts/emulator/beam/erl_lock_check.c
@@ -132,6 +132,7 @@ static erts_lc_lock_order_t erts_lock_order[] = {
#endif /* __WIN32__ */
{ "alcu_init_atoms", NULL },
{ "mseg_init_atoms", NULL },
+ { "mmap_init_atoms", NULL },
{ "drv_tsd", NULL },
{ "async_enq_mtx", NULL },
#ifdef ERTS_SMP
@@ -185,7 +186,9 @@ static erts_lc_lock_order_t erts_lock_order[] = {
{ "sys_gethrtime", NULL },
#endif
#endif
- { "erts_alloc_hard_debug", NULL }
+ { "erts_alloc_hard_debug", NULL },
+ { "hard_dbg_mseg", NULL },
+ { "erts_mmap", NULL }
};
#define ERTS_LOCK_ORDER_SIZE \
diff --git a/erts/emulator/beam/erl_message.c b/erts/emulator/beam/erl_message.c
index 325d77e911..6a9030fd99 100644
--- a/erts/emulator/beam/erl_message.c
+++ b/erts/emulator/beam/erl_message.c
@@ -46,10 +46,12 @@ ERTS_SCHED_PREF_QUICK_ALLOC_IMPL(message,
+#ifdef DEBUG
static ERTS_INLINE int in_heapfrag(const Eterm* ptr, const ErlHeapFragment *bp)
{
return ((unsigned)(ptr - bp->mem) < bp->used_size);
}
+#endif
void
diff --git a/erts/emulator/beam/erl_nif.c b/erts/emulator/beam/erl_nif.c
index 48f8be8dd3..e87959f0ab 100644
--- a/erts/emulator/beam/erl_nif.c
+++ b/erts/emulator/beam/erl_nif.c
@@ -1213,7 +1213,8 @@ static void close_lib(struct erl_module_nif* lib)
lib->entry->unload(&env, lib->priv_data);
post_nif_noproc(&env);
}
- erts_sys_ddll_close(lib->handle);
+ if (!erts_is_static_nif(lib->handle))
+ erts_sys_ddll_close(lib->handle);
lib->handle = NULL;
}
@@ -1564,12 +1565,13 @@ BIF_RETTYPE load_nif_2(BIF_ALIST_2)
static const char upgrade[] = "upgrade";
char* lib_name = NULL;
void* handle = NULL;
- void* init_func;
+ void* init_func = NULL;
ErlNifEntry* entry = NULL;
ErlNifEnv env;
- int len, i, err;
+ int i, err, encoding;
Module* mod;
Eterm mod_atom;
+ const Atom* mod_atomp;
Eterm f_atom;
BeamInstr* caller;
ErtsSysDdllError errdesc = ERTS_SYS_DDLL_ERROR_INIT;
@@ -1578,18 +1580,17 @@ BIF_RETTYPE load_nif_2(BIF_ALIST_2)
struct erl_module_nif* lib = NULL;
int reload_warning = 0;
- len = list_length(BIF_ARG_1);
- if (len < 0) {
- BIF_ERROR(BIF_P, BADARG);
+ encoding = erts_get_native_filename_encoding();
+ if (encoding == ERL_FILENAME_WIN_WCHAR) {
+ /* Do not convert the lib name to utf-16le yet, do that in win32 specific code */
+ /* since lib_name is used in error messages */
+ encoding = ERL_FILENAME_UTF8;
}
-
- lib_name = (char *) erts_alloc(ERTS_ALC_T_TMP, len + 1);
-
- if (intlist_to_buf(BIF_ARG_1, lib_name, len) != len) {
- erts_free(ERTS_ALC_T_TMP, lib_name);
+ lib_name = erts_convert_filename_to_encoding(BIF_ARG_1, NULL, 0,
+ ERTS_ALC_T_TMP, 1, 0, encoding, NULL);
+ if (!lib_name) {
BIF_ERROR(BIF_P, BADARG);
}
- lib_name[len] = '\0';
if (!erts_try_seize_code_write_permission(BIF_P)) {
erts_free(ERTS_ALC_T_TMP, lib_name);
@@ -1613,13 +1614,19 @@ BIF_RETTYPE load_nif_2(BIF_ALIST_2)
mod=erts_get_module(mod_atom, erts_active_code_ix());
ASSERT(mod != NULL);
+ mod_atomp = atom_tab(atom_val(mod_atom));
+ init_func = erts_static_nif_get_nif_init((char*)mod_atomp->name, mod_atomp->len);
+ if (init_func != NULL)
+ handle = init_func;
+
if (!in_area(caller, mod->curr.code, mod->curr.code_length)) {
ASSERT(in_area(caller, mod->old.code, mod->old.code_length));
ret = load_nif_error(BIF_P, "old_code", "Calling load_nif from old "
"module '%T' not allowed", mod_atom);
}
- else if ((err=erts_sys_ddll_open2(lib_name, &handle, &errdesc)) != ERL_DE_NO_ERROR) {
+ else if (init_func == NULL &&
+ (err=erts_sys_ddll_open2(lib_name, &handle, &errdesc)) != ERL_DE_NO_ERROR) {
const char slogan[] = "Failed to load NIF library";
if (strstr(errdesc.str, lib_name) != NULL) {
ret = load_nif_error(BIF_P, "load_failed", "%s: '%s'", slogan, errdesc.str);
@@ -1628,7 +1635,8 @@ BIF_RETTYPE load_nif_2(BIF_ALIST_2)
ret = load_nif_error(BIF_P, "load_failed", "%s %s: '%s'", slogan, lib_name, errdesc.str);
}
}
- else if (erts_sys_ddll_load_nif_init(handle, &init_func, &errdesc) != ERL_DE_NO_ERROR) {
+ else if (init_func == NULL &&
+ erts_sys_ddll_load_nif_init(handle, &init_func, &errdesc) != ERL_DE_NO_ERROR) {
ret = load_nif_error(BIF_P, bad_lib, "Failed to find library init"
" function: '%s'", errdesc.str);
@@ -1784,7 +1792,7 @@ BIF_RETTYPE load_nif_2(BIF_ALIST_2)
if (lib != NULL) {
erts_free(ERTS_ALC_T_NIF, lib);
}
- if (handle != NULL) {
+ if (handle != NULL && !erts_is_static_nif(handle)) {
erts_sys_ddll_close(handle);
}
erts_sys_ddll_free_error(&errdesc);
diff --git a/erts/emulator/beam/erl_nif.h b/erts/emulator/beam/erl_nif.h
index 8006741a63..5f4dc21d5c 100644
--- a/erts/emulator/beam/erl_nif.h
+++ b/erts/emulator/beam/erl_nif.h
@@ -168,7 +168,7 @@ extern TWinDynNifCallbacks WinDynNifCallbacks;
# undef ERL_NIF_API_FUNC_DECL
#endif
-#if (defined(__WIN32__) || defined(_WIN32) || defined(_WIN32_)) && !defined(STATIC_ERLANG_DRIVER)
+#if (defined(__WIN32__) || defined(_WIN32) || defined(_WIN32_)) && !defined(STATIC_ERLANG_DRIVER) && !defined(STATIC_ERLANG_NIF)
# define ERL_NIF_API_FUNC_MACRO(NAME) (WinDynNifCallbacks.NAME)
# include "erl_nif_api_funcs.h"
/* note that we have to keep ERL_NIF_API_FUNC_MACRO defined */
@@ -180,15 +180,22 @@ extern TWinDynNifCallbacks WinDynNifCallbacks;
# undef ERL_NIF_API_FUNC_DECL
#endif
-
#if (defined(__WIN32__) || defined(_WIN32) || defined(_WIN32_))
# define ERL_NIF_INIT_GLOB TWinDynNifCallbacks WinDynNifCallbacks;
-# define ERL_NIF_INIT_DECL(MODNAME) __declspec(dllexport) ErlNifEntry* nif_init(TWinDynNifCallbacks* callbacks)
+# ifdef STATIC_ERLANG_NIF
+# define ERL_NIF_INIT_DECL(MODNAME) __declspec(dllexport) ErlNifEntry* MODNAME ## _nif_init(TWinDynNifCallbacks* callbacks)
+# else
+# define ERL_NIF_INIT_DECL(MODNAME) __declspec(dllexport) ErlNifEntry* nif_init(TWinDynNifCallbacks* callbacks)
+# endif
# define ERL_NIF_INIT_BODY memcpy(&WinDynNifCallbacks,callbacks,sizeof(TWinDynNifCallbacks))
#else
# define ERL_NIF_INIT_GLOB
# define ERL_NIF_INIT_BODY
-# define ERL_NIF_INIT_DECL(MODNAME) ErlNifEntry* nif_init(void)
+# ifdef STATIC_ERLANG_NIF
+# define ERL_NIF_INIT_DECL(MODNAME) ErlNifEntry* MODNAME ## _nif_init(void)
+# else
+# define ERL_NIF_INIT_DECL(MODNAME) ErlNifEntry* nif_init(void)
+# endif
#endif
diff --git a/erts/emulator/beam/erl_node_container_utils.h b/erts/emulator/beam/erl_node_container_utils.h
index 0f93a3a9f0..17f6b32bb1 100644
--- a/erts/emulator/beam/erl_node_container_utils.h
+++ b/erts/emulator/beam/erl_node_container_utils.h
@@ -106,7 +106,7 @@
#define dist_entry_channel_no(x) \
((x) == erts_this_dist_entry \
? ((Uint) 0) \
- : (ASSERT_EXPR(is_atom((x)->sysname)), \
+ : (ASSERT(is_atom((x)->sysname)), \
(Uint) atom_val((x)->sysname)))
#define internal_channel_no(x) ((Uint) ERST_INTERNAL_CHANNEL_NO)
#define external_channel_no(x) \
@@ -122,10 +122,10 @@ extern ErtsPTab erts_proc;
(D), \
_TAG_IMMED1_PID)
-#define internal_pid_index(PID) (ASSERT_EXPR(is_internal_pid((PID))), \
+#define internal_pid_index(PID) (ASSERT(is_internal_pid((PID))), \
erts_ptab_id2pix(&erts_proc, (PID)))
-#define internal_pid_data(PID) (ASSERT_EXPR(is_internal_pid((PID))), \
+#define internal_pid_data(PID) (ASSERT(is_internal_pid((PID))), \
erts_ptab_id2data(&erts_proc, (PID)))
#define internal_pid_number(x) _GET_PID_NUM(internal_pid_data((x)))
@@ -193,10 +193,10 @@ extern ErtsPTab erts_port;
(D), \
_TAG_IMMED1_PORT)
-#define internal_port_index(PRT) (ASSERT_EXPR(is_internal_port((PRT))), \
+#define internal_port_index(PRT) (ASSERT(is_internal_port((PRT))), \
erts_ptab_id2pix(&erts_port, (PRT)))
-#define internal_port_data(PRT) (ASSERT_EXPR(is_internal_port((PRT))), \
+#define internal_port_data(PRT) (ASSERT(is_internal_port((PRT))), \
erts_ptab_id2data(&erts_port, (PRT)))
#define internal_port_number(x) _GET_PORT_NUM(internal_port_data((x)))
diff --git a/erts/emulator/beam/erl_port_task.h b/erts/emulator/beam/erl_port_task.h
index e4d964146e..123253a057 100644
--- a/erts/emulator/beam/erl_port_task.h
+++ b/erts/emulator/beam/erl_port_task.h
@@ -77,6 +77,7 @@ extern erts_smp_atomic_t erts_port_task_outstanding_io_tasks;
#define ERTS_PTS_FLG_HAVE_NS_TASKS (((erts_aint32_t) 1) << 8)
#define ERTS_PTS_FLG_PARALLELISM (((erts_aint32_t) 1) << 9)
#define ERTS_PTS_FLG_FORCE_SCHED (((erts_aint32_t) 1) << 10)
+#define ERTS_PTS_FLG_EXITING (((erts_aint32_t) 1) << 11)
#define ERTS_PTS_FLGS_BUSY \
(ERTS_PTS_FLG_BUSY_PORT | ERTS_PTS_FLG_BUSY_PORT_Q)
@@ -86,7 +87,8 @@ extern erts_smp_atomic_t erts_port_task_outstanding_io_tasks;
| ERTS_PTS_FLG_HAVE_BUSY_TASKS \
| ERTS_PTS_FLG_HAVE_TASKS \
| ERTS_PTS_FLG_EXEC \
- | ERTS_PTS_FLG_FORCE_SCHED)
+ | ERTS_PTS_FLG_FORCE_SCHED \
+ | ERTS_PTS_FLG_EXITING)
#define ERTS_PORT_TASK_DEFAULT_BUSY_PORT_Q_HIGH 8192
#define ERTS_PORT_TASK_DEFAULT_BUSY_PORT_Q_LOW 4096
@@ -135,6 +137,7 @@ ERTS_GLB_INLINE void erts_port_task_fini_sched(ErtsPortTaskSched *ptsp);
ERTS_GLB_INLINE void erts_port_task_sched_lock(ErtsPortTaskSched *ptsp);
ERTS_GLB_INLINE void erts_port_task_sched_unlock(ErtsPortTaskSched *ptsp);
ERTS_GLB_INLINE int erts_port_task_sched_lock_is_locked(ErtsPortTaskSched *ptsp);
+ERTS_GLB_INLINE void erts_port_task_sched_enter_exiting_state(ErtsPortTaskSched *ptsp);
#ifdef ERTS_INCLUDE_SCHEDULER_INTERNALS
ERTS_GLB_INLINE int erts_port_task_have_outstanding_io_tasks(void);
@@ -225,6 +228,12 @@ erts_port_task_fini_sched(ErtsPortTaskSched *ptsp)
#endif
}
+ERTS_GLB_INLINE void
+erts_port_task_sched_enter_exiting_state(ErtsPortTaskSched *ptsp)
+{
+ erts_smp_atomic32_read_bor_nob(&ptsp->flags, ERTS_PTS_FLG_EXITING);
+}
+
#ifdef ERTS_INCLUDE_SCHEDULER_INTERNALS
ERTS_GLB_INLINE int
diff --git a/erts/emulator/beam/erl_process.c b/erts/emulator/beam/erl_process.c
index 13b18e9e0e..0a41fb596d 100644
--- a/erts/emulator/beam/erl_process.c
+++ b/erts/emulator/beam/erl_process.c
@@ -328,7 +328,7 @@ ERTS_SCHED_PREF_QUICK_ALLOC_IMPL(proclist,
ERTS_ALC_T_PROC_LIST)
#define ERTS_SCHED_SLEEP_INFO_IX(IX) \
- (ASSERT_EXPR(-1 <= ((int) (IX)) \
+ (ASSERT(-1 <= ((int) (IX)) \
&& ((int) (IX)) < ((int) erts_no_schedulers)), \
&aligned_sched_sleep_info[(IX)].ssi)
@@ -8636,6 +8636,7 @@ alloc_process(ErtsRunQueue *rq, erts_aint32_t state)
p->approx_started = erts_get_approx_time();
p->rcount = 0;
+ p->heap = NULL;
ASSERT(p == (Process *) (erts_ptab_pix2intptr_nob(
@@ -8749,7 +8750,6 @@ erl_create_process(Process* parent, /* Parent of process (default group leader).
hipe_init_process_smp(&p->hipe_smp);
#endif
#endif
-
p->heap = (Eterm *) ERTS_HEAP_ALLOC(ERTS_ALC_T_HEAP, sizeof(Eterm)*sz);
p->old_hend = p->old_htop = p->old_heap = NULL;
p->high_water = p->heap;
diff --git a/erts/emulator/beam/erl_process.h b/erts/emulator/beam/erl_process.h
index 0b8d2976ed..043621125c 100644
--- a/erts/emulator/beam/erl_process.h
+++ b/erts/emulator/beam/erl_process.h
@@ -1188,10 +1188,10 @@ extern struct erts_system_profile_flags_t erts_system_profile_flags;
} while (0)
#define ERTS_RUNQ_IX(IX) \
- (ASSERT_EXPR(0 <= (IX) && (IX) < erts_no_run_queues), \
+ (ASSERT(0 <= (IX) && (IX) < erts_no_run_queues), \
&erts_aligned_run_queues[(IX)].runq)
#define ERTS_SCHEDULER_IX(IX) \
- (ASSERT_EXPR(0 <= (IX) && (IX) < erts_no_schedulers), \
+ (ASSERT(0 <= (IX) && (IX) < erts_no_schedulers), \
&erts_aligned_scheduler_data[(IX)].esd)
void erts_pre_init_process(void);
diff --git a/erts/emulator/beam/erl_process_dump.c b/erts/emulator/beam/erl_process_dump.c
index 6cd0d23b97..2f3cf23b00 100644
--- a/erts/emulator/beam/erl_process_dump.c
+++ b/erts/emulator/beam/erl_process_dump.c
@@ -34,8 +34,8 @@
#define ERTS_WANT_EXTERNAL_TAGS
#include "external.h"
-#define WORD_FMT "%X"
-#define ADDR_FMT "%X"
+#define PTR_FMT "%bpX"
+#define ETERM_FMT "%beX"
#define OUR_NIL _make_header(0,_TAG_HEADER_FLOAT)
@@ -210,9 +210,9 @@ static void
dump_element(int to, void *to_arg, Eterm x)
{
if (is_list(x)) {
- erts_print(to, to_arg, "H" WORD_FMT, list_val(x));
+ erts_print(to, to_arg, "H" PTR_FMT, list_val(x));
} else if (is_boxed(x)) {
- erts_print(to, to_arg, "H" WORD_FMT, boxed_val(x));
+ erts_print(to, to_arg, "H" PTR_FMT, boxed_val(x));
} else if (is_immed(x)) {
if (is_atom(x)) {
unsigned char* s = atom_tab(atom_val(x))->name;
@@ -311,7 +311,7 @@ heap_dump(int to, void *to_arg, Eterm x)
} else if (is_list(x)) {
ptr = list_val(x);
if (ptr[0] != OUR_NIL) {
- erts_print(to, to_arg, ADDR_FMT ":l", ptr);
+ erts_print(to, to_arg, PTR_FMT ":l", ptr);
dump_element(to, to_arg, ptr[0]);
erts_putc(to, to_arg, '|');
dump_element(to, to_arg, ptr[1]);
@@ -330,12 +330,12 @@ heap_dump(int to, void *to_arg, Eterm x)
ptr = boxed_val(x);
hdr = *ptr;
if (hdr != OUR_NIL) { /* If not visited */
- erts_print(to, to_arg, ADDR_FMT ":", ptr);
+ erts_print(to, to_arg, PTR_FMT ":", ptr);
if (is_arity_value(hdr)) {
Uint i;
Uint arity = arityval(hdr);
- erts_print(to, to_arg, "t" WORD_FMT ":", arity);
+ erts_print(to, to_arg, "t" ETERM_FMT ":", arity);
for (i = 1; i <= arity; i++) {
dump_element(to, to_arg, ptr[i]);
if (is_immed(ptr[i])) {
@@ -388,21 +388,43 @@ heap_dump(int to, void *to_arg, Eterm x)
val->flags = (UWord) all_binaries;
all_binaries = val;
}
- erts_print(to, to_arg, "Yc%X:%X:%X", val,
+ erts_print(to, to_arg,
+ "Yc" PTR_FMT ":" PTR_FMT ":" PTR_FMT,
+ val,
pb->bytes - (byte *)val->orig_bytes,
size);
} else if (tag == SUB_BINARY_SUBTAG) {
ErlSubBin* Sb = (ErlSubBin *) binary_val(x);
- Eterm* real_bin = binary_val(Sb->orig);
+ Eterm* real_bin;
void* val;
+ /*
+ * Must use boxed_val() here, because the original
+ * binary may have been visited and have had its
+ * header word changed to OUR_NIL (in which case
+ * binary_val() will cause an assertion failure in
+ * the DEBUG emulator).
+ */
+
+ real_bin = boxed_val(Sb->orig);
+
if (thing_subtag(*real_bin) == REFC_BINARY_SUBTAG) {
+ /*
+ * Unvisited REFC_BINARY: Point directly to
+ * the binary.
+ */
ProcBin* pb = (ProcBin *) real_bin;
val = pb->val;
- } else { /* Heap binary */
+ } else {
+ /*
+ * Heap binary or visited REFC binary: Point
+ * to heap binary or ProcBin on the heap.
+ */
val = real_bin;
}
- erts_print(to, to_arg, "Ys%X:%X:%X", val, Sb->offs, size);
+ erts_print(to, to_arg,
+ "Ys" PTR_FMT ":" PTR_FMT ":" PTR_FMT,
+ val, Sb->offs, size);
}
erts_putc(to, to_arg, '\n');
*ptr = OUR_NIL;
@@ -438,7 +460,7 @@ dump_binaries(int to, void *to_arg, Binary* current)
long size = current->orig_size;
byte* bytes = (byte*) current->orig_bytes;
- erts_print(to, to_arg, "=binary:%X\n", current);
+ erts_print(to, to_arg, "=binary:" PTR_FMT "\n", current);
erts_print(to, to_arg, "%X:", size);
for (i = 0; i < size; i++) {
erts_print(to, to_arg, "%02X", bytes[i]);
diff --git a/erts/emulator/beam/erl_trace.c b/erts/emulator/beam/erl_trace.c
index fa015ee4b9..ff7fdfcfca 100644
--- a/erts/emulator/beam/erl_trace.c
+++ b/erts/emulator/beam/erl_trace.c
@@ -2184,7 +2184,7 @@ trace_gc(Process *p, Eterm what)
AM_bin_old_vheap_block_size
};
- Uint values[] = {
+ UWord values[] = {
OLD_HEAP(p) ? OLD_HEND(p) - OLD_HEAP(p) : 0,
HEAP_SIZE(p),
MBUF_SIZE(p),
@@ -2198,7 +2198,7 @@ trace_gc(Process *p, Eterm what)
BIN_OLD_VHEAP_SZ(p)
};
#define LOCAL_HEAP_SIZE \
- (sizeof(values)/sizeof(Eterm)) * \
+ (sizeof(values)/sizeof(*values)) * \
(2/*cons*/ + 3/*2-tuple*/ + BIG_UINT_HEAP_SIZE) + \
5/*4-tuple */ + TS_HEAP_WORDS
DeclareTmpHeap(local_heap,LOCAL_HEAP_SIZE,p);
@@ -2206,7 +2206,7 @@ trace_gc(Process *p, Eterm what)
Eterm* limit;
#endif
- ASSERT(sizeof(values)/sizeof(Uint) == sizeof(tags)/sizeof(Eterm));
+ ASSERT(sizeof(values)/sizeof(*values) == sizeof(tags)/sizeof(Eterm));
UseTmpHeap(LOCAL_HEAP_SIZE,p);
@@ -2214,9 +2214,9 @@ trace_gc(Process *p, Eterm what)
hp = local_heap;
#ifdef DEBUG
size = 0;
- (void) erts_bld_atom_uint_2tup_list(NULL,
+ (void) erts_bld_atom_uword_2tup_list(NULL,
&size,
- sizeof(values)/sizeof(Uint),
+ sizeof(values)/sizeof(*values),
tags,
values);
size += 5/*4-tuple*/ + TS_SIZE(p);
@@ -2229,9 +2229,9 @@ trace_gc(Process *p, Eterm what)
ERTS_TRACE_FLAGS(p));
size = 0;
- (void) erts_bld_atom_uint_2tup_list(NULL,
+ (void) erts_bld_atom_uword_2tup_list(NULL,
&size,
- sizeof(values)/sizeof(Uint),
+ sizeof(values)/sizeof(*values),
tags,
values);
size += 5/*4-tuple*/ + TS_SIZE(p);
@@ -2244,9 +2244,9 @@ trace_gc(Process *p, Eterm what)
ASSERT(size <= LOCAL_HEAP_SIZE);
#endif
- msg = erts_bld_atom_uint_2tup_list(&hp,
+ msg = erts_bld_atom_uword_2tup_list(&hp,
NULL,
- sizeof(values)/sizeof(Uint),
+ sizeof(values)/sizeof(*values),
tags,
values);
@@ -2415,7 +2415,7 @@ monitor_long_gc(Process *p, Uint time) {
am_old_heap_size,
am_heap_size
};
- Eterm values[] = {
+ UWord values[] = {
time,
OLD_HEAP(p) ? OLD_HEND(p) - OLD_HEAP(p) : 0,
HEAP_SIZE(p),
@@ -2436,9 +2436,9 @@ monitor_long_gc(Process *p, Uint time) {
#endif
hsz = 0;
- (void) erts_bld_atom_uint_2tup_list(NULL,
+ (void) erts_bld_atom_uword_2tup_list(NULL,
&hsz,
- sizeof(values)/sizeof(Uint),
+ sizeof(values)/sizeof(*values),
tags,
values);
hsz += 5 /* 4-tuple */;
@@ -2449,9 +2449,9 @@ monitor_long_gc(Process *p, Uint time) {
hp_end = hp + hsz;
#endif
- list = erts_bld_atom_uint_2tup_list(&hp,
+ list = erts_bld_atom_uword_2tup_list(&hp,
NULL,
- sizeof(values)/sizeof(Uint),
+ sizeof(values)/sizeof(*values),
tags,
values);
msg = TUPLE4(hp, am_monitor, p->common.id, am_long_gc, list);
@@ -2489,7 +2489,7 @@ monitor_large_heap(Process *p) {
am_old_heap_size,
am_heap_size
};
- Uint values[] = {
+ UWord values[] = {
OLD_HEAP(p) ? OLD_HEND(p) - OLD_HEAP(p) : 0,
HEAP_SIZE(p),
MBUF_SIZE(p),
@@ -2511,9 +2511,9 @@ monitor_large_heap(Process *p) {
#endif
hsz = 0;
- (void) erts_bld_atom_uint_2tup_list(NULL,
+ (void) erts_bld_atom_uword_2tup_list(NULL,
&hsz,
- sizeof(values)/sizeof(Uint),
+ sizeof(values)/sizeof(*values),
tags,
values);
hsz += 5 /* 4-tuple */;
@@ -2524,9 +2524,9 @@ monitor_large_heap(Process *p) {
hp_end = hp + hsz;
#endif
- list = erts_bld_atom_uint_2tup_list(&hp,
+ list = erts_bld_atom_uword_2tup_list(&hp,
NULL,
- sizeof(values)/sizeof(Uint),
+ sizeof(values)/sizeof(*values),
tags,
values);
msg = TUPLE4(hp, am_monitor, p->common.id, am_large_heap, list);
diff --git a/erts/emulator/beam/erl_unicode.c b/erts/emulator/beam/erl_unicode.c
index e00440b905..7e3c6681d9 100644
--- a/erts/emulator/beam/erl_unicode.c
+++ b/erts/emulator/beam/erl_unicode.c
@@ -1476,6 +1476,9 @@ static Eterm do_utf8_to_list_normalize(Process *p, Uint num, byte *bytes, Uint s
Uint16 savepoints[4];
int numpoints = 0;
+ if (num == 0)
+ return NIL;
+
ASSERT(num > 0);
hp = HAlloc(p,num * 2); /* May be to much */
@@ -1981,9 +1984,19 @@ BIF_RETTYPE binary_to_existing_atom_2(BIF_ALIST_2)
* string routines, that will certainly fail on some OS.
*/
-char *erts_convert_filename_to_native(Eterm name, char *statbuf, size_t statbuf_size, ErtsAlcType_t alloc_type, int allow_empty, int allow_atom, Sint *used)
+char *erts_convert_filename_to_native(Eterm name, char *statbuf, size_t statbuf_size,
+ ErtsAlcType_t alloc_type, int allow_empty,
+ int allow_atom, Sint *used)
{
int encoding = erts_get_native_filename_encoding();
+ return erts_convert_filename_to_encoding(name, statbuf, statbuf_size, alloc_type,
+ allow_empty, allow_atom, encoding, used);
+}
+
+char *erts_convert_filename_to_encoding(Eterm name, char *statbuf, size_t statbuf_size,
+ ErtsAlcType_t alloc_type, int allow_empty,
+ int allow_atom, int encoding, Sint *used)
+{
char* name_buf = NULL;
if ((allow_atom && is_atom(name)) ||
@@ -2013,11 +2026,11 @@ char *erts_convert_filename_to_native(Eterm name, char *statbuf, size_t statbuf_
} else if (is_binary(name)) {
byte *temp_alloc = NULL;
byte *bytes;
- byte *err_pos;
- Uint size,num_chars;
+ Uint size;
size = binary_size(name);
bytes = erts_get_aligned_binary_bytes(name, &temp_alloc);
+
if (encoding != ERL_FILENAME_WIN_WCHAR) {
/*Add 0 termination only*/
if (used)
@@ -2029,36 +2042,11 @@ char *erts_convert_filename_to_native(Eterm name, char *statbuf, size_t statbuf_
}
memcpy(name_buf,bytes,size);
name_buf[size]=0;
- } else if (erts_analyze_utf8(bytes,size,&err_pos,&num_chars,NULL) != ERTS_UTF8_OK ||
- erts_get_user_requested_filename_encoding() == ERL_FILENAME_LATIN1) {
- byte *p;
- /* What to do now? Maybe latin1, so just take byte for byte instead */
- if (used)
- *used = (Sint) (size+1)*2;
- if ((size+1)*2 > statbuf_size) {
- name_buf = (char *) erts_alloc(alloc_type, (size+1)*2);
- } else {
- name_buf = statbuf;
- }
- p = (byte *) name_buf;
- while (size--) {
- *p++ = *bytes++;
- *p++ = 0;
- }
- *p++ = 0;
- *p++ = 0;
- } else { /* WIN_WCHAR and valid UTF8 */
- if (used)
- *used = (Sint) (num_chars+1)*2;
- if ((num_chars+1)*2 > statbuf_size) {
- name_buf = (char *) erts_alloc(alloc_type, (num_chars+1)*2);
- } else {
- name_buf = statbuf;
- }
- erts_copy_utf8_to_utf16_little((byte *) name_buf, bytes, num_chars);
- name_buf[num_chars*2] = 0;
- name_buf[num_chars*2+1] = 0;
- }
+ } else {
+ name_buf = erts_convert_filename_to_wchar(bytes, size,
+ statbuf, statbuf_size,
+ alloc_type, used, 0);
+ }
erts_free_aligned_binary_bytes(temp_alloc);
} else {
return NULL;
@@ -2066,6 +2054,50 @@ char *erts_convert_filename_to_native(Eterm name, char *statbuf, size_t statbuf_
return name_buf;
}
+char* erts_convert_filename_to_wchar(byte* bytes, Uint size,
+ char *statbuf, size_t statbuf_size,
+ ErtsAlcType_t alloc_type, Sint* used,
+ Uint extra_wchars)
+{
+ byte *err_pos;
+ Uint num_chars;
+ char* name_buf = NULL;
+ Sint need;
+ char *p;
+
+ if (erts_analyze_utf8(bytes,size,&err_pos,&num_chars,NULL) != ERTS_UTF8_OK ||
+ erts_get_user_requested_filename_encoding() == ERL_FILENAME_LATIN1) {
+
+ /* What to do now? Maybe latin1, so just take byte for byte instead */
+ need = (Sint) (size + extra_wchars + 1) * 2;
+ if (need > statbuf_size) {
+ name_buf = (char *) erts_alloc(alloc_type, need);
+ } else {
+ name_buf = statbuf;
+ }
+ p = name_buf;
+ while (size--) {
+ *p++ = *bytes++;
+ *p++ = 0;
+ }
+ } else { /* WIN_WCHAR and valid UTF8 */
+ need = (Sint) (num_chars + extra_wchars + 1) * 2;
+ if (need > statbuf_size) {
+ name_buf = (char *) erts_alloc(alloc_type, need);
+ } else {
+ name_buf = statbuf;
+ }
+ erts_copy_utf8_to_utf16_little((byte *) name_buf, bytes, num_chars);
+ p = name_buf + num_chars*2;
+ }
+ *p++ = 0;
+ *p++ = 0;
+ if (used)
+ *used = p - name_buf;
+ return name_buf;
+}
+
+
static int filename_len_16bit(byte *str)
{
byte *p = str;
@@ -2145,16 +2177,31 @@ Sint erts_native_filename_need(Eterm ioterm, int encoding)
ap = atom_tab(atom_val(ioterm));
switch (encoding) {
case ERL_FILENAME_LATIN1:
- need = ap->len;
+ need = ap->latin1_chars; /* May be -1 */
break;
case ERL_FILENAME_UTF8_MAC:
case ERL_FILENAME_UTF8:
- for (i = 0; i < ap->len; i++) {
- need += (ap->name[i] >= 0x80) ? 2 : 1;
- }
+ need = ap->len;
break;
case ERL_FILENAME_WIN_WCHAR:
- need = 2*(ap->len);
+ if (ap->latin1_chars >= 0) {
+ need = 2* ap->latin1_chars;
+ }
+ else {
+ for (i = 0; i < ap->len; ) {
+ if (ap->name[i] < 0x80) {
+ i++;
+ } else if (ap->name[i] < 0xE0) {
+ i += 2;
+ } else if (ap->name[i] < 0xF0) {
+ i += 3;
+ } else {
+ need = -1;
+ break;
+ }
+ need += 2;
+ }
+ }
break;
default:
need = -1;
@@ -2284,26 +2331,36 @@ void erts_native_filename_put(Eterm ioterm, int encoding, byte *p)
switch (encoding) {
case ERL_FILENAME_LATIN1:
for (i = 0; i < ap->len; i++) {
- *p++ = ap->name[i];
- }
- break;
- case ERL_FILENAME_UTF8_MAC:
- case ERL_FILENAME_UTF8:
- for (i = 0; i < ap->len; i++) {
- if(ap->name[i] < 0x80) {
+ if (ap->name[i] < 0x80) {
*p++ = ap->name[i];
} else {
- *p++ = (((ap->name[i]) >> 6) | ((byte) 0xC0));
- *p++ = (((ap->name[i]) & 0x3F) | ((byte) 0x80));
+ ASSERT(ap->name[i] < 0xC4);
+ *p++ = ((ap->name[i] & 3) << 6) | (ap->name[i+1] & 0x3F);
+ i++;
}
}
break;
+ case ERL_FILENAME_UTF8_MAC:
+ case ERL_FILENAME_UTF8:
+ sys_memcpy(p, ap->name, ap->len);
+ break;
case ERL_FILENAME_WIN_WCHAR:
for (i = 0; i < ap->len; i++) {
/* Little endian */
- *p++ = ap->name[i];
- *p++ = 0;
- }
+ if (ap->name[i] < 0x80) {
+ *p++ = ap->name[i];
+ *p++ = 0;
+ } else if (ap->name[i] < 0xE0) {
+ *p++ = ((ap->name[i] & 3) << 6) | (ap->name[i+1] & 0x3F);
+ *p++ = ((ap->name[i] & 0x1C) >> 2);
+ i++;
+ } else {
+ ASSERT(ap->name[i] < 0xF0);
+ *p++ = ((ap->name[i+1] & 3) << 6) | (ap->name[i+2] & 0x3C);
+ *p++ = ((ap->name[i] & 0xF) << 4) | ((ap->name[i+1] & 0x3C) >> 2);
+ i += 2;
+ }
+ }
break;
default:
ASSERT(0);
diff --git a/erts/emulator/beam/erl_utils.h b/erts/emulator/beam/erl_utils.h
index 80d29d554a..292d135946 100644
--- a/erts/emulator/beam/erl_utils.h
+++ b/erts/emulator/beam/erl_utils.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2012. All Rights Reserved.
+ * Copyright Ericsson AB 2012-2013. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -168,6 +168,10 @@ Eterm erts_bld_uint64(Uint **hpp, Uint *szp, Uint64 ui64);
Eterm erts_bld_sint64(Uint **hpp, Uint *szp, Sint64 si64);
Eterm erts_bld_cons(Uint **hpp, Uint *szp, Eterm car, Eterm cdr);
Eterm erts_bld_tuple(Uint **hpp, Uint *szp, Uint arity, ...);
+#define erts_bld_tuple2(H,S,E1,E2) erts_bld_tuple(H,S,2,E1,E2)
+#define erts_bld_tuple3(H,S,E1,E2,E3) erts_bld_tuple(H,S,3,E1,E2,E3)
+#define erts_bld_tuple4(H,S,E1,E2,E3,E4) erts_bld_tuple(H,S,4,E1,E2,E3,E4)
+#define erts_bld_tuple5(H,S,E1,E2,E3,E4,E5) erts_bld_tuple(H,S,5,E1,E2,E3,E4,E5)
Eterm erts_bld_tuplev(Uint **hpp, Uint *szp, Uint arity, Eterm terms[]);
Eterm erts_bld_string_n(Uint **hpp, Uint *szp, const char *str, Sint len);
#define erts_bld_string(hpp,szp,str) erts_bld_string_n(hpp,szp,str,strlen(str))
@@ -175,8 +179,8 @@ Eterm erts_bld_list(Uint **hpp, Uint *szp, Sint length, Eterm terms[]);
Eterm erts_bld_2tup_list(Uint **hpp, Uint *szp,
Sint length, Eterm terms1[], Uint terms2[]);
Eterm
-erts_bld_atom_uint_2tup_list(Uint **hpp, Uint *szp,
- Sint length, Eterm atoms[], Uint uints[]);
+erts_bld_atom_uword_2tup_list(Uint **hpp, Uint *szp,
+ Sint length, Eterm atoms[], UWord uints[]);
Eterm
erts_bld_atom_2uint_3tup_list(Uint **hpp, Uint *szp, Sint length,
Eterm atoms[], Uint uints1[], Uint uints2[]);
diff --git a/erts/emulator/beam/erl_vm.h b/erts/emulator/beam/erl_vm.h
index c962955de9..337422eead 100644
--- a/erts/emulator/beam/erl_vm.h
+++ b/erts/emulator/beam/erl_vm.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1996-2012. All Rights Reserved.
+ * Copyright Ericsson AB 1996-2013. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -80,7 +80,7 @@
# ifdef CHECK_FOR_HOLES
# define INIT_HEAP_MEM(p,sz) erts_set_hole_marker(HEAP_TOP(p), (sz))
# else
-# define INIT_HEAP_MEM(p,sz) memset(HEAP_TOP(p),DEBUG_BAD_BYTE,(sz)*sizeof(Eterm*))
+# define INIT_HEAP_MEM(p,sz) memset(HEAP_TOP(p),0x01,(sz)*sizeof(Eterm*))
# endif
#else
# define INIT_HEAP_MEM(p,sz) ((void)0)
@@ -98,7 +98,7 @@
* failing that, in a heap fragment.
*/
#define HAllocX(p, sz, xtra) \
- (ASSERT_EXPR((sz) >= 0), \
+ (ASSERT((sz) >= 0), \
ErtsHAllocLockCheck(p), \
(IS_FORCE_HEAP_FRAGS || (((HEAP_LIMIT(p) - HEAP_TOP(p)) < (sz))) \
? erts_heap_alloc((p),(sz),(xtra)) \
@@ -135,14 +135,14 @@
*/
#ifdef CHECK_FOR_HOLES
# define HeapOnlyAlloc(p, sz) \
- (ASSERT_EXPR((sz) >= 0), \
- (ASSERT_EXPR(((HEAP_LIMIT(p) - HEAP_TOP(p)) >= (sz))), \
+ (ASSERT((sz) >= 0), \
+ (ASSERT(((HEAP_LIMIT(p) - HEAP_TOP(p)) >= (sz))), \
(erts_set_hole_marker(HEAP_TOP(p), (sz)), \
(HEAP_TOP(p) = HEAP_TOP(p) + (sz), HEAP_TOP(p) - (sz)))))
#else
# define HeapOnlyAlloc(p, sz) \
- (ASSERT_EXPR((sz) >= 0), \
- (ASSERT_EXPR(((HEAP_LIMIT(p) - HEAP_TOP(p)) >= (sz))), \
+ (ASSERT((sz) >= 0), \
+ (ASSERT(((HEAP_LIMIT(p) - HEAP_TOP(p)) >= (sz))), \
(HEAP_TOP(p) = HEAP_TOP(p) + (sz), HEAP_TOP(p) - (sz))))
#endif
diff --git a/erts/emulator/beam/external.c b/erts/emulator/beam/external.c
index 1c88765381..22b0a02937 100644
--- a/erts/emulator/beam/external.c
+++ b/erts/emulator/beam/external.c
@@ -2970,7 +2970,7 @@ dec_term_atom_common:
n = get_int32(ep);
ep += 4;
- if (n <= ERL_ONHEAP_BIN_LIMIT) {
+ if ((unsigned)n <= ERL_ONHEAP_BIN_LIMIT) {
ErlHeapBin* hb = (ErlHeapBin *) hp;
hb->thing_word = header_heap_bin(n);
@@ -3007,8 +3007,10 @@ dec_term_atom_common:
n = get_int32(ep);
bitsize = ep[4];
- ep += 5;
- if (n <= ERL_ONHEAP_BIN_LIMIT) {
+ if (((bitsize==0) != (n==0)) || bitsize > 8)
+ goto error;
+ ep += 5;
+ if ((unsigned)n <= ERL_ONHEAP_BIN_LIMIT) {
ErlHeapBin* hb = (ErlHeapBin *) hp;
hb->thing_word = header_heap_bin(n);
@@ -3035,10 +3037,10 @@ dec_term_atom_common:
hp += PROC_BIN_SIZE;
}
ep += n;
- if (bitsize == 0) {
+ if (bitsize == 8 || n == 0) {
*objp = bin;
} else {
- sb = (ErlSubBin *) hp;
+ sb = (ErlSubBin *)hp;
sb->thing_word = HEADER_SUB_BIN;
sb->orig = bin;
sb->size = n - 1;
diff --git a/erts/emulator/beam/external.h b/erts/emulator/beam/external.h
index e37d47919e..ff29e84972 100644
--- a/erts/emulator/beam/external.h
+++ b/erts/emulator/beam/external.h
@@ -138,8 +138,8 @@ typedef struct {
#define ERTS_DIST_EXT_SIZE(EDEP) \
(sizeof(ErtsDistExternal) \
- (((EDEP)->flags & ERTS_DIST_EXT_ATOM_TRANS_TAB) \
- ? (ASSERT_EXPR(0 <= (EDEP)->attab.size \
- && (EDEP)->attab.size <= ERTS_ATOM_CACHE_SIZE), \
+ ? (ASSERT(0 <= (EDEP)->attab.size \
+ && (EDEP)->attab.size <= ERTS_ATOM_CACHE_SIZE), \
sizeof(Eterm)*(ERTS_ATOM_CACHE_SIZE - (EDEP)->attab.size)) \
: sizeof(ErtsAtomTranslationTable)))
diff --git a/erts/emulator/beam/global.h b/erts/emulator/beam/global.h
index 6b720b53d8..94bc1b172a 100755
--- a/erts/emulator/beam/global.h
+++ b/erts/emulator/beam/global.h
@@ -186,11 +186,6 @@ extern void erts_ddll_remove_monitor(Process *p,
extern Eterm erts_ddll_monitor_driver(Process *p,
Eterm description,
ErtsProcLocks plocks);
-/*
- * Max no. of drivers (linked in and dynamically loaded). Each table
- * entry uses 4 bytes.
- */
-#define DRIVER_TAB_SIZE 32
/*
** Just like the driver binary but with initial flags
@@ -856,6 +851,12 @@ Port *erts_get_heart_port(void);
void erts_lcnt_enable_io_lock_count(int enable);
#endif
+/* driver_tab.c */
+typedef void *(*ErtsStaticNifInitFPtr)(void);
+ErtsStaticNifInitFPtr erts_static_nif_get_nif_init(const char *name, int len);
+int erts_is_static_nif(void *handle);
+void erts_init_static_drivers(void);
+
/* erl_drv_thread.c */
void erl_drv_thr_init(void);
@@ -870,13 +871,13 @@ Eterm store_external_or_ref_in_proc_(Process *, Eterm);
Eterm store_external_or_ref_(Uint **, ErlOffHeap*, Eterm);
#define NC_HEAP_SIZE(NC) \
- (ASSERT_EXPR(is_node_container((NC))), \
+ (ASSERT(is_node_container((NC))), \
IS_CONST((NC)) ? 0 : (thing_arityval(*boxed_val((NC))) + 1))
#define STORE_NC(Hpp, ETpp, NC) \
- (ASSERT_EXPR(is_node_container((NC))), \
+ (ASSERT(is_node_container((NC))), \
IS_CONST((NC)) ? (NC) : store_external_or_ref_((Hpp), (ETpp), (NC)))
#define STORE_NC_IN_PROC(Pp, NC) \
- (ASSERT_EXPR(is_node_container((NC))), \
+ (ASSERT(is_node_container((NC))), \
IS_CONST((NC)) ? (NC) : store_external_or_ref_in_proc_((Pp), (NC)))
/* duplicates from big.h */
@@ -915,6 +916,16 @@ char *erts_convert_filename_to_native(Eterm name, char *statbuf,
ErtsAlcType_t alloc_type,
int allow_empty, int allow_atom,
Sint *used /* out */);
+char *erts_convert_filename_to_encoding(Eterm name, char *statbuf,
+ size_t statbuf_size,
+ ErtsAlcType_t alloc_type,
+ int allow_empty, int allow_atom,
+ int encoding,
+ Sint *used /* out */);
+char* erts_convert_filename_to_wchar(byte* bytes, Uint size,
+ char *statbuf, size_t statbuf_size,
+ ErtsAlcType_t alloc_type, Sint* used,
+ Uint extra_wchars);
Eterm erts_convert_native_to_filename(Process *p, byte *bytes);
Eterm erts_utf8_to_list(Process *p, Uint num, byte *bytes, Uint sz, Uint left,
Uint *num_built, Uint *num_eaten, Eterm tail);
diff --git a/erts/emulator/beam/io.c b/erts/emulator/beam/io.c
index c1e66b59af..d4623c0450 100644
--- a/erts/emulator/beam/io.c
+++ b/erts/emulator/beam/io.c
@@ -1330,7 +1330,7 @@ force_imm_drv_call(ErtsTryImmDrvCallState *sp)
erts_aint32_t invalid_state;
Port *prt = sp->port;
- ASSERT(ERTS_IS_CRASH_DUMPING)
+ ASSERT(ERTS_IS_CRASH_DUMPING);
ASSERT(is_atom(sp->port_op));
invalid_state = sp->state;
@@ -2765,6 +2765,7 @@ void erts_init_io(int port_tab_size,
init_driver(&fd_driver, &fd_driver_entry, NULL);
init_driver(&vanilla_driver, &vanilla_driver_entry, NULL);
init_driver(&spawn_driver, &spawn_driver_entry, NULL);
+ erts_init_static_drivers();
for (dp = driver_tab; *dp != NULL; dp++)
erts_add_driver_entry(*dp, NULL, 1);
@@ -3601,6 +3602,8 @@ erts_deliver_port_exit(Port *p, Eterm from, Eterm reason, int send_closed)
if (send_closed)
set_state_flags |= ERTS_PORT_SFLG_SEND_CLOSED;
+ erts_port_task_sched_enter_exiting_state(&p->sched);
+
state = erts_atomic32_read_bor_mb(&p->state, set_state_flags);
state |= set_state_flags;
@@ -4078,7 +4081,7 @@ erts_port_control(Process* c_p,
copy = 1;
else {
binp = ((ProcBin *) ebinp)->val;
- ASSERT(bufp < bufp + size);
+ ASSERT(bufp <= bufp + size);
ASSERT(binp->orig_bytes <= bufp
&& bufp + size <= binp->orig_bytes + binp->orig_size);
erts_refc_inc(&binp->refc, 1);
diff --git a/erts/emulator/beam/sys.h b/erts/emulator/beam/sys.h
index 05bff430e3..31252ed78f 100644
--- a/erts/emulator/beam/sys.h
+++ b/erts/emulator/beam/sys.h
@@ -149,19 +149,33 @@ typedef ERTS_SYS_FD_TYPE ErtsSysFdType;
# define ERTS_EXIT_AFTER_DUMP exit
#endif
+/* In VC++, noreturn is a declspec that has to be before the types,
+ * but in GNUC it is an att ribute to be placed between return type
+ * and function name, hence __decl_noreturn <types> __noreturn <function name>
+ */
+#if __GNUC__
+# define __decl_noreturn
+# define __noreturn __attribute__((noreturn))
+#else
+# if defined(__WIN32__) && defined(_MSC_VER)
+# define __noreturn
+# define __decl_noreturn __declspec(noreturn)
+# else
+# define __noreturn
+# define __decl_noreturn
+# endif
+#endif
+
+#define ERTS_ASSERT(e) \
+ ((void) ((e) ? 1 : (erl_assert_error(#e, __func__, __FILE__, __LINE__), 0)))
+
+__decl_noreturn void __noreturn erl_assert_error(const char* expr, const char *func,
+ const char* file, int line);
+
#ifdef DEBUG
-# define ASSERT(e) \
- if (e) { \
- ; \
- } else { \
- erl_assert_error(#e, __FILE__, __LINE__); \
- }
-# define ASSERT_EXPR(e) \
- ((void) ((e) ? 1 : (erl_assert_error(#e, __FILE__, __LINE__), 0)))
-void erl_assert_error(char* expr, char* file, int line);
+# define ASSERT(e) ERTS_ASSERT(e)
#else
-# define ASSERT(e)
-# define ASSERT_EXPR(e) ((void) 1)
+# define ASSERT(e) ((void) 1)
#endif
/*
@@ -197,23 +211,6 @@ void erl_assert_error(char* expr, char* file, int line);
# define erts_align_attribute(SZ)
#endif
-/* In VC++, noreturn is a declspec that has to be before the types,
- * but in GNUC it is an att ribute to be placed between return type
- * and function name, hence __decl_noreturn <types> __noreturn <function name>
- */
-#if __GNUC__
-# define __decl_noreturn
-# define __noreturn __attribute__((noreturn))
-#else
-# if defined(__WIN32__) && defined(_MSC_VER)
-# define __noreturn
-# define __decl_noreturn __declspec(noreturn)
-# else
-# define __noreturn
-# define __decl_noreturn
-# endif
-#endif
-
/*
** Data types:
**
@@ -282,16 +279,19 @@ typedef unsigned long UWord;
typedef long SWord;
#define SWORD_CONSTANT(Const) Const##L
#define UWORD_CONSTANT(Const) Const##UL
+#define ERTS_SWORD_MAX LONG_MAX
#elif SIZEOF_VOID_P == SIZEOF_INT
typedef unsigned int UWord;
typedef int SWord;
#define SWORD_CONSTANT(Const) Const
#define UWORD_CONSTANT(Const) Const##U
+#define ERTS_SWORD_MAX INT_MAX
#elif SIZEOF_VOID_P == SIZEOF_LONG_LONG
typedef unsigned long long UWord;
typedef long long SWord;
#define SWORD_CONSTANT(Const) Const##LL
#define UWORD_CONSTANT(Const) Const##ULL
+#define ERTS_SWORD_MAX LLONG_MAX
#else
#error Found no appropriate type to use for 'Eterm', 'Uint' and 'Sint'
#endif
@@ -304,6 +304,7 @@ typedef unsigned long Uint;
typedef long Sint;
#define SWORD_CONSTANT(Const) Const##L
#define UWORD_CONSTANT(Const) Const##UL
+#define ERTS_SWORD_MAX LONG_MAX
#define ERTS_SIZEOF_ETERM SIZEOF_LONG
#define ErtsStrToSint strtol
#elif SIZEOF_VOID_P == SIZEOF_INT
@@ -312,6 +313,7 @@ typedef unsigned int Uint;
typedef int Sint;
#define SWORD_CONSTANT(Const) Const
#define UWORD_CONSTANT(Const) Const##U
+#define ERTS_SWORD_MAX INT_MAX
#define ERTS_SIZEOF_ETERM SIZEOF_INT
#define ErtsStrToSint strtol
#elif SIZEOF_VOID_P == SIZEOF_LONG_LONG
@@ -320,6 +322,7 @@ typedef unsigned long long Uint;
typedef long long Sint;
#define SWORD_CONSTANT(Const) Const##LL
#define UWORD_CONSTANT(Const) Const##ULL
+#define ERTS_SWORD_MAX LLONG_MAX
#define ERTS_SIZEOF_ETERM SIZEOF_LONG_LONG
#if defined(__WIN32__)
#define ErtsStrToSint _strtoi64
@@ -749,6 +752,8 @@ int erts_sys_getenv(char *key, char *value, size_t *size);
int erts_sys_getenv_raw(char *key, char *value, size_t *size);
/* erts_sys_getenv__() is only allowed to be used in early init phase */
int erts_sys_getenv__(char *key, char *value, size_t *size);
+/* erst_sys_unsetenv() returns 0 on success and a value != 0 on failure. */
+int erts_sys_unsetenv(char *key);
/* Easier to use, but not as efficient, environment functions */
char *erts_read_env(char *key);
@@ -1012,6 +1017,9 @@ void erl_bin_write(unsigned char *, int, int);
#define ERTS_SMALL_ABS(Small) labs(Small)
#endif
+#ifndef ERTS_HAVE_ERTS_SYS_ALIGNED_ALLOC
+# define ERTS_HAVE_ERTS_SYS_ALIGNED_ALLOC 0
+#endif
#ifdef __WIN32__
void call_break_handler(void);
diff --git a/erts/emulator/beam/utils.c b/erts/emulator/beam/utils.c
index a5b2cc589c..297c4bf439 100644
--- a/erts/emulator/beam/utils.c
+++ b/erts/emulator/beam/utils.c
@@ -576,8 +576,8 @@ erts_bld_2tup_list(Uint **hpp, Uint *szp,
}
Eterm
-erts_bld_atom_uint_2tup_list(Uint **hpp, Uint *szp,
- Sint length, Eterm atoms[], Uint uints[])
+erts_bld_atom_uword_2tup_list(Uint **hpp, Uint *szp,
+ Sint length, Eterm atoms[], UWord uints[])
{
Sint i;
Eterm res = THE_NON_VALUE;
@@ -3021,6 +3021,14 @@ buf_to_intlist(Eterm** hpp, const char *buf, size_t len, Eterm tail)
** Return remaining bytes in buffer on success
** ERTS_IOLIST_TO_BUF_OVERFLOW on overflow
** ERTS_IOLIST_TO_BUF_TYPE_ERROR on type error (including that result would not be a whole number of bytes)
+**
+** Note!
+** Do not detect indata errors in this fiunction that are not detected by erts_iolist_size!
+**
+** A caller should be able to rely on a successful return from erts_iolist_to_buf
+** if erts_iolist_size is previously successfully called and erts_iolist_to_buf
+** is called with a buffer at least as large as the value given by erts_iolist_size.
+**
*/
ErlDrvSizeT erts_iolist_to_buf(Eterm obj, char* buf, ErlDrvSizeT alloced_len)
@@ -3127,6 +3135,11 @@ ErlDrvSizeT erts_iolist_to_buf(Eterm obj, char* buf, ErlDrvSizeT alloced_len)
/*
* Return 0 if successful, and non-zero if unsuccessful.
+ *
+ * It is vital that if erts_iolist_to_buf would return an error for
+ * any type of term data, this function should do so as well.
+ * Any input term error detected in erts_iolist_to_buf should also
+ * be detected in this function!
*/
int erts_iolist_size(Eterm obj, ErlDrvSizeT* sizep)
{
@@ -4006,7 +4019,6 @@ erts_smp_ensure_later_interval_acqb(erts_interval_t *icp, Uint64 ic)
#endif
}
-
/*
* A millisecond timestamp without time correction where there's no hrtime
* - for tracing on "long" things...