diff options
Diffstat (limited to 'erts')
41 files changed, 461 insertions, 211 deletions
diff --git a/erts/configure.in b/erts/configure.in index d865e675c4..e3eb6034e6 100644 --- a/erts/configure.in +++ b/erts/configure.in @@ -490,7 +490,19 @@ CFLAG_RUNTIME_LIBRARY_PATH="-Wl,-R" case $host_os in darwin*) CFLAG_RUNTIME_LIBRARY_PATH= - CFLAGS="$CFLAGS -no-cpp-precomp" + AC_TRY_COMPILE([],[ + #if __GNUC__ >= 4 + ; + #else + #error old or no gcc + #endif + ], + gcc_need_no_cpp_precomp=no, + gcc_need_no_cpp_precomp=yes) + + if test x$gcc_need_no_cpp_precomp = xyes; then + CFLAGS="$CFLAGS -no-cpp-precomp" + fi ;; win32) CFLAG_RUNTIME_LIBRARY_PATH= @@ -3076,8 +3088,6 @@ dnl done up where floating point is checked, need to descide there already... if test X${enable_hipe} = Xyes; then if test X$ac_cv_sizeof_void_p != X4 -a X$ARCH != Xamd64 -a X$ARCH != Xppc64; then AC_MSG_WARN([HiPE is not supported in 64-bit builds]) - elif test X$FPE != Xreliable -a X$ARCH != Xarm; then - AC_MSG_WARN([HiPE is not supported on $ARCH without reliable floating-point exceptions]) else HIPE_ENABLED=yes AC_DEFINE(HIPE,[1],[Define to enable HiPE]) diff --git a/erts/doc/src/erl.xml b/erts/doc/src/erl.xml index 39c79a29df..d0a0ceaeba 100644 --- a/erts/doc/src/erl.xml +++ b/erts/doc/src/erl.xml @@ -745,6 +745,19 @@ <seealso marker="erlang#system_flag_scheduler_bind_type">erlang:system_flag(scheduler_bind_type, SchedulerBindType)</seealso>. </p> </item> + <tag><marker id="+scl"><c>+scl true|false</c></marker></tag> + <item> + <p>Enable or disable scheduler compaction of load. By default + scheduler compaction of load is enabled. When enabled, load + balancing will strive for a load distribution which causes + as many scheduler threads as possible to be fully loaded (i.e., + not run out of work). This is accomplished by migrating load + (e.g. runnable processes) into a smaller set of schedulers + when schedulers frequently run out of work. When disabled, + the frequency with which schedulers run out of work will + not be taken into account by the load balancing logic. + </p> + </item> <tag><marker id="+sct"><c>+sct CpuTopology</c></marker></tag> <item> <list type="bulleted"> diff --git a/erts/emulator/Makefile.in b/erts/emulator/Makefile.in index 708d4ca0a3..a2cef8a8a5 100644 --- a/erts/emulator/Makefile.in +++ b/erts/emulator/Makefile.in @@ -971,7 +971,8 @@ HIPE_SRC= endif BEAM_SRC=$(wildcard beam/*.c) -DRV_SRC=$(wildcard drivers/common/*.c) $(wildcard drivers/$(ERLANG_OSTYPE)/*.c) +DRV_COMMON_SRC=$(wildcard drivers/common/*.c) +DRV_OSTYPE_SRC=$(wildcard drivers/$(ERLANG_OSTYPE)/*.c) ALL_SYS_SRC=$(wildcard sys/$(ERLANG_OSTYPE)/*.c) $(wildcard sys/common/*.c) TARGET_SRC=$(wildcard $(TARGET)/*.c) $(wildcard $(TTF_DIR)/*.c) @@ -982,7 +983,7 @@ ifeq ($(TARGET),win32) #DEP_CC=$(EMU_CC) DEP_CC=$(CC) -DEP_FLAGS=-MM $(subst -O2,,$(CFLAGS)) $(INCLUDES) -I../etc/win32 -Idrivers/common +DEP_FLAGS=-MM $(subst -O2,,$(CFLAGS)) $(INCLUDES) -I../etc/win32 -Idrivers/common -Idrivers/$(ERLANG_OSTYPE) # ifeq (@MIXED_CYGWIN_VC@,yes) # VC++ used for compiling. If __GNUC__ is defined we will include # other headers then when compiling which will result in faulty @@ -1002,14 +1003,16 @@ MG_FLAG=-MG endif DEP_CC=$(CC) -DEP_FLAGS=-MM $(MG_FLAG) $(CFLAGS) $(INCLUDES) -Idrivers/common +DEP_FLAGS=-MM $(MG_FLAG) $(CFLAGS) $(INCLUDES) -Idrivers/common -Idrivers/$(ERLANG_OSTYPE) SYS_SRC=$(ALL_SYS_SRC) endif depend: $(DEP_CC) $(DEP_FLAGS) $(BEAM_SRC) \ | $(SED_DEPEND) > $(TARGET)/depend.mk - $(DEP_CC) $(DEP_FLAGS) $(DRV_SRC) \ + $(DEP_CC) $(DEP_FLAGS) -DLIBSCTP=$(LIBSCTP) $(DRV_COMMON_SRC) \ + | $(SED_DEPEND) >> $(TARGET)/depend.mk + $(DEP_CC) $(DEP_FLAGS) -I../etc/$(ERLANG_OSTYPE) $(DRV_OSTYPE_SRC) \ | $(SED_DEPEND) >> $(TARGET)/depend.mk $(DEP_CC) $(DEP_FLAGS) $(SYS_SRC) \ | $(SED_DEPEND) >> $(TARGET)/depend.mk diff --git a/erts/emulator/beam/beam_emu.c b/erts/emulator/beam/beam_emu.c index 9c5450bd48..68e6383f7f 100644 --- a/erts/emulator/beam/beam_emu.c +++ b/erts/emulator/beam/beam_emu.c @@ -1057,7 +1057,7 @@ void process_main(void) Process* c_p = NULL; int reds_used; #ifdef DEBUG - Eterm pid; + ERTS_DECLARE_DUMMY(Eterm pid); #endif /* @@ -1165,7 +1165,7 @@ void process_main(void) c_p = schedule(c_p, reds_used); ERTS_VERIFY_UNUSED_TEMP_ALLOC(c_p); #ifdef DEBUG - pid = c_p->id; + pid = c_p->id; /* Save for debugging purpouses */ #endif ERTS_SMP_REQ_PROC_MAIN_LOCK(c_p); PROCESS_MAIN_CHK_LOCKS(c_p); @@ -4747,7 +4747,12 @@ void process_main(void) OpCase(fclearerror): OpCase(i_fcheckerror): erl_exit(1, "fclearerror/i_fcheckerror without fpe signals (beam_emu)"); +# define ERTS_NO_FPE_CHECK_INIT ERTS_FP_CHECK_INIT +# define ERTS_NO_FPE_ERROR ERTS_FP_ERROR #else +# define ERTS_NO_FPE_CHECK_INIT(p) +# define ERTS_NO_FPE_ERROR(p, a, b) + OpCase(fclearerror): { BeamInstr *next; @@ -4763,10 +4768,6 @@ void process_main(void) ERTS_FP_ERROR(c_p, freg[0].fd, goto fbadarith); NextPF(0, next); } -# undef ERTS_FP_CHECK_INIT -# undef ERTS_FP_ERROR -# define ERTS_FP_CHECK_INIT(p) -# define ERTS_FP_ERROR(p, a, b) #endif @@ -4774,45 +4775,45 @@ void process_main(void) BeamInstr *next; PreFetch(3, next); - ERTS_FP_CHECK_INIT(c_p); + ERTS_NO_FPE_CHECK_INIT(c_p); fb(Arg(2)) = fb(Arg(0)) + fb(Arg(1)); - ERTS_FP_ERROR(c_p, fb(Arg(2)), goto fbadarith); + ERTS_NO_FPE_ERROR(c_p, fb(Arg(2)), goto fbadarith); NextPF(3, next); } OpCase(i_fsub_lll): { BeamInstr *next; PreFetch(3, next); - ERTS_FP_CHECK_INIT(c_p); + ERTS_NO_FPE_CHECK_INIT(c_p); fb(Arg(2)) = fb(Arg(0)) - fb(Arg(1)); - ERTS_FP_ERROR(c_p, fb(Arg(2)), goto fbadarith); + ERTS_NO_FPE_ERROR(c_p, fb(Arg(2)), goto fbadarith); NextPF(3, next); } OpCase(i_fmul_lll): { BeamInstr *next; PreFetch(3, next); - ERTS_FP_CHECK_INIT(c_p); + ERTS_NO_FPE_CHECK_INIT(c_p); fb(Arg(2)) = fb(Arg(0)) * fb(Arg(1)); - ERTS_FP_ERROR(c_p, fb(Arg(2)), goto fbadarith); + ERTS_NO_FPE_ERROR(c_p, fb(Arg(2)), goto fbadarith); NextPF(3, next); } OpCase(i_fdiv_lll): { BeamInstr *next; PreFetch(3, next); - ERTS_FP_CHECK_INIT(c_p); + ERTS_NO_FPE_CHECK_INIT(c_p); fb(Arg(2)) = fb(Arg(0)) / fb(Arg(1)); - ERTS_FP_ERROR(c_p, fb(Arg(2)), goto fbadarith); + ERTS_NO_FPE_ERROR(c_p, fb(Arg(2)), goto fbadarith); NextPF(3, next); } OpCase(i_fnegate_ll): { BeamInstr *next; PreFetch(2, next); - ERTS_FP_CHECK_INIT(c_p); + ERTS_NO_FPE_CHECK_INIT(c_p); fb(Arg(1)) = -fb(Arg(0)); - ERTS_FP_ERROR(c_p, fb(Arg(1)), goto fbadarith); + ERTS_NO_FPE_ERROR(c_p, fb(Arg(1)), goto fbadarith); NextPF(2, next); fbadarith: diff --git a/erts/emulator/beam/beam_load.c b/erts/emulator/beam/beam_load.c index e43d364add..d8434c098e 100644 --- a/erts/emulator/beam/beam_load.c +++ b/erts/emulator/beam/beam_load.c @@ -254,6 +254,7 @@ typedef struct LoaderState { char* file_name; /* Name of file we are reading (usually chunk name). */ byte* file_p; /* Current pointer within file. */ unsigned file_left; /* Number of bytes left in file. */ + ErlDrvBinary* bin; /* Binary holding BEAM file (or NULL) */ /* * The following are used mainly for diagnostics. @@ -499,8 +500,10 @@ static void free_state(LoaderState* stp); static Eterm insert_new_code(Process *c_p, ErtsProcLocks c_p_locks, Eterm group_leader, Eterm module, BeamInstr* code, Uint size); +static int init_iff_file(LoaderState* stp, byte* code, Uint size); static int scan_iff_file(LoaderState* stp, Uint* chunk_types, Uint num_types, Uint num_mandatory); +static int verify_chunks(LoaderState* stp); static int load_atom_table(LoaderState* stp); static int load_import_table(LoaderState* stp); static int read_export_table(LoaderState* stp); @@ -630,40 +633,23 @@ erts_prepare_loading(LoaderState* stp, Process *c_p, Eterm group_leader, Eterm* modp, byte* code, Uint unloaded_size) { Eterm retval = am_badfile; - ErlDrvBinary* bin = NULL; stp->module = *modp; stp->group_leader = group_leader; - /* - * Check if the module is compressed (or possibly invalid/corrupted). - */ - if ( !(unloaded_size >= 4 && - code[0] == 'F' && code[1] == 'O' && - code[2] == 'R' && code[3] == '1') ) { - bin = (ErlDrvBinary *) - erts_gzinflate_buffer((char*)code, unloaded_size); - if (bin == NULL) { - goto load_error; - } - code = (byte*)bin->orig_bytes; - unloaded_size = bin->orig_size; - } +#if defined(LOAD_MEMORY_HARD_DEBUG) && defined(DEBUG) + erts_fprintf(stderr,"Loading a module\n"); +#endif /* * Scan the IFF file. */ -#if defined(LOAD_MEMORY_HARD_DEBUG) && defined(DEBUG) - erts_fprintf(stderr,"Loading a module\n"); -#endif - CHKALLOC(); CHKBLK(ERTS_ALC_T_CODE,stp->code); - stp->file_name = "IFF header for Beam file"; - stp->file_p = code; - stp->file_left = unloaded_size; - if (!scan_iff_file(stp, chunk_types, NUM_CHUNK_TYPES, NUM_MANDATORY)) { + if (!init_iff_file(stp, code, unloaded_size) || + !scan_iff_file(stp, chunk_types, NUM_CHUNK_TYPES, NUM_MANDATORY) || + !verify_chunks(stp)) { goto load_error; } @@ -787,9 +773,6 @@ erts_prepare_loading(LoaderState* stp, Process *c_p, Eterm group_leader, retval = NIL; load_error: - if (bin) { - driver_free_binary(bin); - } if (retval != NIL) { free_state(stp); } @@ -864,6 +847,7 @@ erts_alloc_loader_state(void) LoaderState* stp; stp = erts_alloc(ERTS_ALC_T_LOADER_TMP, sizeof(LoaderState)); + stp->bin = NULL; stp->function = THE_NON_VALUE; /* Function not known yet */ stp->arity = 0; stp->specific_op = -1; @@ -897,6 +881,9 @@ erts_alloc_loader_state(void) static void free_state(LoaderState* stp) { + if (stp->bin != 0) { + driver_free_binary(stp->bin); + } if (stp->code != 0) { erts_free(ERTS_ALC_T_CODE, stp->code); } @@ -956,6 +943,7 @@ free_state(LoaderState* stp) if (stp->fname != 0) { erts_free(ERTS_ALC_T_LOADER_TMP, stp->fname); } + erts_free(ERTS_ALC_T_LOADER_TMP, stp); } @@ -1011,23 +999,47 @@ insert_new_code(Process *c_p, ErtsProcLocks c_p_locks, } static int -scan_iff_file(LoaderState* stp, Uint* chunk_types, Uint num_types, Uint num_mandatory) +init_iff_file(LoaderState* stp, byte* code, Uint size) { - MD5_CTX context; + Uint form_id = MakeIffId('F', 'O', 'R', '1'); Uint id; Uint count; - int i; + + if (size < 4) { + goto load_error; + } /* - * The binary must start with an IFF 'FOR1' chunk. + * Check if the module is compressed (or possibly invalid/corrupted). */ + if (MakeIffId(code[0], code[1], code[2], code[3]) != form_id) { + stp->bin = (ErlDrvBinary *) erts_gzinflate_buffer((char*)code, size); + if (stp->bin == NULL) { + goto load_error; + } + code = (byte*)stp->bin->orig_bytes; + size = stp->bin->orig_size; + if (size < 4) { + goto load_error; + } + } - GetInt(stp, 4, id); - if (id != MakeIffId('F', 'O', 'R', '1')) { + /* + * The binary must start with an IFF 'FOR1' chunk. + */ + if (MakeIffId(code[0], code[1], code[2], code[3]) != form_id) { LoadError0(stp, "not a BEAM file: no IFF 'FOR1' chunk"); } /* + * Initialize our "virtual file system". + */ + + stp->file_name = "IFF header for Beam file"; + stp->file_p = code + 4; + stp->file_left = size - 4; + + /* * Retrieve the chunk size and verify it. If the size is equal to * or less than the size of the binary, it is ok and we will use it * as the limit for the logical file size. @@ -1048,6 +1060,21 @@ scan_iff_file(LoaderState* stp, Uint* chunk_types, Uint num_types, Uint num_mand if (id != MakeIffId('B', 'E', 'A', 'M')) { LoadError0(stp, "not a BEAM file: IFF form type is not 'BEAM'"); } + return 1; + + load_error: + return 0; +} + +/* + * Scan the IFF file. The header should have been verified by init_iff_file(). + */ +static int +scan_iff_file(LoaderState* stp, Uint* chunk_types, Uint num_types, Uint num_mandatory) +{ + Uint count; + Uint id; + int i; /* * Initialize the chunks[] array in the state. @@ -1104,17 +1131,25 @@ scan_iff_file(LoaderState* stp, Uint* chunk_types, Uint num_types, Uint num_mand stp->file_p += count; stp->file_left -= count; } + return 1; - /* - * At this point, we have read the entire IFF file, and we - * know that it is syntactically correct. - * - * Now check that it contains all mandatory chunks. At the - * same time calculate the MD5 for the module. - */ + load_error: + return 0; +} + +/* + * Verify that all mandatory chunks are present and calculate + * MD5 for the module. + */ + +static int +verify_chunks(LoaderState* stp) +{ + int i; + MD5_CTX context; MD5Init(&context); - for (i = 0; i < num_mandatory; i++) { + for (i = 0; i < NUM_MANDATORY; i++) { if (stp->chunks[i].start != NULL) { MD5Update(&context, stp->chunks[i].start, stp->chunks[i].size); } else { @@ -1124,41 +1159,49 @@ scan_iff_file(LoaderState* stp, Uint* chunk_types, Uint num_types, Uint num_mand LoadError1(stp, "mandatory chunk of type '%s' not found\n", sbuf); } } - if (LITERAL_CHUNK < num_types) { - if (stp->chunks[LAMBDA_CHUNK].start != 0) { - byte* start = stp->chunks[LAMBDA_CHUNK].start; - Uint left = stp->chunks[LAMBDA_CHUNK].size; - /* - * The idea here is to ignore the OldUniq field for the fun; it is - * based on the old broken hash function, which can be different - * on little endian and big endian machines. - */ - if (left >= 4) { - static byte zero[4]; - MD5Update(&context, start, 4); - start += 4; - left -= 4; + /* + * If there is a lambda chunk, include parts of it in the MD5. + */ + if (stp->chunks[LAMBDA_CHUNK].start != 0) { + byte* start = stp->chunks[LAMBDA_CHUNK].start; + Uint left = stp->chunks[LAMBDA_CHUNK].size; + + /* + * The idea here is to ignore the OldUniq field for the fun; it is + * based on the old broken hash function, which can be different + * on little endian and big endian machines. + */ + if (left >= 4) { + static byte zero[4]; + MD5Update(&context, start, 4); + start += 4; + left -= 4; - while (left >= 24) { - /* Include: Function Arity Index NumFree */ - MD5Update(&context, start, 20); - /* Set to zero: OldUniq */ - MD5Update(&context, zero, 4); - start += 24; - left -= 24; - } - } - /* Can't happen for a correct 'FunT' chunk */ - if (left > 0) { - MD5Update(&context, start, left); + while (left >= 24) { + /* Include: Function Arity Index NumFree */ + MD5Update(&context, start, 20); + /* Set to zero: OldUniq */ + MD5Update(&context, zero, 4); + start += 24; + left -= 24; } } - if (stp->chunks[LITERAL_CHUNK].start != 0) { - MD5Update(&context, stp->chunks[LITERAL_CHUNK].start, - stp->chunks[LITERAL_CHUNK].size); + /* Can't happen for a correct 'FunT' chunk */ + if (left > 0) { + MD5Update(&context, start, left); } } + + + /* + * If there is a literal chunk, include it in the MD5. + */ + if (stp->chunks[LITERAL_CHUNK].start != 0) { + MD5Update(&context, stp->chunks[LITERAL_CHUNK].start, + stp->chunks[LITERAL_CHUNK].size); + } + MD5Final(stp->mod_md5, &context); return 1; @@ -1453,7 +1496,7 @@ static int read_line_table(LoaderState* stp) { unsigned version; - unsigned flags; + ERTS_DECLARE_DUMMY(unsigned flags); int num_line_items; BeamInstr* lp; int i; @@ -5407,7 +5450,7 @@ code_get_chunk_2(BIF_ALIST_2) Process* p = BIF_P; Eterm Bin = BIF_ARG_1; Eterm Chunk = BIF_ARG_2; - LoaderState state; + LoaderState* stp; Uint chunk = 0; ErlSubBin* sb; Uint offset; @@ -5419,15 +5462,16 @@ code_get_chunk_2(BIF_ALIST_2) Eterm real_bin; byte* temp_alloc = NULL; + stp = erts_alloc_loader_state(); if ((start = erts_get_aligned_binary_bytes(Bin, &temp_alloc)) == NULL) { error: erts_free_aligned_binary_bytes(temp_alloc); + if (stp) { + free_state(stp); + } BIF_ERROR(p, BADARG); } - state.module = THE_NON_VALUE; /* Suppress diagnostiscs */ - state.file_name = "IFF header for Beam file"; - state.file_p = start; - state.file_left = binary_size(Bin); + stp->module = THE_NON_VALUE; /* Suppress diagnostics */ for (i = 0; i < 4; i++) { Eterm* chunkp; Eterm num; @@ -5445,25 +5489,30 @@ code_get_chunk_2(BIF_ALIST_2) if (is_not_nil(Chunk)) { goto error; } - if (!scan_iff_file(&state, &chunk, 1, 1)) { - erts_free_aligned_binary_bytes(temp_alloc); - return am_undefined; + if (!init_iff_file(stp, start, binary_size(Bin)) || + !scan_iff_file(stp, &chunk, 1, 1) || + stp->chunks[0].start == NULL) { + res = am_undefined; + goto done; } ERTS_GET_REAL_BIN(Bin, real_bin, offset, bitoffs, bitsize); if (bitoffs) { - res = new_binary(p, state.chunks[0].start, state.chunks[0].size); + res = new_binary(p, stp->chunks[0].start, stp->chunks[0].size); } else { sb = (ErlSubBin *) HAlloc(p, ERL_SUB_BIN_SIZE); sb->thing_word = HEADER_SUB_BIN; sb->orig = real_bin; - sb->size = state.chunks[0].size; + sb->size = stp->chunks[0].size; sb->bitsize = 0; sb->bitoffs = 0; - sb->offs = offset + (state.chunks[0].start - start); + sb->offs = offset + (stp->chunks[0].start - start); sb->is_writable = 0; res = make_binary(sb); } + + done: erts_free_aligned_binary_bytes(temp_alloc); + free_state(stp); return res; } @@ -5476,21 +5525,29 @@ code_module_md5_1(BIF_ALIST_1) { Process* p = BIF_P; Eterm Bin = BIF_ARG_1; - LoaderState state; + LoaderState* stp; + byte* bytes; byte* temp_alloc = NULL; + Eterm res; - if ((state.file_p = erts_get_aligned_binary_bytes(Bin, &temp_alloc)) == NULL) { + stp = erts_alloc_loader_state(); + if ((bytes = erts_get_aligned_binary_bytes(Bin, &temp_alloc)) == NULL) { + free_state(stp); BIF_ERROR(p, BADARG); } - state.module = THE_NON_VALUE; /* Suppress diagnostiscs */ - state.file_name = "IFF header for Beam file"; - state.file_left = binary_size(Bin); - - if (!scan_iff_file(&state, chunk_types, NUM_CHUNK_TYPES, NUM_MANDATORY)) { - return am_undefined; + stp->module = THE_NON_VALUE; /* Suppress diagnostiscs */ + if (!init_iff_file(stp, bytes, binary_size(Bin)) || + !scan_iff_file(stp, chunk_types, NUM_CHUNK_TYPES, NUM_MANDATORY) || + !verify_chunks(stp)) { + res = am_undefined; + goto done; } + res = new_binary(p, stp->mod_md5, sizeof(stp->mod_md5)); + + done: erts_free_aligned_binary_bytes(temp_alloc); - return new_binary(p, state.mod_md5, sizeof(state.mod_md5)); + free_state(stp); + return res; } #define WORDS_PER_FUNCTION 6 @@ -5776,7 +5833,6 @@ erts_make_stub_module(Process* p, Eterm Mod, Eterm Beam, Eterm Info) int code_size; int rval; int i; - ErlDrvBinary* bin = NULL; byte* temp_alloc = NULL; byte* bytes; Uint size; @@ -5809,29 +5865,17 @@ erts_make_stub_module(Process* p, Eterm Mod, Eterm Beam, Eterm Info) size = binary_size(Beam); /* - * Uncompressed if needed. - */ - if (!(size >= 4 && bytes[0] == 'F' && bytes[1] == 'O' && - bytes[2] == 'R' && bytes[3] == '1')) { - bin = (ErlDrvBinary *) erts_gzinflate_buffer((char*)bytes, size); - if (bin == NULL) { - goto error; - } - bytes = (byte*)bin->orig_bytes; - size = bin->orig_size; - } - - /* * Scan the Beam binary and read the interesting sections. */ - stp->file_name = "IFF header for Beam file"; - stp->file_p = bytes; - stp->file_left = size; stp->module = Mod; stp->group_leader = p->group_leader; stp->num_functions = n; - if (!scan_iff_file(stp, chunk_types, NUM_CHUNK_TYPES, NUM_MANDATORY)) { + if (!init_iff_file(stp, bytes, size)) { + goto error; + } + if (!scan_iff_file(stp, chunk_types, NUM_CHUNK_TYPES, NUM_MANDATORY) || + !verify_chunks(stp)) { goto error; } define_file(stp, "code chunk header", CODE_CHUNK); @@ -5986,13 +6030,11 @@ erts_make_stub_module(Process* p, Eterm Mod, Eterm Beam, Eterm Info) if (patch_funentries(Patchlist)) { erts_free_aligned_binary_bytes(temp_alloc); free_state(stp); - if (bin != NULL) { - driver_free_binary(bin); - } return Mod; } error: + erts_free_aligned_binary_bytes(temp_alloc); free_state(stp); BIF_ERROR(p, BADARG); } diff --git a/erts/emulator/beam/big.c b/erts/emulator/beam/big.c index b90ea6b478..46db9ca99c 100644 --- a/erts/emulator/beam/big.c +++ b/erts/emulator/beam/big.c @@ -310,12 +310,12 @@ #define DREM(a1,a0,b,r) do { \ ErtsDigit __a1 = (a1); \ ErtsDigit __b = (b); \ - ErtsDigit __q0; \ + ERTS_DECLARE_DUMMY(ErtsDigit __q0); \ DDIVREM((__a1 % __b), (a0), __b, __q0, r); \ } while(0) #define DDIV(a1,a0,b,q) do { \ - ErtsDigit _tmp; \ + ERTS_DECLARE_DUMMY(ErtsDigit _tmp); \ DDIVREM(a1,a0,b,q,_tmp); \ } while(0) @@ -413,8 +413,8 @@ } while(0) #define DDIV2(a1,a0,b1,b0,q) do { \ - ErtsDigit _tmp_r1; \ - ErtsDigit _tmp_r0; \ + ERTS_DECLARE_DUMMY(ErtsDigit _tmp_r1); \ + ERTS_DECLARE_DUMMY(ErtsDigit _tmp_r0); \ D2DIVREM(a1,a0,b1,b0,q,_tmp_r1,_tmp_r0); \ } while(0) @@ -810,7 +810,9 @@ static dsize_t D_div(ErtsDigit* x, dsize_t xl, ErtsDigit d, ErtsDigit* q, ErtsDi } do { - ErtsDigit q0, a0, b1, b0, b; + ErtsDigit q0, a0, b0; + ERTS_DECLARE_DUMMY(ErtsDigit b); + ERTS_DECLARE_DUMMY(ErtsDigit b1); if (d > a1) { a0 = *xp; diff --git a/erts/emulator/beam/copy.c b/erts/emulator/beam/copy.c index 90201f3a90..1d968fb147 100644 --- a/erts/emulator/beam/copy.c +++ b/erts/emulator/beam/copy.c @@ -134,7 +134,7 @@ Uint size_object(Eterm obj) case SUB_BINARY_SUBTAG: { Eterm real_bin; - Uint offset; /* Not used. */ + ERTS_DECLARE_DUMMY(Uint offset); /* Not used. */ Uint bitsize; Uint bitoffs; Uint extra_bytes; diff --git a/erts/emulator/beam/erl_bif_binary.c b/erts/emulator/beam/erl_bif_binary.c index 6d022e0d11..7e7bec9b87 100644 --- a/erts/emulator/beam/erl_bif_binary.c +++ b/erts/emulator/beam/erl_bif_binary.c @@ -1152,7 +1152,7 @@ static int do_binary_match(Process *p, Eterm subject, Uint hsstart, Uint hsend, erts_free_aligned_binary_bytes(temp_alloc); return DO_BIN_MATCH_RESTART; } else { - Eterm epos = erts_make_integer(pos+hsstart,p); + Eterm epos = erts_make_integer(pos,p); Eterm erlen = erts_make_integer(rlen,p); hp = HAlloc(p,3); ret = TUPLE2(hp, epos, erlen); @@ -1898,9 +1898,9 @@ static BIF_RETTYPE do_longest_common(Process *p, Eterm list, int direction) cd = (CommonData *) ERTS_MAGIC_BIN_DATA(mb); l = list; while (is_list(l)) { - Uint bitoffs; + ERTS_DECLARE_DUMMY(Uint bitoffs); Uint bitsize; - Uint offset; + ERTS_DECLARE_DUMMY(Uint offset); Eterm real_bin; ProcBin* pb; @@ -2377,7 +2377,7 @@ static BIF_RETTYPE do_binary_copy(Process *p, Eterm bin, Eterm en) { Uint n; byte *bytes; - Uint bit_offs; + ERTS_DECLARE_DUMMY(Uint bit_offs); Uint bit_size; size_t size; Uint reds = get_reds(p, BINARY_COPY_LOOP_FACTOR); @@ -2406,9 +2406,9 @@ static BIF_RETTYPE do_binary_copy(Process *p, Eterm bin, Eterm en) if ((target_size - size) >= reds) { Eterm orig; - Uint offset; - Uint bit_offset; - Uint bit_size; + ERTS_DECLARE_DUMMY(Uint offset); + ERTS_DECLARE_DUMMY(Uint bit_offset); + ERTS_DECLARE_DUMMY(Uint bit_size); CopyBinState *cbs; Eterm *hp; Eterm trap_term; diff --git a/erts/emulator/beam/erl_db.c b/erts/emulator/beam/erl_db.c index 0079c13287..38b4a2d460 100644 --- a/erts/emulator/beam/erl_db.c +++ b/erts/emulator/beam/erl_db.c @@ -1298,7 +1298,10 @@ BIF_RETTYPE ets_new_2(BIF_ALIST_2) UWord heir_data; Uint32 status; Sint keypos; - int is_named, is_fine_locked, frequent_read, is_compressed; + int is_named, is_compressed; +#ifdef ERTS_SMP + int is_fine_locked, frequent_read; +#endif #ifdef DEBUG int cret; #endif @@ -1316,8 +1319,10 @@ BIF_RETTYPE ets_new_2(BIF_ALIST_2) status = DB_NORMAL | DB_SET | DB_PROTECTED; keypos = 1; is_named = 0; +#ifdef ERTS_SMP is_fine_locked = 0; frequent_read = 0; +#endif heir = am_none; heir_data = (UWord) am_undefined; is_compressed = erts_ets_always_compress; @@ -1346,18 +1351,31 @@ BIF_RETTYPE ets_new_2(BIF_ALIST_2) keypos = signed_val(tp[2]); } else if (tp[1] == am_write_concurrency) { +#ifdef ERTS_SMP if (tp[2] == am_true) { is_fine_locked = 1; } else if (tp[2] == am_false) { is_fine_locked = 0; } else break; +#else + if ((tp[2] != am_true) && (tp[2] != am_false)) { + break; + } +#endif } else if (tp[1] == am_read_concurrency) { +#ifdef ERTS_SMP if (tp[2] == am_true) { frequent_read = 1; } else if (tp[2] == am_false) { frequent_read = 0; } else break; +#else + if ((tp[2] != am_true) && (tp[2] != am_false)) { + break; + } +#endif + } else if (tp[1] == am_heir && tp[2] == am_none) { heir = am_none; @@ -1397,11 +1415,11 @@ BIF_RETTYPE ets_new_2(BIF_ALIST_2) } if (IS_HASH_TABLE(status)) { meth = &db_hash; - #ifdef ERTS_SMP +#ifdef ERTS_SMP if (is_fine_locked && !(status & DB_PRIVATE)) { status |= DB_FINE_LOCKED; } - #endif +#endif } else if (IS_TREE_TABLE(status)) { meth = &db_tree; diff --git a/erts/emulator/beam/erl_init.c b/erts/emulator/beam/erl_init.c index 7ae9f990ad..6c4ba2af68 100644 --- a/erts/emulator/beam/erl_init.c +++ b/erts/emulator/beam/erl_init.c @@ -513,6 +513,8 @@ void erts_usage(void) erts_fprintf(stderr, "-rg amount set reader groups limit\n"); erts_fprintf(stderr, "-sbt type set scheduler bind type, valid types are:\n"); erts_fprintf(stderr, " u|ns|ts|ps|s|nnts|nnps|tnnps|db\n"); + erts_fprintf(stderr, "-scl bool enable/disable compaction of scheduler load,\n"); + erts_fprintf(stderr, " see the erl(1) documentation for more info.\n"); erts_fprintf(stderr, "-sct cput set cpu topology,\n"); erts_fprintf(stderr, " see the erl(1) documentation for more info.\n"); erts_fprintf(stderr, "-swt val set scheduler wakeup threshold, valid values are:\n"); @@ -610,6 +612,7 @@ early_init(int *argc, char **argv) /* char envbuf[21]; /* enough for any 64-bit integer */ size_t envbufsz; + erts_sched_compact_load = 1; use_multi_run_queue = 1; erts_printf_eterm_func = erts_printf_term; erts_disable_tolerant_timeofday = 0; @@ -1198,6 +1201,19 @@ erl_start(int argc, char **argv) erts_usage(); } } + else if (has_prefix("cl", sub_param)) { + arg = get_arg(sub_param+2, argv[i+1], &i); + if (sys_strcmp("true", arg) == 0) + erts_sched_compact_load = 1; + else if (sys_strcmp("false", arg) == 0) + erts_sched_compact_load = 0; + else { + erts_fprintf(stderr, + "bad scheduler compact load value '%s'\n", + arg); + erts_usage(); + } + } else if (has_prefix("ct", sub_param)) { arg = get_arg(sub_param+2, argv[i+1], &i); res = erts_init_cpu_topology_string(arg); diff --git a/erts/emulator/beam/erl_process.c b/erts/emulator/beam/erl_process.c index a3c1c9577b..84c0ded016 100644 --- a/erts/emulator/beam/erl_process.c +++ b/erts/emulator/beam/erl_process.c @@ -114,6 +114,7 @@ static Sint p_serial; static Uint p_serial_mask; static Uint p_serial_shift; +int erts_sched_compact_load; Uint erts_no_schedulers; Uint erts_max_processes = ERTS_DEFAULT_MAX_PROCESSES; Uint erts_process_tab_index_mask; @@ -2949,6 +2950,9 @@ check_balance(ErtsRunQueue *c_rq) mmax_len = run_queue_info[qix].max_len; } + if (!erts_sched_compact_load) + goto all_active; + if (!forced && half_full_scheds != blnc_no_rqs) { int min = 1; if (min < half_full_scheds) @@ -7136,7 +7140,7 @@ erl_create_process(Process* parent, /* Parent of process (default group leader). p->pending_exit.bp = NULL; #endif -#if !defined(NO_FPE_SIGNALS) +#if !defined(NO_FPE_SIGNALS) || defined(HIPE) p->fp_exception = 0; #endif @@ -7310,7 +7314,7 @@ void erts_init_empty_process(Process *p) p->run_queue = ERTS_RUNQ_IX(0); #endif -#if !defined(NO_FPE_SIGNALS) +#if !defined(NO_FPE_SIGNALS) || defined(HIPE) p->fp_exception = 0; #endif diff --git a/erts/emulator/beam/erl_process.h b/erts/emulator/beam/erl_process.h index 4027fade35..69ff423133 100644 --- a/erts/emulator/beam/erl_process.h +++ b/erts/emulator/beam/erl_process.h @@ -95,6 +95,7 @@ struct saved_calls { }; extern Export exp_send, exp_receive, exp_timeout; +extern int erts_sched_compact_load; extern Uint erts_no_schedulers; extern Uint erts_no_run_queues; extern int erts_sched_thread_suggested_stack_size; @@ -617,7 +618,7 @@ struct process { Uint min_heap_size; /* Minimum size of heap (in words). */ Uint min_vheap_size; /* Minimum size of virtual heap (in words). */ -#if !defined(NO_FPE_SIGNALS) +#if !defined(NO_FPE_SIGNALS) || defined(HIPE) volatile unsigned long fp_exception; #endif diff --git a/erts/emulator/beam/erl_unicode.c b/erts/emulator/beam/erl_unicode.c index fca785a4de..6d5eae73b0 100644 --- a/erts/emulator/beam/erl_unicode.c +++ b/erts/emulator/beam/erl_unicode.c @@ -227,8 +227,8 @@ static ERTS_INLINE int simple_loops_to_common(int cost) static Sint aligned_binary_size(Eterm binary) { - unsigned char *bytes; - Uint bitoffs; + ERTS_DECLARE_DUMMY(unsigned char *bytes); + ERTS_DECLARE_DUMMY(Uint bitoffs); Uint bitsize; ERTS_GET_BINARY_BYTES(binary, bytes, bitoffs, bitsize); @@ -894,7 +894,9 @@ static BIF_RETTYPE build_utf8_return(Process *p,Eterm bin,int pos, static BIF_RETTYPE characters_to_utf8_trap(BIF_ALIST_3) { +#ifdef DEBUG Eterm *real_bin; +#endif byte* bytes; Eterm rest_term; int left, sleft; @@ -908,8 +910,10 @@ static BIF_RETTYPE characters_to_utf8_trap(BIF_ALIST_3) /*erts_printf("Trap %T!\r\n",BIF_ARG_2);*/ ASSERT(is_binary(BIF_ARG_1)); +#ifdef DEBUG real_bin = binary_val(BIF_ARG_1); ASSERT(*real_bin == HEADER_PROC_BIN); +#endif pos = (int) binary_size(BIF_ARG_1); bytes = binary_bytes(BIF_ARG_1); sleft = left = allowed_iterations(BIF_P); @@ -1719,7 +1723,7 @@ static BIF_RETTYPE do_bif_utf8_to_list(Process *p, if (b_sz) { ErlSubBin *sb; Eterm orig; - Uint offset; + ERTS_DECLARE_DUMMY(Uint offset); ASSERT(state != ERTS_UTF8_OK); hp = HAlloc(p, ERL_SUB_BIN_SIZE); sb = (ErlSubBin *) hp; @@ -2566,11 +2570,11 @@ BIF_RETTYPE prim_file_internal_native2name_1(BIF_ALIST_1) BIF_RETTYPE prim_file_internal_normalize_utf8_1(BIF_ALIST_1) { - Eterm real_bin; - Uint offset; + ERTS_DECLARE_DUMMY(Eterm real_bin); + ERTS_DECLARE_DUMMY(Uint offset); Uint size,num_chars; Uint bitsize; - Uint bitoffs; + ERTS_DECLARE_DUMMY(Uint bitoffs); Eterm ret; byte *temp_alloc = NULL; byte *bytes; diff --git a/erts/emulator/beam/io.c b/erts/emulator/beam/io.c index fff720634d..132dc78515 100644 --- a/erts/emulator/beam/io.c +++ b/erts/emulator/beam/io.c @@ -952,7 +952,7 @@ io_list_to_vec(Eterm obj, /* io-list */ do { \ int _size = binary_size(obj); \ Eterm _real; \ - Uint _offset; \ + ERTS_DECLARE_DUMMY(Uint _offset); \ int _bitoffs; \ int _bitsize; \ ERTS_GET_REAL_BIN(obj, _real, _offset, _bitoffs, _bitsize); \ @@ -2171,8 +2171,8 @@ erts_port_control(Process* p, Port* prt, Uint command, Eterm iolist) * and with its length in to_len. */ if (is_binary(iolist) && binary_bitoffset(iolist) == 0) { - Uint bitoffs; - Uint bitsize; + ERTS_DECLARE_DUMMY(Uint bitoffs); + ERTS_DECLARE_DUMMY(Uint bitsize); ERTS_GET_BINARY_BYTES(iolist, to_port, bitoffs, bitsize); to_len = binary_size(iolist); } else { diff --git a/erts/emulator/beam/sys.h b/erts/emulator/beam/sys.h index f9cbcc5892..94c36c8c59 100644 --- a/erts/emulator/beam/sys.h +++ b/erts/emulator/beam/sys.h @@ -103,6 +103,15 @@ typedef ERTS_SYS_FD_TYPE ErtsSysFdType; # define ERTS_LIKELY(BOOL) (BOOL) # define ERTS_UNLIKELY(BOOL) (BOOL) #endif +#ifdef __GNUC__ +# if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 5) +# define ERTS_DECLARE_DUMMY(X) X __attribute__ ((unused)) +# else +# define ERTS_DECLARE_DUMMY(X) X +# endif +#else +# define ERTS_DECLARE_DUMMY(X) X +#endif #if defined(DEBUG) || defined(ERTS_ENABLE_LOCK_CHECK) # undef ERTS_CAN_INLINE diff --git a/erts/emulator/beam/utils.c b/erts/emulator/beam/utils.c index 1bd178f280..8d4073f40f 100644 --- a/erts/emulator/beam/utils.c +++ b/erts/emulator/beam/utils.c @@ -2647,7 +2647,7 @@ tailrecur_ne: FloatDef f1, f2; Eterm big; #if HEAP_ON_C_STACK - Eterm big_buf[32]; /* If HEAP_ON_C_STACK */ + Eterm big_buf[CMP_TMP_HEAP_SIZE]; /* If HEAP_ON_C_STACK */ #else Eterm *big_buf = erts_get_scheduler_data()->cmp_tmp_heap; #endif @@ -2955,14 +2955,14 @@ Eterm buf_to_intlist(Eterm** hpp, char *buf, int len, Eterm tail) { Eterm* hp = *hpp; + int i = len - 1; - buf += (len-1); - while(len > 0) { - tail = CONS(hp, make_small((byte)*buf), tail); + while(i >= 0) { + tail = CONS(hp, make_small((Uint)(byte)buf[i]), tail); hp += 2; - buf--; - len--; + --i; } + *hpp = hp; return tail; } diff --git a/erts/emulator/drivers/common/efile_drv.c b/erts/emulator/drivers/common/efile_drv.c index 52f1b5312b..901d98c09d 100644 --- a/erts/emulator/drivers/common/efile_drv.c +++ b/erts/emulator/drivers/common/efile_drv.c @@ -2472,16 +2472,22 @@ file_output(ErlDrvData e, char* buf, int count) static void file_flush(ErlDrvData e) { file_descriptor *desc = (file_descriptor *)e; +#ifdef DEBUG int r; +#endif TRACE_C('f'); - r = flush_write(desc, NULL); +#ifdef DEBUG + r = +#endif + flush_write(desc, NULL); /* Only possible reason for bad return value is ENOMEM, and * there is nobody to tell... */ +#ifdef DEBUG ASSERT(r == 0); - r = 0; /* Avoiding warning */ +#endif cq_execute(desc); } @@ -2531,12 +2537,14 @@ file_timeout(ErlDrvData e) { driver_async(desc->port, KEY(desc), desc->invoke, desc->d, desc->free); break; case timer_write: { - int r = flush_write(desc, NULL); +#ifdef DEBUG + int r = +#endif + flush_write(desc, NULL); /* Only possible reason for bad return value is ENOMEM, and * there is nobody to tell... */ ASSERT(r == 0); - r = 0; /* Avoiding warning */ cq_execute(desc); } break; } /* case */ diff --git a/erts/emulator/drivers/common/inet_drv.c b/erts/emulator/drivers/common/inet_drv.c index 2ff5f744d6..dcc2954b02 100644 --- a/erts/emulator/drivers/common/inet_drv.c +++ b/erts/emulator/drivers/common/inet_drv.c @@ -9767,8 +9767,9 @@ static int packet_inet_ctl(ErlDrvData e, unsigned int cmd, char* buf, int len, */ int code; char tbuf[2]; +#ifdef HAVE_SCTP unsigned timeout; - +#endif DEBUGF(("packet_inet_ctl(%ld): CONNECT\r\n", (long)desc->port)); /* INPUT: [ Timeout(4), Port(2), Address(N) ] */ @@ -9829,7 +9830,7 @@ static int packet_inet_ctl(ErlDrvData e, unsigned int cmd, char* buf, int len, else if (len < 6) return ctl_error(EINVAL, rbuf, rsize); else { - timeout = get_int32(buf); /* IGNORED */ + /* Ignore timeout */ buf += 4; len -= 4; if (inet_set_address(desc->sfamily, @@ -10268,6 +10269,7 @@ static int packet_inet_input(udp_descriptor* udesc, HANDLE event) int code; void * extra = NULL; char * ptr; + int nsz; inet_input_count(desc, n); udesc->i_ptr += n; @@ -10281,17 +10283,19 @@ static int packet_inet_input(udp_descriptor* udesc, HANDLE event) ptr = udesc->i_buf->orig_bytes + sizeof(other) - len; sys_memcpy(ptr, abuf, len); + nsz = udesc->i_ptr - ptr; + /* Check if we need to reallocate binary */ - if ((desc->mode == INET_MODE_BINARY) && - (desc->hsz < (udesc->i_ptr - ptr)) && - ((udesc->i_ptr - ptr) + BIN_REALLOC_MARGIN(desc->bufsz) >= - udesc->i_bufsz)) { + if ((desc->mode == INET_MODE_BINARY) + && (desc->hsz < (nsz - len)) + && (nsz + BIN_REALLOC_MARGIN(desc->bufsz) < udesc->i_bufsz)) { ErlDrvBinary* tmp; int bufsz; bufsz = udesc->i_ptr - udesc->i_buf->orig_bytes; if ((tmp = realloc_buffer(udesc->i_buf, bufsz)) != NULL) { udesc->i_buf = tmp; udesc->i_bufsz = bufsz; + udesc->i_ptr = NULL; /* not used from here */ } } #ifdef HAVE_SCTP @@ -10299,8 +10303,8 @@ static int packet_inet_input(udp_descriptor* udesc, HANDLE event) #endif /* Actual parsing and return of the data received, occur here: */ code = packet_reply_binary_data(desc, len, udesc->i_buf, - ptr - udesc->i_buf->orig_bytes, - udesc->i_ptr - ptr, + (sizeof(other) - len), + nsz, extra); free_buffer(udesc->i_buf); udesc->i_buf = NULL; diff --git a/erts/emulator/hipe/hipe_amd64_bifs.m4 b/erts/emulator/hipe/hipe_amd64_bifs.m4 index 97a8267647..ec25c0b9b7 100644 --- a/erts/emulator/hipe/hipe_amd64_bifs.m4 +++ b/erts/emulator/hipe/hipe_amd64_bifs.m4 @@ -549,7 +549,9 @@ ASYM($1): /* * AMD64-specific primops. */ +#ifndef NO_FPE_SIGNALS noproc_primop_interface_0(nbif_handle_fp_exception, erts_restore_fpu) +#endif /* NO_FPE_SIGNALS */ /* * Implement gc_bif_interface_0 as nofail_primop_interface_0. diff --git a/erts/emulator/hipe/hipe_amd64_primops.h b/erts/emulator/hipe/hipe_amd64_primops.h index e3c7111997..55cb0eadb8 100644 --- a/erts/emulator/hipe/hipe_amd64_primops.h +++ b/erts/emulator/hipe/hipe_amd64_primops.h @@ -19,5 +19,7 @@ PRIMOP_LIST(am_inc_stack_0, &nbif_inc_stack_0) +#ifndef NO_FPE_SIGNALS PRIMOP_LIST(am_handle_fp_exception, &nbif_handle_fp_exception) +#endif PRIMOP_LIST(am_sse2_fnegate_mask, &sse2_fnegate_mask) diff --git a/erts/emulator/hipe/hipe_bif0.c b/erts/emulator/hipe/hipe_bif0.c index e7fb850530..cec22b3836 100644 --- a/erts/emulator/hipe/hipe_bif0.c +++ b/erts/emulator/hipe/hipe_bif0.c @@ -985,6 +985,26 @@ BIF_RETTYPE hipe_conv_big_to_float(BIF_ALIST_1) BIF_RET(res); } +#ifdef NO_FPE_SIGNALS + +/* + This is the current solution to make hipe run without FPE. + The native code is the same except that a call to this primop + is made after _every_ float operation to check the result. + The native fcheckerror still done later will detect if an + "emulated" FPE has occured. + We use p->hipe.float_result to avoid passing a 'double' argument, + which has its own calling convention (on amd64 at least). + Simple and slow... +*/ +void hipe_emulate_fpe(Process* p) +{ + if (!finite(p->hipe.float_result)) { + p->fp_exception = 1; + } +} +#endif + #if 0 /* XXX: unused */ /* * At least parts of this should be inlined in native code. diff --git a/erts/emulator/hipe/hipe_bif0.tab b/erts/emulator/hipe/hipe_bif0.tab index b6c6bede23..ce641365e9 100644 --- a/erts/emulator/hipe/hipe_bif0.tab +++ b/erts/emulator/hipe/hipe_bif0.tab @@ -140,3 +140,5 @@ atom bs_put_utf16le atom bs_get_utf16 atom bs_validate_unicode atom bs_validate_unicode_retract +atom emulate_fpe + diff --git a/erts/emulator/hipe/hipe_bif_list.m4 b/erts/emulator/hipe/hipe_bif_list.m4 index 48c7c1bc9b..942fa0c5cb 100644 --- a/erts/emulator/hipe/hipe_bif_list.m4 +++ b/erts/emulator/hipe/hipe_bif_list.m4 @@ -245,6 +245,10 @@ noproc_primop_interface_5(nbif_bs_put_big_integer, hipe_bs_put_big_integer) gc_bif_interface_0(nbif_check_get_msg, hipe_check_get_msg) +#ifdef NO_FPE_SIGNALS +nocons_nofail_primop_interface_0(nbif_emulate_fpe, hipe_emulate_fpe) +#endif + /* * SMP-specific stuff */ diff --git a/erts/emulator/hipe/hipe_mkliterals.c b/erts/emulator/hipe/hipe_mkliterals.c index 61e15f1d58..d07d14028c 100644 --- a/erts/emulator/hipe/hipe_mkliterals.c +++ b/erts/emulator/hipe/hipe_mkliterals.c @@ -293,6 +293,11 @@ static const struct literal { { "P_NRA", offsetof(struct process, hipe.nra) }, #endif { "P_NARITY", offsetof(struct process, hipe.narity) }, + { "P_FLOAT_RESULT", +# ifdef NO_FPE_SIGNALS + offsetof(struct process, hipe.float_result) +# endif + }, # if defined(ERTS_ENABLE_LOCK_CHECK) && defined(ERTS_SMP) { "P_BIF_CALLEE", offsetof(struct process, hipe.bif_callee) }, # endif @@ -491,7 +496,7 @@ static const struct rts_param { #endif }, { 14, "P_FP_EXCEPTION", -#if !defined(NO_FPE_SIGNALS) +#if !defined(NO_FPE_SIGNALS) || defined(HIPE) 1, offsetof(struct process, fp_exception) #endif }, @@ -504,6 +509,15 @@ static const struct rts_param { 0 #endif }, + /* This flag is always defined, but its value is configuration-dependent. */ + { 16, "ERTS_NO_FPE_SIGNALS", + 1, +#if defined(NO_FPE_SIGNALS) + 1 +#else + 0 +#endif + }, /* This parameter is always defined, but its value depends on ERTS_SMP. */ { 19, "MSG_MESSAGE", 1, offsetof(struct erl_mesg, m[0]) diff --git a/erts/emulator/hipe/hipe_native_bif.c b/erts/emulator/hipe/hipe_native_bif.c index 77dee6f9e9..3be821f8f7 100644 --- a/erts/emulator/hipe/hipe_native_bif.c +++ b/erts/emulator/hipe/hipe_native_bif.c @@ -189,6 +189,8 @@ void hipe_fclearerror_error(Process *p) { #if !defined(NO_FPE_SIGNALS) erts_fp_check_init_error(&p->fp_exception); +#else + erl_exit(ERTS_ABORT_EXIT, "Emulated FPE not cleared by HiPE"); #endif } diff --git a/erts/emulator/hipe/hipe_native_bif.h b/erts/emulator/hipe/hipe_native_bif.h index 8c9dec180e..9e3a156fbc 100644 --- a/erts/emulator/hipe/hipe_native_bif.h +++ b/erts/emulator/hipe/hipe_native_bif.h @@ -93,6 +93,11 @@ BIF_RETTYPE hipe_bs_validate_unicode(BIF_ALIST_1); struct erl_bin_match_buffer; int hipe_bs_validate_unicode_retract(struct erl_bin_match_buffer*, Eterm); +#ifdef NO_FPE_SIGNALS +AEXTERN(void,nbif_emulate_fpe,(Process*)); +void hipe_emulate_fpe(Process*); +#endif + /* * Stuff that is different in SMP and non-SMP. */ diff --git a/erts/emulator/hipe/hipe_primops.h b/erts/emulator/hipe/hipe_primops.h index 94113ffcd8..38509c105b 100644 --- a/erts/emulator/hipe/hipe_primops.h +++ b/erts/emulator/hipe/hipe_primops.h @@ -77,6 +77,10 @@ PRIMOP_LIST(am_nonclosure_address, &nbif_nonclosure_address) PRIMOP_LIST(am_conv_big_to_float, &nbif_conv_big_to_float) PRIMOP_LIST(am_fclearerror_error, &nbif_fclearerror_error) +#ifdef NO_FPE_SIGNALS +PRIMOP_LIST(am_emulate_fpe, &nbif_emulate_fpe) +#endif + #if defined(__sparc__) #include "hipe_sparc_primops.h" #endif diff --git a/erts/emulator/hipe/hipe_process.h b/erts/emulator/hipe/hipe_process.h index 43f47d1a28..4ee99d78a2 100644 --- a/erts/emulator/hipe/hipe_process.h +++ b/erts/emulator/hipe/hipe_process.h @@ -42,6 +42,9 @@ struct hipe_process_state { void (*nra)(void); /* Native code return address. */ #endif unsigned int narity; /* Arity of BIF call, for stack walks. */ +#ifdef NO_FPE_SIGNALS + double float_result; /* to be checked for inf/NaN by hipe_emulate_fpe */ +#endif #if defined(ERTS_ENABLE_LOCK_CHECK) && defined(ERTS_SMP) void (*bif_callee)(void); /* When calling BIF's via debug wrapper */ #endif diff --git a/erts/emulator/hipe/hipe_x86.h b/erts/emulator/hipe/hipe_x86.h index f0f3c158af..97f09e38cd 100644 --- a/erts/emulator/hipe/hipe_x86.h +++ b/erts/emulator/hipe/hipe_x86.h @@ -49,7 +49,9 @@ static __inline__ int hipe_word32_address_ok(void *address) #define hipe_arch_name am_x86 extern void nbif_inc_stack_0(void); +#ifndef NO_FPE_SIGNALS extern void nbif_handle_fp_exception(void); +#endif /* for hipe_bifs_enter_code_2 */ extern void *hipe_alloc_code(Uint nrbytes, Eterm callees, Eterm *trampolines, Process *p); diff --git a/erts/emulator/hipe/hipe_x86_bifs.m4 b/erts/emulator/hipe/hipe_x86_bifs.m4 index 2ea69bde3c..3cb7d67be0 100644 --- a/erts/emulator/hipe/hipe_x86_bifs.m4 +++ b/erts/emulator/hipe/hipe_x86_bifs.m4 @@ -621,7 +621,9 @@ ASYM($1): /* * x86-specific primops. */ +#ifndef NO_FPE_SIGNALS noproc_primop_interface_0(nbif_handle_fp_exception, erts_restore_fpu) +#endif /* NO_FPE_SIGNALS */ /* * Implement gc_bif_interface_0 as nofail_primop_interface_0. diff --git a/erts/emulator/hipe/hipe_x86_primops.h b/erts/emulator/hipe/hipe_x86_primops.h index 96d2336bc5..111b1fa8bd 100644 --- a/erts/emulator/hipe/hipe_x86_primops.h +++ b/erts/emulator/hipe/hipe_x86_primops.h @@ -19,4 +19,7 @@ PRIMOP_LIST(am_inc_stack_0, &nbif_inc_stack_0) +#ifndef NO_FPE_SIGNALS PRIMOP_LIST(am_handle_fp_exception, &nbif_handle_fp_exception) +#endif + diff --git a/erts/emulator/sys/common/erl_mseg.c b/erts/emulator/sys/common/erl_mseg.c index 49750ff6ce..db2854fa40 100644 --- a/erts/emulator/sys/common/erl_mseg.c +++ b/erts/emulator/sys/common/erl_mseg.c @@ -371,20 +371,30 @@ mseg_create(ErtsMsegAllctr_t *ma, MemKind* mk, Uint size) static ERTS_INLINE void mseg_destroy(ErtsMsegAllctr_t *ma, MemKind* mk, void *seg, Uint size) { +#ifdef DEBUG int res; +#endif #if HALFWORD_HEAP if (mk == &ma->low_mem) { - res = pmunmap((void *) seg, size); +#ifdef DEBUG + res = +#endif + pmunmap((void *) seg, size); } else #endif { #ifdef ERTS_MSEG_FAKE_SEGMENTS erts_sys_free(ERTS_ALC_N_INVALID, NULL, seg); +#ifdef DEBUG res = 0; +#endif #elif HAVE_MMAP - res = munmap((void *) seg, size); +#ifdef DEBUG + res = +#endif + munmap((void *) seg, size); #else # error "Missing mseg_destroy() implementation" #endif diff --git a/erts/emulator/test/Makefile b/erts/emulator/test/Makefile index 4d0c87bf12..08d2066da3 100644 --- a/erts/emulator/test/Makefile +++ b/erts/emulator/test/Makefile @@ -61,7 +61,7 @@ MODULES= \ exception_SUITE \ float_SUITE \ fun_SUITE \ - fun_r12_SUITE \ + fun_r13_SUITE \ gc_SUITE \ guard_SUITE \ hash_SUITE \ diff --git a/erts/emulator/test/distribution_SUITE.erl b/erts/emulator/test/distribution_SUITE.erl index 19281f6d58..08308629fe 100644 --- a/erts/emulator/test/distribution_SUITE.erl +++ b/erts/emulator/test/distribution_SUITE.erl @@ -18,7 +18,7 @@ %% -module(distribution_SUITE). --compile(r12). +-compile(r13). %% Tests distribution and the tcp driver. @@ -37,7 +37,7 @@ dist_auto_connect_never/1, dist_auto_connect_once/1, dist_parallel_send/1, atom_roundtrip/1, - atom_roundtrip_r12b/1, + atom_roundtrip_r13b/1, contended_atom_cache_entry/1, bad_dist_structure/1, bad_dist_ext_receive/1, @@ -62,7 +62,7 @@ all() -> link_to_dead_new_node, applied_monitor_node, ref_port_roundtrip, nil_roundtrip, stop_dist, {group, trap_bif}, {group, dist_auto_connect}, - dist_parallel_send, atom_roundtrip, atom_roundtrip_r12b, + dist_parallel_send, atom_roundtrip, atom_roundtrip_r13b, contended_atom_cache_entry, bad_dist_structure, {group, bad_dist_ext}]. groups() -> @@ -1100,17 +1100,17 @@ atom_roundtrip(Config) when is_list(Config) -> ?line stop_node(Node), ?line ok. -atom_roundtrip_r12b(Config) when is_list(Config) -> - case ?t:is_release_available("r12b") of +atom_roundtrip_r13b(Config) when is_list(Config) -> + case ?t:is_release_available("r13b") of true -> ?line AtomData = atom_data(), ?line verify_atom_data(AtomData), - ?line {ok, Node} = start_node(Config, [], "r12b"), + ?line {ok, Node} = start_node(Config, [], "r13b"), ?line do_atom_roundtrip(Node, AtomData), ?line stop_node(Node), ?line ok; false -> - ?line {skip,"No OTP R12B available"} + ?line {skip,"No OTP R13B available"} end. do_atom_roundtrip(Node, AtomData) -> diff --git a/erts/emulator/test/float_SUITE.erl b/erts/emulator/test/float_SUITE.erl index 46466427c5..8e6923ce9f 100644 --- a/erts/emulator/test/float_SUITE.erl +++ b/erts/emulator/test/float_SUITE.erl @@ -27,6 +27,7 @@ fpe/1,fp_drv/1,fp_drv_thread/1,denormalized/1,match/1, bad_float_unpack/1,cmp_zero/1, cmp_integer/1, cmp_bignum/1]). -export([otp_7178/1]). +-export([hidden_inf/1]). init_per_testcase(Func, Config) when is_atom(Func), is_list(Config) -> @@ -41,7 +42,9 @@ suite() -> [{ct_hooks,[ts_install_cth]}]. all() -> [fpe, fp_drv, fp_drv_thread, otp_7178, denormalized, - match, bad_float_unpack, {group, comparison}]. + match, bad_float_unpack, {group, comparison} + ,hidden_inf + ]. groups() -> [{comparison, [parallel], [cmp_zero, cmp_integer, cmp_bignum]}]. @@ -300,3 +303,25 @@ start_node(Config) when is_list(Config) -> stop_node(Node) -> ?t:stop_node(Node). + + +%% Test that operations that might hide infinite intermediate results +%% do not supress the badarith. +hidden_inf(Config) when is_list(Config) -> + ZeroP = 0.0, + ZeroN = id(ZeroP) * (-1), + [hidden_inf_1(A, B, Z, 9.23e307) + || A <- [1.0, -1.0, 3.1415, -0.00001000131, 3.57e257, ZeroP, ZeroN], + B <- [1.0, -1.0, 3.1415, -0.00001000131, 3.57e257, ZeroP, ZeroN], + Z <- [ZeroP, ZeroN]], + ok. + +hidden_inf_1(A, B, Zero, Huge) -> + {'EXIT',{badarith,_}} = (catch (B / (A / Zero))), + {'EXIT',{badarith,_}} = (catch (B * (A / Zero))), + {'EXIT',{badarith,_}} = (catch (B / (Huge * Huge))), + {'EXIT',{badarith,_}} = (catch (B * (Huge * Huge))), + {'EXIT',{badarith,_}} = (catch (B / (Huge + Huge))), + {'EXIT',{badarith,_}} = (catch (B * (Huge + Huge))), + {'EXIT',{badarith,_}} = (catch (B / (-Huge - Huge))), + {'EXIT',{badarith,_}} = (catch (B * (-Huge - Huge))). diff --git a/erts/emulator/test/fun_r12_SUITE.erl b/erts/emulator/test/fun_r13_SUITE.erl index 3b1dfc9825..76ddf9fec9 100644 --- a/erts/emulator/test/fun_r12_SUITE.erl +++ b/erts/emulator/test/fun_r13_SUITE.erl @@ -17,10 +17,10 @@ %% %CopyrightEnd% %% --module(fun_r12_SUITE). --compile(r12). +-module(fun_r13_SUITE). +-compile(r13). --export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, +-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, init_per_group/2,end_per_group/2, init_per_testcase/2,end_per_testcase/2,dist_old_release/1]). @@ -29,10 +29,10 @@ suite() -> [{ct_hooks,[ts_install_cth]}]. -all() -> +all() -> [dist_old_release]. -groups() -> +groups() -> []. init_per_suite(Config) -> diff --git a/erts/etc/common/erlexec.c b/erts/etc/common/erlexec.c index 8d119984df..19b3bb82ef 100644 --- a/erts/etc/common/erlexec.c +++ b/erts/etc/common/erlexec.c @@ -121,6 +121,7 @@ static char *plusM_other_switches[] = { /* +s arguments with values */ static char *pluss_val_switches[] = { "bt", + "cl", "ct", "wt", "ss", diff --git a/erts/lib_src/common/erl_memory_trace_parser.c b/erts/lib_src/common/erl_memory_trace_parser.c index 54c3dfadec..ebf7182913 100644 --- a/erts/lib_src/common/erl_memory_trace_parser.c +++ b/erts/lib_src/common/erl_memory_trace_parser.c @@ -368,12 +368,16 @@ emtp_state_destroy(emtp_state *statep) #define GET_UI8(UI, BP) ((UI) = *((BP)++)) +#define SKIP_UI8(BP) ((BP)++) + #define GET_UI16(UI, BP) \ do { \ (UI) = ((( (usgnd_int_16) (BP)[0]) << 8) \ | ((usgnd_int_16) (BP)[1])); \ (BP) += UI16_SZ; \ } while(0) +#define SKIP_UI16(BP) ((BP) += UI16_SZ) + #define GET_UI32(UI, BP) \ do { \ @@ -383,6 +387,7 @@ emtp_state_destroy(emtp_state *statep) | ( (usgnd_int_32) (BP)[3])); \ (BP) += UI32_SZ; \ } while(0) +#define SKIP_UI32(BP) ((BP) += UI32_SZ) #define GET_UI64(UI, BP) \ do { \ @@ -396,6 +401,7 @@ emtp_state_destroy(emtp_state *statep) | ( (usgnd_int_64) (BP)[7])); \ (BP) += UI64_SZ; \ } while(0) +#define SKIP_UI64(BP) ((BP) += UI64_SZ) #define GET_VSZ_UI16(UI, BP, MSB) \ do { \ @@ -1267,11 +1273,10 @@ parse_header(emtp_state *statep, switch (statep->version.major) { case 1: { - usgnd_int_32 hdr_sz; NEED(2*UI32_SZ + 2*UI16_SZ, trace_size); GET_UI32(statep->flags, tracep); - GET_UI32(hdr_sz, tracep); /* ignore this; may contain garbage! */ + SKIP_UI32(tracep); /* ignore this; may contain garbage! */ GET_UI16(statep->max_allocator_ix, tracep); GET_UI16(statep->max_block_type_ix, tracep); @@ -1564,13 +1569,13 @@ parse_header(emtp_state *statep, } case ERTS_MT_BLOCK_TYPE_HDR_TAG: { - usgnd_int_16 bt_ix, a_ix, btflgs; + usgnd_int_16 bt_ix, a_ix; if (entry_sz < UI8_SZ + 3*UI16_SZ + UI8_SZ + 0 + UI16_SZ) ERROR(EMTP_PARSE_ERROR); - GET_UI16(btflgs, c_p); + SKIP_UI16(c_p); /* bitflags */ GET_UI16(bt_ix, c_p); if (bt_ix > statep->max_block_type_ix) ERROR(EMTP_PARSE_ERROR); diff --git a/erts/start_scripts/Makefile b/erts/start_scripts/Makefile index 4df7568484..c2576ee4cc 100644 --- a/erts/start_scripts/Makefile +++ b/erts/start_scripts/Makefile @@ -1,7 +1,7 @@ # # %CopyrightBegin% # -# Copyright Ericsson AB 1997-2010. All Rights Reserved. +# Copyright Ericsson AB 1997-2011. 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 @@ -74,7 +74,7 @@ $(SS_ROOT)/start_clean.script \ $(SS_ROOT)/start_clean.boot: $(SS_ROOT)/start_clean.rel $(INSTALL_DIR) $(SS_TMP) ( cd $(SS_TMP) && \ - $(ERLC) $(SASL_FLAGS) $(SCRIPT_PATH) -o $(SS_ROOT) $< ) + $(ERLC) $(SASL_FLAGS) $(SCRIPT_PATH) +no_warn_sasl -o $(SS_ROOT) $< ) $(SS_ROOT)/start_sasl.script \ $(SS_ROOT)/start_sasl.boot: $(SS_ROOT)/start_sasl.rel @@ -128,7 +128,7 @@ $(SS_ROOT)/start_all_example.rel: $(SS_ROOT)/start_all_example.rel.src \ $(ERL_TOP)/bin/start.script: $(INSTALL_DIR) $(SS_TMP) ( cd $(SS_TMP) && \ - $(ERLC) $(SCRIPT_PATH) +otp_build -o $@ $(SS_ROOT)/start_clean.rel ) + $(ERLC) $(SCRIPT_PATH) +no_warn_sasl +otp_build -o $@ $(SS_ROOT)/start_clean.rel ) $(ERL_TOP)/bin/start_sasl.script: $(INSTALL_DIR) $(SS_TMP) @@ -138,18 +138,20 @@ $(ERL_TOP)/bin/start_sasl.script: $(ERL_TOP)/bin/start_clean.script: $(INSTALL_DIR) $(SS_TMP) ( cd $(SS_TMP) && \ - $(ERLC) $(SCRIPT_PATH) +otp_build -o $@ $(SS_ROOT)/start_clean.rel ) + $(ERLC) $(SCRIPT_PATH) +no_warn_sasl +otp_build -o $@ $(SS_ROOT)/start_clean.rel ) ## Special target used from system/build/Makefile for source code release bootstrap. bootstrap_scripts: $(SS_ROOT)/start_clean.rel $(INSTALL_DIR) $(TESTROOT)/bin $(INSTALL_DIR) $(SS_TMP) ( cd $(SS_TMP) && \ - $(ERLC) $(BOOTSTRAP_SCRIPT_PATH) +otp_build +no_module_tests \ - -o $(TESTROOT)/bin/start.script $(SS_ROOT)/start_clean.rel ) + $(ERLC) $(BOOTSTRAP_SCRIPT_PATH) +no_warn_sasl +otp_build \ + +no_module_tests -o $(TESTROOT)/bin/start.script \ + $(SS_ROOT)/start_clean.rel ) ( cd $(SS_TMP) && \ - $(ERLC) $(BOOTSTRAP_SCRIPT_PATH) +otp_build +no_module_tests \ - -o $(TESTROOT)/bin/start_clean.script $(SS_ROOT)/start_clean.rel ) + $(ERLC) $(BOOTSTRAP_SCRIPT_PATH) +no_warn_sasl +otp_build \ + +no_module_tests -o $(TESTROOT)/bin/start_clean.script \ + $(SS_ROOT)/start_clean.rel ) clean: $(RM) $(REL_SCRIPTS) $(INSTALL_SCRIPTS) diff --git a/erts/test/erlc_SUITE.erl b/erts/test/erlc_SUITE.erl index a9e28672e3..6c0d662126 100644 --- a/erts/test/erlc_SUITE.erl +++ b/erts/test/erlc_SUITE.erl @@ -154,7 +154,8 @@ compile_mib(Config) when is_list(Config) -> ?line BadFile = filename:join(SrcDir, "BAD-MIB.mib"), ?line run(Config, Cmd, BadFile, "", - ["Error: syntax error before: mibs\$", "compilation_failed_ERROR_"]), + ["BAD-MIB.mib: 1: syntax error before: mibs\$", + "compilation_failed_ERROR_"]), %% Make sure that no -I option works. @@ -237,6 +238,12 @@ num_d_options() -> %% of arguments is 16383. %% See: http://www.in-ulm.de/~mascheck/various/argmax/ 5440; + {{unix,darwin},{Major,_,_}} when Major >= 11 -> + %% "getconf ARG_MAX" still reports 262144 (as in previous + %% version of MacOS X), but the useful space seem to have + %% shrunk significantly (or possibly the number of arguments). + %% 7673 + 7500; {_,_} -> 12000 end. diff --git a/erts/vsn.mk b/erts/vsn.mk index d56d03146d..1b3cd67947 100644 --- a/erts/vsn.mk +++ b/erts/vsn.mk @@ -18,7 +18,7 @@ # VSN = 5.9 -SYSTEM_VSN = R15A +SYSTEM_VSN = R15B # Port number 4365 in 4.2 # Port number 4366 in 4.3 |