diff options
Diffstat (limited to 'erts')
38 files changed, 494 insertions, 239 deletions
diff --git a/erts/Makefile.in b/erts/Makefile.in index 0bcb784972..51aee98a05 100644 --- a/erts/Makefile.in +++ b/erts/Makefile.in @@ -74,14 +74,12 @@ local_setup: $(ERL_TOP)/bin/escript $(ERL_TOP)/bin/escript.exe \ $(ERL_TOP)/bin/dialyzer $(ERL_TOP)/bin/dialyzer.exe \ $(ERL_TOP)/bin/typer $(ERL_TOP)/bin/typer.exe \ - $(ERL_TOP)/bin/run_test $(ERL_TOP)/bin/run_test.exe \ $(ERL_TOP)/bin/ct_run $(ERL_TOP)/bin/ct_run.exe \ $(ERL_TOP)/bin/start*.boot $(ERL_TOP)/bin/start*.script @if [ "X$(TARGET)" = "Xwin32" ]; then \ cp $(ERL_TOP)/bin/$(TARGET)/dialyzer.exe $(ERL_TOP)/bin/dialyzer.exe; \ cp $(ERL_TOP)/bin/$(TARGET)/typer.exe $(ERL_TOP)/bin/typer.exe; \ cp $(ERL_TOP)/bin/$(TARGET)/ct_run.exe $(ERL_TOP)/bin/ct_run.exe; \ - cp $(ERL_TOP)/bin/$(TARGET)/ct_run.exe $(ERL_TOP)/bin/run_test.exe; \ cp $(ERL_TOP)/bin/$(TARGET)/erlc.exe $(ERL_TOP)/bin/erlc.exe; \ cp $(ERL_TOP)/bin/$(TARGET)/erl.exe $(ERL_TOP)/bin/erl.exe; \ cp $(ERL_TOP)/bin/$(TARGET)/werl.exe $(ERL_TOP)/bin/werl.exe; \ @@ -102,7 +100,6 @@ local_setup: cp $(ERL_TOP)/bin/$(TARGET)/dialyzer $(ERL_TOP)/bin/dialyzer; \ cp $(ERL_TOP)/bin/$(TARGET)/typer $(ERL_TOP)/bin/typer; \ cp $(ERL_TOP)/bin/$(TARGET)/ct_run $(ERL_TOP)/bin/ct_run; \ - ln -s $(ERL_TOP)/bin/ct_run $(ERL_TOP)/bin/run_test; \ cp $(ERL_TOP)/bin/$(TARGET)/erlc $(ERL_TOP)/bin/erlc; \ cp $(ERL_TOP)/bin/$(TARGET)/escript $(ERL_TOP)/bin/escript; \ chmod 755 $(ERL_TOP)/bin/erl $(ERL_TOP)/bin/erlc \ diff --git a/erts/configure.in b/erts/configure.in index 1e3a607a6f..7257751068 100644 --- a/erts/configure.in +++ b/erts/configure.in @@ -1923,12 +1923,21 @@ fi AC_CHECK_FUNCS([getipnodebyname getipnodebyaddr gethostbyname2]) AC_CHECK_FUNCS([ieee_handler fpsetmask finite isnan isinf res_gethostbyname dlopen \ - pread pwrite writev memmove strerror strerror_r strncasecmp \ + pread pwrite memmove strerror strerror_r strncasecmp \ gethrtime localtime_r gmtime_r inet_pton mmap mremap memcpy mallopt \ sbrk _sbrk __sbrk brk _brk __brk \ flockfile fstat strlcpy strlcat setsid posix2time time2posix \ setlocale nl_langinfo poll]) +dnl writev on OS X snow leopard is broken for files > 4GB +case $host_os in + darwin10.8.0) + AC_MSG_CHECKING([for writev]) + AC_MSG_RESULT(no, not stable on OS X Snow Leopard) ;; + *) + AC_CHECK_FUNCS([writev]) ;; +esac + AC_CHECK_DECLS([posix2time, time2posix],,,[#include <time.h>]) disable_vfork=false diff --git a/erts/doc/src/erl.xml b/erts/doc/src/erl.xml index f354d68d45..bd03fb4970 100644 --- a/erts/doc/src/erl.xml +++ b/erts/doc/src/erl.xml @@ -615,6 +615,28 @@ debugging.</item> </taglist> </item> + <tag><marker id="+pc"/><marker id="max_processes"><c><![CDATA[+pc Range]]></c></marker></tag> + <item> + <p>Sets the range of characters that the system will consider printable in heuristic detection of strings. This typically affects the shell, debugger and io:format functions (when ~tp is used in the format string).</p> + <p>Currently two values for the <c>Range</c> are supported: + <taglist> + <tag><c>latin1</c></tag> <item>The default. Only characters + in the ISO-latin-1 range can be considered printable, which means + that a character with a code point > 255 will never be + considered printable and that lists containing such + characters will be displayed as lists of integers rather + than text strings by tools.</item> + <tag><c>unicode</c></tag> + <item>All printable Unicode characters are considered when + determining if a list of integers is to be displayed in + string syntax. This may give unexpected results if for + example your font does not cover all Unicode + characters.</item> + </taglist> + </p> + <p>Se also <seealso marker="stdlib:io#printable_range/0"> + io:printable_range/0</seealso>.</p> + </item> <tag><marker id="+P"/><marker id="max_processes"><c><![CDATA[+P Number]]></c></marker></tag> <item> <p>Sets the maximum number of simultaneously existing processes for this @@ -985,15 +1007,12 @@ documentation of the <seealso marker="#+sbt">+sbt</seealso> flag. </p> </item> - <tag><marker id="+sws"><c>+sws default|legacy|proposal</c></marker></tag> + <tag><marker id="+sws"><c>+sws default|legacy</c></marker></tag> <item> - <p>Set scheduler wakeup strategy. Default is <c>legacy</c> (has been - used since OTP-R13B). The <c>proposal</c> strategy is the currently - proposed strategy for OTP-R16. Note that the <c>proposal</c> strategy - might change during OTP-R15. + <p> + Set scheduler wakeup strategy. Default strategy changed in erts-5.10/OTP-R16A. This strategy was previously known as <c>proposal</c> in OTP-R15. The <c>legacy</c> strategy was used as default from R13 up to and including R15. </p> - <p><em>NOTE:</em> This flag may be removed or changed at any time - without prior notice. + <p><em>NOTE:</em> This flag may be removed or changed at any time without prior notice. </p> </item> <tag><marker id="+swt"><c>+swt very_low|low|medium|high|very_high</c></marker></tag> diff --git a/erts/emulator/Makefile.in b/erts/emulator/Makefile.in index 7033ea0a3d..2877e58cdf 100644 --- a/erts/emulator/Makefile.in +++ b/erts/emulator/Makefile.in @@ -20,7 +20,7 @@ include $(ERL_TOP)/make/target.mk include ../vsn.mk include $(ERL_TOP)/make/$(TARGET)/otp.mk -include $(TARGET)/gen_git_version.mk +-include $(TARGET)/gen_git_version.mk ENABLE_ALLOC_TYPE_VARS = @ENABLE_ALLOC_TYPE_VARS@ diff --git a/erts/emulator/beam/atom.c b/erts/emulator/beam/atom.c index b69f979397..84d2d5e3ed 100644 --- a/erts/emulator/beam/atom.c +++ b/erts/emulator/beam/atom.c @@ -132,9 +132,17 @@ atom_hash(Atom* obj) byte* p = obj->name; int len = obj->len; HashValue h = 0, g; + byte v; while(len--) { - h = (h << 4) + *p++; + v = *p++; + /* latin1 clutch for r16 */ + if ((v & 0xFE) == 0xC2 && (*p & 0xC0) == 0x80) { + v = (v << 6) | (*p & 0x3F); + p++; len--; + } + /* normal hashpjw follows for v */ + h = (h << 4) + v; if ((g = h & 0xf0000000)) { h ^= (g >> 24); h ^= g; diff --git a/erts/emulator/beam/beam_bif_load.c b/erts/emulator/beam/beam_bif_load.c index 73264214ce..8a8239493a 100644 --- a/erts/emulator/beam/beam_bif_load.c +++ b/erts/emulator/beam/beam_bif_load.c @@ -1081,7 +1081,21 @@ beam_make_current_old(Process *c_p, ErtsProcLocks c_p_locks, Eterm module) static int is_native(BeamInstr* code) { - return ((Eterm *)code[MI_FUNCTIONS])[1] != 0; + Uint i, num_functions = code[MI_NUM_FUNCTIONS]; + + /* Check NativeAdress of first real function in module + */ + for (i=0; i<num_functions; i++) { + BeamInstr* func_info = (BeamInstr *) code[MI_FUNCTIONS+i]; + Eterm name = (Eterm) func_info[3]; + + if (is_atom(name)) { + return func_info[1] != 0; + } + else ASSERT(is_nil(name)); /* ignore BIF stubs */ + } + /* Not a single non-BIF function? */ + return 0; } diff --git a/erts/emulator/beam/beam_catches.c b/erts/emulator/beam/beam_catches.c index 7c92408eea..d374d0469e 100644 --- a/erts/emulator/beam/beam_catches.c +++ b/erts/emulator/beam/beam_catches.c @@ -160,10 +160,9 @@ void beam_catches_delmod(unsigned head, BeamInstr *code, unsigned code_bytes, } if( (char*)p->beam_catches[i].cp - (char*)code >= code_bytes ) { erl_exit(1, - "beam_catches_delmod: item %#x has cp %#lx which is not " - "in module's range [%#lx,%#lx[\r\n", - i, (long)p->beam_catches[i].cp, - (long)code, (long)((char*)code + code_bytes)); + "beam_catches_delmod: item %#x has cp %p which is not " + "in module's range [%p,%p[\r\n", + i, p->beam_catches[i].cp, code, ((char*)code + code_bytes)); } p->beam_catches[i].cp = 0; cdr = p->beam_catches[i].cdr; diff --git a/erts/emulator/beam/bif.tab b/erts/emulator/beam/bif.tab index b74dc5c3fe..8bc994c8c3 100644 --- a/erts/emulator/beam/bif.tab +++ b/erts/emulator/beam/bif.tab @@ -569,6 +569,8 @@ bif erlang:float_to_binary/1 bif erlang:float_to_binary/2 bif erlang:binary_to_float/1 +bif io:printable_range/0 + # # Obsolete # diff --git a/erts/emulator/beam/erl_db_util.c b/erts/emulator/beam/erl_db_util.c index fc1c946c7d..713ac0ba18 100644 --- a/erts/emulator/beam/erl_db_util.c +++ b/erts/emulator/beam/erl_db_util.c @@ -3415,8 +3415,7 @@ static DMCRet dmc_one_term(DMCContext *context, } default: erl_exit(1, "db_match_compile: " - "Bad object on heap: 0x%08lx\n", - (unsigned long) c); + "Bad object on heap: 0x%bex\n", c); } return retOk; } @@ -4861,7 +4860,7 @@ static Eterm my_copy_struct(Eterm t, Eterm **hp, ErlOffHeap* off_heap) ret = copy_struct(b,sz,hp,off_heap); } else { erl_exit(1, "Trying to constant-copy non constant expression " - "0x%08x in (d)ets:match compilation.", (unsigned long) t); + "0x%bex in (d)ets:match compilation.", t); } } else { sz = size_object(t); @@ -5395,7 +5394,7 @@ void db_match_dis(Binary *bp) erts_printf("Caller\n"); break; default: - erts_printf("??? (0x%08x)\n", *t); + erts_printf("??? (0x%bpx)\n", *t); ++t; break; } @@ -5407,13 +5406,13 @@ void db_match_dis(Binary *bp) first = 0; else erts_printf(", "); - erts_printf("0x%08x", (unsigned long) tmp); + erts_printf("%p", tmp); } erts_printf("}\n"); erts_printf("num_bindings: %d\n", prog->num_bindings); erts_printf("heap_size: %beu\n", prog->heap_size); erts_printf("stack_offset: %beu\n", prog->stack_offset); - erts_printf("text: 0x%08x\n", (unsigned long) prog->text); + erts_printf("text: %p\n", prog->text); erts_printf("stack_size: %d (words)\n", prog->heap_size-prog->stack_offset); } diff --git a/erts/emulator/beam/erl_gc.c b/erts/emulator/beam/erl_gc.c index a33085315a..293d9fa3ec 100644 --- a/erts/emulator/beam/erl_gc.c +++ b/erts/emulator/beam/erl_gc.c @@ -231,7 +231,7 @@ erts_next_heap_size(Uint size, Uint offset) low = mid + 1; } } - erl_exit(1, "no next heap size found: %lu, offset %lu\n", (unsigned long)size, (unsigned long)offset); + erl_exit(1, "no next heap size found: %beu, offset %beu\n", size, offset); } return 0; } diff --git a/erts/emulator/beam/erl_init.c b/erts/emulator/beam/erl_init.c index ec3e0d54cb..83853dcd43 100644 --- a/erts/emulator/beam/erl_init.c +++ b/erts/emulator/beam/erl_init.c @@ -496,7 +496,7 @@ void erts_usage(void) erts_fprintf(stderr, "-d don't write a crash dump for internally detected errors\n"); erts_fprintf(stderr, " (halt(String) will still produce a crash dump)\n"); - + erts_fprintf(stderr, "-fn[u|a|l] Control how filenames are interpreted\n"); erts_fprintf(stderr, "-hms size set minimum heap size in words (default %d)\n", H_DEFAULT_SIZE); erts_fprintf(stderr, "-hmbs size set minimum binary virtual heap size in words (default %d)\n", @@ -509,7 +509,7 @@ void erts_usage(void) erts_fprintf(stderr, " Note that this flag is deprecated!\n"); erts_fprintf(stderr, "-M<X> <Y> memory allocator switches,\n"); erts_fprintf(stderr, " see the erts_alloc(3) documentation for more info.\n"); - + erts_fprintf(stderr, "-pc <set> Control what characters are considered printable (default latin1)\n"); erts_fprintf(stderr, "-P number set maximum number of processes on this node,\n"); erts_fprintf(stderr, " valid range is [%d-%d]\n", ERTS_MIN_PROCESSES, ERTS_MAX_PROCESSES); @@ -979,13 +979,30 @@ erl_start(int argc, char **argv) VERBOSE(DEBUG_SYSTEM, ("using display items %d\n",display_items)); break; + case 'p': + if (!strncmp(argv[i],"-pc",3)) { + int printable_chars = ERL_PRINTABLE_CHARACTERS_LATIN1; + arg = get_arg(argv[i]+3, argv[i+1], &i); + if (!strcmp(arg,"unicode")) { + printable_chars = ERL_PRINTABLE_CHARACTERS_UNICODE; + } else if (strcmp(arg,"latin1")) { + erts_fprintf(stderr, "bad range of printable " + "characters: %s\n", arg); + erts_usage(); + } + erts_set_printable_characters(printable_chars); + break; + } else { + erts_fprintf(stderr, "%s unknown flag %s\n", argv[0], argv[i]); + erts_usage(); + } case 'f': if (!strncmp(argv[i],"-fn",3)) { int warning_type = ERL_FILENAME_WARNING_WARNING; arg = get_arg(argv[i]+3, argv[i+1], &i); switch (*arg) { case 'u': - switch (*(argv[i]+4)) { + switch (*(arg+1)) { case 'w': case 0: break; @@ -997,7 +1014,7 @@ erl_start(int argc, char **argv) break; default: erts_fprintf(stderr, "bad type of warnings for " - "wrongly coded filename: %s\n", argv[i]+4); + "wrongly coded filename: %s\n", arg+1); erts_usage(); } erts_set_user_requested_filename_encoding @@ -1014,7 +1031,7 @@ erl_start(int argc, char **argv) ); break; case 'a': - switch (*(argv[i]+4)) { + switch (*(arg+1)) { case 'w': case 0: break; @@ -1026,7 +1043,7 @@ erl_start(int argc, char **argv) break; default: erts_fprintf(stderr, "bad type of warnings for " - "wrongly coded filename: %s\n", argv[i]+4); + "wrongly coded filename: %s\n", arg+1); erts_usage(); } erts_set_user_requested_filename_encoding diff --git a/erts/emulator/beam/erl_printf_term.c b/erts/emulator/beam/erl_printf_term.c index 2320b64295..ce544503bd 100644 --- a/erts/emulator/beam/erl_printf_term.c +++ b/erts/emulator/beam/erl_printf_term.c @@ -57,17 +57,17 @@ do { \ (CNT) += res__; \ } while (0) -#define PRINT_ULONG(CNT, FN, ARG, C, P, W, I) \ +#define PRINT_UWORD(CNT, FN, ARG, C, P, W, I) \ do { \ - int res__ = erts_printf_ulong((FN), (ARG), (C), (P), (W), (I)); \ + int res__ = erts_printf_uword((FN), (ARG), (C), (P), (W), (I)); \ if (res__ < 0) \ return res__; \ (CNT) += res__; \ } while (0) -#define PRINT_SLONG(CNT, FN, ARG, C, P, W, I) \ +#define PRINT_SWORD(CNT, FN, ARG, C, P, W, I) \ do { \ - int res__ = erts_printf_slong((FN), (ARG), (C), (P), (W), (I)); \ + int res__ = erts_printf_sword((FN), (ARG), (C), (P), (W), (I)); \ if (res__ < 0) \ return res__; \ (CNT) += res__; \ @@ -153,7 +153,7 @@ static int print_atom_name(fmtfn_t fn, void* arg, Eterm atom, long *dcount) if ((i < 0) || (i >= atom_table_size()) || (atom_tab(i) == NULL)) { PRINT_STRING(res, fn, arg, "<bad atom index: "); - PRINT_SLONG(res, fn, arg, 'd', 0, 1, (signed long) i); + PRINT_SWORD(res, fn, arg, 'd', 0, 1, (ErlPfSWord) i); PRINT_CHAR(res, fn, arg, '>'); return res; } @@ -203,7 +203,7 @@ static int print_atom_name(fmtfn_t fn, void* arg, Eterm atom, long *dcount) default: if (IS_CNTRL(c)) { PRINT_CHAR(res, fn, arg, '\\'); - PRINT_ULONG(res, fn, arg, 'o', 1, 3, (unsigned long) c); + PRINT_UWORD(res, fn, arg, 'o', 1, 3, (ErlPfUWord) c); } else PRINT_CHAR(res, fn, arg, (char) c); @@ -334,7 +334,7 @@ print_term(fmtfn_t fn, void* arg, Eterm obj, long *dcount, break; } case SMALL_DEF: - PRINT_SLONG(res, fn, arg, 'd', 0, 1, (signed long) signed_val(obj)); + PRINT_SWORD(res, fn, arg, 'd', 0, 1, (ErlPfSWord) signed_val(obj)); break; case BIG_DEF: { int print_res; @@ -360,36 +360,36 @@ print_term(fmtfn_t fn, void* arg, Eterm obj, long *dcount, case REF_DEF: case EXTERNAL_REF_DEF: PRINT_STRING(res, fn, arg, "#Ref<"); - PRINT_ULONG(res, fn, arg, 'u', 0, 1, - (unsigned long) ref_channel_no(wobj)); + PRINT_UWORD(res, fn, arg, 'u', 0, 1, + (ErlPfUWord) ref_channel_no(wobj)); ref_num = ref_numbers(wobj); for (i = ref_no_of_numbers(wobj)-1; i >= 0; i--) { PRINT_CHAR(res, fn, arg, '.'); - PRINT_ULONG(res, fn, arg, 'u', 0, 1, (unsigned long) ref_num[i]); + PRINT_UWORD(res, fn, arg, 'u', 0, 1, (ErlPfUWord) ref_num[i]); } PRINT_CHAR(res, fn, arg, '>'); break; case PID_DEF: case EXTERNAL_PID_DEF: PRINT_CHAR(res, fn, arg, '<'); - PRINT_ULONG(res, fn, arg, 'u', 0, 1, - (unsigned long) pid_channel_no(wobj)); + PRINT_UWORD(res, fn, arg, 'u', 0, 1, + (ErlPfUWord) pid_channel_no(wobj)); PRINT_CHAR(res, fn, arg, '.'); - PRINT_ULONG(res, fn, arg, 'u', 0, 1, - (unsigned long) pid_number(wobj)); + PRINT_UWORD(res, fn, arg, 'u', 0, 1, + (ErlPfUWord) pid_number(wobj)); PRINT_CHAR(res, fn, arg, '.'); - PRINT_ULONG(res, fn, arg, 'u', 0, 1, - (unsigned long) pid_serial(wobj)); + PRINT_UWORD(res, fn, arg, 'u', 0, 1, + (ErlPfUWord) pid_serial(wobj)); PRINT_CHAR(res, fn, arg, '>'); break; case PORT_DEF: case EXTERNAL_PORT_DEF: PRINT_STRING(res, fn, arg, "#Port<"); - PRINT_ULONG(res, fn, arg, 'u', 0, 1, - (unsigned long) port_channel_no(wobj)); + PRINT_UWORD(res, fn, arg, 'u', 0, 1, + (ErlPfUWord) port_channel_no(wobj)); PRINT_CHAR(res, fn, arg, '.'); - PRINT_ULONG(res, fn, arg, 'u', 0, 1, - (unsigned long) port_number(wobj)); + PRINT_UWORD(res, fn, arg, 'u', 0, 1, + (ErlPfUWord) port_number(wobj)); PRINT_CHAR(res, fn, arg, '>'); break; case LIST_DEF: @@ -446,7 +446,7 @@ print_term(fmtfn_t fn, void* arg, Eterm obj, long *dcount, PRINT_STRING(res, fn, arg, "<<1 byte>>"); else { PRINT_STRING(res, fn, arg, "<<"); - PRINT_ULONG(res, fn, arg, 'u', 0, 1, (unsigned long) pb->size); + PRINT_UWORD(res, fn, arg, 'u', 0, 1, (ErlPfUWord) pb->size); PRINT_STRING(res, fn, arg, " bytes>>"); } } @@ -462,8 +462,8 @@ print_term(fmtfn_t fn, void* arg, Eterm obj, long *dcount, PRINT_CHAR(res, fn, arg, '.'); PRINT_BUF(res, fn, arg, name->name, name->len); PRINT_CHAR(res, fn, arg, '.'); - PRINT_SLONG(res, fn, arg, 'd', 0, 1, - (signed long) ep->code[2]); + PRINT_SWORD(res, fn, arg, 'd', 0, 1, + (ErlPfSWord) ep->code[2]); PRINT_CHAR(res, fn, arg, '>'); } break; @@ -475,11 +475,11 @@ print_term(fmtfn_t fn, void* arg, Eterm obj, long *dcount, PRINT_STRING(res, fn, arg, "#Fun<"); PRINT_BUF(res, fn, arg, ap->name, ap->len); PRINT_CHAR(res, fn, arg, '.'); - PRINT_SLONG(res, fn, arg, 'd', 0, 1, - (signed long) funp->fe->old_index); + PRINT_SWORD(res, fn, arg, 'd', 0, 1, + (ErlPfSWord) funp->fe->old_index); PRINT_CHAR(res, fn, arg, '.'); - PRINT_SLONG(res, fn, arg, 'd', 0, 1, - (signed long) funp->fe->old_uniq); + PRINT_SWORD(res, fn, arg, 'd', 0, 1, + (ErlPfSWord) funp->fe->old_uniq); PRINT_CHAR(res, fn, arg, '>'); } break; @@ -498,10 +498,13 @@ print_term(fmtfn_t fn, void* arg, Eterm obj, long *dcount, } int -erts_printf_term(fmtfn_t fn, void* arg, unsigned long term, long precision, - unsigned long* term_base) +erts_printf_term(fmtfn_t fn, void* arg, ErlPfEterm term, long precision, + ErlPfEterm* term_base) { - int res = print_term(fn, arg, (Eterm)term, &precision, (Eterm*)term_base); + int res; + ASSERT(sizeof(ErlPfEterm) == sizeof(Eterm)); + + res = print_term(fn, arg, (Eterm)term, &precision, (Eterm*)term_base); if (res < 0) return res; if (precision <= 0) diff --git a/erts/emulator/beam/erl_printf_term.h b/erts/emulator/beam/erl_printf_term.h index a48a3de34c..d9bf79a5ce 100644 --- a/erts/emulator/beam/erl_printf_term.h +++ b/erts/emulator/beam/erl_printf_term.h @@ -21,6 +21,6 @@ #define ERL_PRINTF_TERM_H__ #include "erl_printf_format.h" -int erts_printf_term(fmtfn_t fn, void* arg, unsigned long term, long precision, - unsigned long* term_base); +int erts_printf_term(fmtfn_t fn, void* arg, ErlPfEterm term, long precision, + ErlPfEterm* term_base); #endif diff --git a/erts/emulator/beam/erl_process.c b/erts/emulator/beam/erl_process.c index 96af19fb83..00247b387a 100644 --- a/erts/emulator/beam/erl_process.c +++ b/erts/emulator/beam/erl_process.c @@ -4311,8 +4311,7 @@ erts_sched_set_wakeup_other_type(char *str) wakeup_other.type = type; return 0; #else - if (sys_strcmp(str, "proposal") == 0 || sys_strcmp(str, "default") == 0 || - sys_strcmp(str, "legacy") == 0) { + if (sys_strcmp(str, "default") == 0 || sys_strcmp(str, "legacy") == 0) { return 0; } return EINVAL; diff --git a/erts/emulator/beam/erl_smp.h b/erts/emulator/beam/erl_smp.h index 34c90c0bda..0dd9e29e8e 100644 --- a/erts/emulator/beam/erl_smp.h +++ b/erts/emulator/beam/erl_smp.h @@ -259,6 +259,9 @@ ERTS_GLB_INLINE void erts_smp_thr_sigwait(const sigset_t *set, int *sig); #define erts_smp_dw_atomic_read_wb erts_dw_atomic_read_wb #define erts_smp_dw_atomic_cmpxchg_wb erts_dw_atomic_cmpxchg_wb +#define erts_smp_dw_atomic_set_dirty erts_dw_atomic_set_dirty +#define erts_smp_dw_atomic_read_dirty erts_dw_atomic_read_dirty + /* Word size atomics */ #define erts_smp_atomic_init_nob erts_atomic_init_nob @@ -366,6 +369,9 @@ ERTS_GLB_INLINE void erts_smp_thr_sigwait(const sigset_t *set, int *sig); #define erts_smp_atomic_cmpxchg_wb erts_atomic_cmpxchg_wb #define erts_smp_atomic_read_bset_wb erts_atomic_read_bset_wb +#define erts_smp_atomic_set_dirty erts_atomic_set_dirty +#define erts_smp_atomic_read_dirty erts_atomic_read_dirty + /* 32-bit atomics */ #define erts_smp_atomic32_init_nob erts_atomic32_init_nob @@ -473,6 +479,9 @@ ERTS_GLB_INLINE void erts_smp_thr_sigwait(const sigset_t *set, int *sig); #define erts_smp_atomic32_cmpxchg_wb erts_atomic32_cmpxchg_wb #define erts_smp_atomic32_read_bset_wb erts_atomic32_read_bset_wb +#define erts_smp_atomic32_set_dirty erts_atomic32_set_dirty +#define erts_smp_atomic32_read_dirty erts_atomic32_read_dirty + #else /* !ERTS_SMP */ /* Double word size atomics */ @@ -512,6 +521,9 @@ ERTS_GLB_INLINE void erts_smp_thr_sigwait(const sigset_t *set, int *sig); #define erts_smp_dw_atomic_read_wb erts_no_dw_atomic_read #define erts_smp_dw_atomic_cmpxchg_wb erts_no_dw_atomic_cmpxchg +#define erts_smp_dw_atomic_set_dirty erts_no_dw_atomic_set +#define erts_smp_dw_atomic_read_dirty erts_no_dw_atomic_read + /* Word size atomics */ #define erts_smp_atomic_init_nob erts_no_atomic_set @@ -619,6 +631,9 @@ ERTS_GLB_INLINE void erts_smp_thr_sigwait(const sigset_t *set, int *sig); #define erts_smp_atomic_cmpxchg_wb erts_no_atomic_cmpxchg #define erts_smp_atomic_read_bset_wb erts_no_atomic_read_bset +#define erts_smp_atomic_set_dirty erts_no_atomic_set +#define erts_smp_atomic_read_dirty erts_no_atomic_read + /* 32-bit atomics */ #define erts_smp_atomic32_init_nob erts_no_atomic32_set @@ -726,6 +741,9 @@ ERTS_GLB_INLINE void erts_smp_thr_sigwait(const sigset_t *set, int *sig); #define erts_smp_atomic32_cmpxchg_wb erts_no_atomic32_cmpxchg #define erts_smp_atomic32_read_bset_wb erts_no_atomic32_read_bset +#define erts_smp_atomic32_set_dirty erts_no_atomic32_set +#define erts_smp_atomic32_read_dirty erts_no_atomic32_read + #endif /* !ERTS_SMP */ #if ERTS_GLB_INLINE_INCL_FUNC_DEF diff --git a/erts/emulator/beam/erl_thr_queue.c b/erts/emulator/beam/erl_thr_queue.c index f07964a265..ee2ff765e0 100644 --- a/erts/emulator/beam/erl_thr_queue.c +++ b/erts/emulator/beam/erl_thr_queue.c @@ -113,6 +113,11 @@ sl_element_free(ErtsThrQElement_t *p) #endif +#define ErtsThrQDirtyReadEl(A) \ + ((ErtsThrQElement_t *) erts_atomic_read_dirty((A))) +#define ErtsThrQDirtySetEl(A, V) \ + erts_atomic_set_dirty((A), (erts_aint_t) (V)) + typedef union { ErtsThrQ_t q; char align__[ERTS_ALC_CACHE_LINE_ALIGN_SIZE(sizeof(ErtsThrQ_t))]; @@ -137,7 +142,7 @@ erts_thr_q_initialize(ErtsThrQ_t *q, ErtsThrQInit_t *qi) q->last = NULL; q->q.blk = NULL; #else - erts_atomic_init_nob(&q->tail.data.marker.next.atmc, ERTS_AINT_NULL); + erts_atomic_init_nob(&q->tail.data.marker.next, ERTS_AINT_NULL); q->tail.data.marker.data.ptr = NULL; erts_atomic_init_nob(&q->tail.data.last, (erts_aint_t) &q->tail.data.marker); @@ -150,7 +155,7 @@ erts_thr_q_initialize(ErtsThrQ_t *q, ErtsThrQInit_t *qi) if (!q->tail.data.notify) q->tail.data.notify = noop_callback; - q->head.head.ptr = &q->tail.data.marker; + erts_atomic_init_nob(&q->head.head, (erts_aint_t) &q->tail.data.marker); q->head.live = qi->live.objects; q->head.first = &q->tail.data.marker; q->head.unref_end = &q->tail.data.marker; @@ -296,17 +301,17 @@ element_free(ErtsThrQ_t *q, ErtsThrQElement_t *el) #ifdef USE_THREADS static ERTS_INLINE ErtsThrQElement_t * -enqueue_managed(ErtsThrQ_t *q, ErtsThrQElement_t *this, int want_last) +enqueue_managed(ErtsThrQ_t *q, ErtsThrQElement_t *this) { erts_aint_t ilast, itmp; - erts_atomic_init_nob(&this->next.atmc, ERTS_AINT_NULL); + erts_atomic_init_nob(&this->next, ERTS_AINT_NULL); /* Enqueue at end of list... */ ilast = erts_atomic_read_nob(&q->tail.data.last); while (1) { ErtsThrQElement_t *last = (ErtsThrQElement_t *) ilast; - itmp = erts_atomic_cmpxchg_mb(&last->next.atmc, + itmp = erts_atomic_cmpxchg_mb(&last->next, (erts_aint_t) this, ERTS_AINT_NULL); if (itmp == ERTS_AINT_NULL) @@ -316,31 +321,57 @@ enqueue_managed(ErtsThrQ_t *q, ErtsThrQElement_t *this, int want_last) /* Move last pointer forward... */ while (1) { - if (want_last) { - if (erts_atomic_read_rb(&this->next.atmc) != ERTS_AINT_NULL) { - /* Someone else will move it forward */ - ilast = erts_atomic_read_rb(&q->tail.data.last); - return (ErtsThrQElement_t *) ilast; - } - } - else { - if (erts_atomic_read_nob(&this->next.atmc) != ERTS_AINT_NULL) { - /* Someone else will move it forward */ - return NULL; - } + if (erts_atomic_read_rb(&this->next) != ERTS_AINT_NULL) { + /* Someone else will move it forward */ + ilast = erts_atomic_read_rb(&q->tail.data.last); + return (ErtsThrQElement_t *) ilast; } itmp = erts_atomic_cmpxchg_mb(&q->tail.data.last, (erts_aint_t) this, ilast); if (ilast == itmp) - return want_last ? this : NULL; + return this; ilast = itmp; } } +static ERTS_INLINE ErtsThrQElement_t * +enqueue_marker(ErtsThrQ_t *q, ErtsThrQElement_t **headp) +{ + int maybe_notify; + erts_aint_t inext; + ErtsThrQElement_t *last, *head; + + if (headp) + head = *headp; + else + head = ErtsThrQDirtyReadEl(&q->head.head); + + ASSERT(!q->head.used_marker); + q->head.used_marker = 1; + last = enqueue_managed(q, &q->tail.data.marker); + maybe_notify = &q->tail.data.marker == last; + inext = erts_atomic_read_acqb(&head->next); + if (inext == (erts_aint_t) &q->tail.data.marker) { + ErtsThrQDirtySetEl(&q->head.head, &q->tail.data.marker); + if (headp) + *headp = &q->tail.data.marker; + } + else if (maybe_notify) { + /* + * We need to notify; otherwise, we might loose a notification + * for a concurrently inserted element. + */ + q->head.notify(q->head.arg); + } + return last; +} + + static ErtsThrQCleanState_t clean(ErtsThrQ_t *q, int max_ops, int do_notify) { + ErtsThrQElement_t *head; erts_aint_t ilast; int um_refc_ix; int ops; @@ -349,7 +380,8 @@ clean(ErtsThrQ_t *q, int max_ops, int do_notify) ErtsThrQElement_t *tmp; restart: ASSERT(q->head.first); - if (q->head.first == q->head.head.ptr) { + head = ErtsThrQDirtyReadEl(&q->head.head); + if (q->head.first == head) { q->head.clean_reached_head_count++; if (q->head.clean_reached_head_count >= ERTS_THR_Q_MAX_CLEAN_REACHED_HEAD_COUNT) { @@ -362,19 +394,20 @@ clean(ErtsThrQ_t *q, int max_ops, int do_notify) break; if (q->head.first == &q->tail.data.marker) { q->head.used_marker = 0; - q->head.first = q->head.first->next.ptr; + q->head.first = ErtsThrQDirtyReadEl(&q->head.first->next); goto restart; } tmp = q->head.first; - q->head.first = q->head.first->next.ptr; + q->head.first = ErtsThrQDirtyReadEl(&q->head.first->next); if (q->head.deq_fini.automatic) element_free(q, tmp); else { tmp->data.ptr = (void *) (UWord) q->head.live; if (!q->head.deq_fini.start) q->head.deq_fini.start = tmp; - else if (q->head.deq_fini.end->next.ptr == &q->tail.data.marker) - q->head.deq_fini.end->next.ptr = tmp; + else if (ErtsThrQDirtyReadEl(&q->head.deq_fini.end->next) + == &q->tail.data.marker) + ErtsThrQDirtySetEl(&q->head.deq_fini.end->next, tmp); q->head.deq_fini.end = tmp; } } @@ -401,21 +434,8 @@ clean(ErtsThrQ_t *q, int max_ops, int do_notify) q->head.unref_end = q->head.next.unref_end; if (!q->head.used_marker - && q->head.unref_end == (ErtsThrQElement_t *) ilast) { - q->head.used_marker = 1; - ilast = (erts_aint_t) enqueue_managed(q, - &q->tail.data.marker, - 1); - if (q->head.head.ptr == q->head.unref_end) { - ErtsThrQElement_t *next; - next = ((ErtsThrQElement_t *) - erts_atomic_read_acqb(&q->head.head.ptr->next.atmc)); - if (next == &q->tail.data.marker) { - q->head.head.ptr->next.ptr = &q->tail.data.marker; - q->head.head.ptr = &q->tail.data.marker; - } - } - } + && q->head.unref_end == (ErtsThrQElement_t *) ilast) + ilast = (erts_aint_t) enqueue_marker(q, NULL); if (q->head.unref_end == (ErtsThrQElement_t *) ilast) ERTS_SMP_MEMORY_BARRIER; @@ -436,20 +456,16 @@ clean(ErtsThrQ_t *q, int max_ops, int do_notify) } #endif - if (q->head.first == q->head.head.ptr) { + head = ErtsThrQDirtyReadEl(&q->head.head); + if (q->head.first == head) { inspect_head: if (!q->head.used_marker) { erts_aint_t inext; - inext = erts_atomic_read_acqb(&q->head.head.ptr->next.atmc); + inext = erts_atomic_read_acqb(&head->next); if (inext == ERTS_AINT_NULL) { - q->head.used_marker = 1; - (void) enqueue_managed(q, &q->tail.data.marker, 0); - inext = erts_atomic_read_acqb(&q->head.head.ptr->next.atmc); - if (inext == (erts_aint_t) &q->tail.data.marker) { - q->head.head.ptr->next.ptr = &q->tail.data.marker; - q->head.head.ptr = &q->tail.data.marker; + enqueue_marker(q, &head); + if (head == &q->tail.data.marker) goto check_thr_progress; - } } } @@ -506,26 +522,27 @@ erts_thr_q_inspect(ErtsThrQ_t *q, int ensure_empty) #ifndef USE_THREADS return ERTS_THR_Q_CLEAN; #else + ErtsThrQElement_t *head = ErtsThrQDirtyReadEl(&q->head.head); if (ensure_empty) { erts_aint_t inext; - inext = erts_atomic_read_acqb(&q->head.head.ptr->next.atmc); + inext = erts_atomic_read_acqb(&head->next); if (inext != ERTS_AINT_NULL) { if (&q->tail.data.marker != (ErtsThrQElement_t *) inext) return ERTS_THR_Q_DIRTY; else { - q->head.head.ptr->next.ptr = (ErtsThrQElement_t *) inext; - q->head.head.ptr = (ErtsThrQElement_t *) inext; - inext = erts_atomic_read_acqb(&q->head.head.ptr->next.atmc); + head = (ErtsThrQElement_t *) inext; + ErtsThrQDirtySetEl(&q->head.head, head); + inext = erts_atomic_read_acqb(&head->next); if (inext != ERTS_AINT_NULL) return ERTS_THR_Q_DIRTY; } } } - if (q->head.first == q->head.head.ptr) { + if (q->head.first == head) { if (!q->head.used_marker) { erts_aint_t inext; - inext = erts_atomic_read_acqb(&q->head.head.ptr->next.atmc); + inext = erts_atomic_read_acqb(&head->next); if (inext == ERTS_AINT_NULL) return ERTS_THR_Q_DIRTY; } @@ -553,11 +570,11 @@ enqueue(ErtsThrQ_t *q, void *data, ErtsThrQElement_t *this) #ifndef USE_THREADS ASSERT(data); - this->next.ptr = NULL; + this->next = NULL; this->data.ptr = data; if (q->last) - q->last->next.ptr = this; + q->last->next = this; else { q->first = q->last = this; q->init.notify(q->init.arg); @@ -595,7 +612,7 @@ enqueue(ErtsThrQ_t *q, void *data, ErtsThrQElement_t *this) } } - notify = this == enqueue_managed(q, this, 1); + notify = this == enqueue_managed(q, this); #ifdef ERTS_SMP @@ -638,17 +655,17 @@ erts_thr_q_get_finalize_dequeue_data(ErtsThrQ_t *q, ErtsThrQFinDeQ_t *fdp) ErtsThrQElement_t *e = q->head.deq_fini.start; ErtsThrQElement_t *end = q->head.deq_fini.end; while (e != end) { - ASSERT(q->head.head.ptr != e); + ASSERT(ErtsThrQDirtyReadEl(&q->head.head) != e); ASSERT(q->head.first != e); ASSERT(q->head.unref_end != e); - e = e->next.ptr; + e = ErtsThrQDirtyReadEl(&e->next); } } #endif fdp->start = q->head.deq_fini.start; fdp->end = q->head.deq_fini.end; if (fdp->end) - fdp->end->next.ptr = NULL; + ErtsThrQDirtySetEl(&fdp->end->next, NULL); q->head.deq_fini.start = NULL; q->head.deq_fini.end = NULL; return fdp->start != NULL; @@ -662,7 +679,7 @@ erts_thr_q_append_finalize_dequeue_data(ErtsThrQFinDeQ_t *fdp0, #ifdef USE_THREADS if (fdp1->start) { if (fdp0->end) - fdp0->end->next.ptr = fdp1->start; + ErtsThrQDirtySetEl(&fdp0->end->next, fdp1->start); else fdp0->start = fdp1->start; fdp0->end = fdp1->end; @@ -683,7 +700,7 @@ int erts_thr_q_finalize_dequeue(ErtsThrQFinDeQ_t *state) if (!start) break; tmp = start; - start = start->next.ptr; + start = ErtsThrQDirtyReadEl(&start->next); live = (ErtsThrQLive_t) (UWord) tmp->data.ptr; element_live_free(live, tmp); } @@ -724,7 +741,7 @@ erts_thr_q_dequeue(ErtsThrQ_t *q) return NULL; tmp = q->first; res = tmp->data.ptr; - q->first = tmp->next.ptr; + q->first = tmp->next; if (!q->first) q->last = NULL; @@ -732,24 +749,26 @@ erts_thr_q_dequeue(ErtsThrQ_t *q) return res; #else + ErtsThrQElement_t *head; erts_aint_t inext; void *res; - inext = erts_atomic_read_acqb(&q->head.head.ptr->next.atmc); + head = ErtsThrQDirtyReadEl(&q->head.head); + inext = erts_atomic_read_acqb(&head->next); if (inext == ERTS_AINT_NULL) return NULL; - q->head.head.ptr->next.ptr = (ErtsThrQElement_t *) inext; - q->head.head.ptr = (ErtsThrQElement_t *) inext; - if (q->head.head.ptr == &q->tail.data.marker) { - inext = erts_atomic_read_acqb(&q->head.head.ptr->next.atmc); + head = (ErtsThrQElement_t *) inext; + ErtsThrQDirtySetEl(&q->head.head, head); + if (head == &q->tail.data.marker) { + inext = erts_atomic_read_acqb(&head->next); if (inext == ERTS_AINT_NULL) return NULL; - q->head.head.ptr->next.ptr = (ErtsThrQElement_t *) inext; - q->head.head.ptr = (ErtsThrQElement_t *) inext; + head = (ErtsThrQElement_t *) inext; + ErtsThrQDirtySetEl(&q->head.head, head); } - res = q->head.head.ptr->data.ptr; + res = head->data.ptr; #if ERTS_THR_Q_DBG_CHK_DATA - q->head.head.ptr->data.ptr = NULL; + head->data.ptr = NULL; if (!res) erl_exit(ERTS_ABORT_EXIT, "Missing data in dequeue\n"); #endif diff --git a/erts/emulator/beam/erl_thr_queue.h b/erts/emulator/beam/erl_thr_queue.h index edcf2c3823..ae8c7fb19a 100644 --- a/erts/emulator/beam/erl_thr_queue.h +++ b/erts/emulator/beam/erl_thr_queue.h @@ -76,13 +76,12 @@ typedef struct { typedef struct ErtsThrQElement_t_ ErtsThrQElement_t; typedef struct ErtsThrQElement_t ErtsThrQPrepEnQ_t; -typedef union { - erts_atomic_t atmc; - ErtsThrQElement_t *ptr; -} ErtsThrQPtr_t; - struct ErtsThrQElement_t_ { - ErtsThrQPtr_t next; +#ifdef USE_THREADS + erts_atomic_t next; +#else + ErtsThrQElement_t *next; +#endif union { erts_atomic_t atmc; void *ptr; @@ -130,7 +129,7 @@ struct ErtsThrQ_t_ { * thread dequeuing. */ struct { - ErtsThrQPtr_t head; + erts_atomic_t head; ErtsThrQLive_t live; ErtsThrQElement_t *first; ErtsThrQElement_t *unref_end; diff --git a/erts/emulator/beam/erl_threads.h b/erts/emulator/beam/erl_threads.h index 1dc3ffeb3c..594d38b2a1 100644 --- a/erts/emulator/beam/erl_threads.h +++ b/erts/emulator/beam/erl_threads.h @@ -690,6 +690,19 @@ do { \ } while (0) #endif +ERTS_GLB_INLINE void +erts_dw_atomic_set_dirty(erts_dw_atomic_t *var, erts_dw_aint_t *val); +ERTS_GLB_INLINE void +erts_dw_atomic_read_dirty(erts_dw_atomic_t *var, erts_dw_aint_t *val); +ERTS_GLB_INLINE void +erts_atomic_set_dirty(erts_atomic_t *var, erts_aint_t val); +ERTS_GLB_INLINE erts_aint_t +erts_atomic_read_dirty(erts_atomic_t *var); +ERTS_GLB_INLINE void +erts_atomic32_set_dirty(erts_atomic32_t *var, erts_aint32_t val); +ERTS_GLB_INLINE erts_aint32_t +erts_atomic32_read_dirty(erts_atomic32_t *var); + /* * See "Documentation of atomics and memory barriers" at the top * of this file for info on atomics. @@ -732,6 +745,26 @@ do { \ #define erts_dw_atomic_read_wb ethr_dw_atomic_read_wb #define erts_dw_atomic_cmpxchg_wb ethr_dw_atomic_cmpxchg_wb +#if ERTS_GLB_INLINE_INCL_FUNC_DEF + +ERTS_GLB_INLINE void +erts_dw_atomic_set_dirty(erts_dw_atomic_t *var, erts_dw_aint_t *val) +{ + ethr_sint_t *sint = ethr_dw_atomic_addr(var); + sint[0] = val->sint[0]; + sint[1] = val->sint[1]; +} + +ERTS_GLB_INLINE void +erts_dw_atomic_read_dirty(erts_dw_atomic_t *var, erts_dw_aint_t *val) +{ + ethr_sint_t *sint = ethr_dw_atomic_addr(var); + val->sint[0] = sint[0]; + val->sint[1] = sint[1]; +} + +#endif + /* Word size atomics */ #define erts_atomic_init_nob ethr_atomic_init @@ -911,6 +944,7 @@ erts_atomic_read_bset_rb(erts_atomic_t *var, #define erts_atomic_cmpxchg_wb ethr_atomic_cmpxchg_wb #if ERTS_GLB_INLINE_INCL_FUNC_DEF + ERTS_GLB_INLINE erts_aint_t erts_atomic_read_bset_wb(erts_atomic_t *var, erts_aint_t mask, @@ -921,6 +955,25 @@ erts_atomic_read_bset_wb(erts_atomic_t *var, ethr_atomic_cmpxchg_wb, var, mask, set); } + +#endif + +#if ERTS_GLB_INLINE_INCL_FUNC_DEF + +ERTS_GLB_INLINE void +erts_atomic_set_dirty(erts_atomic_t *var, erts_aint_t val) +{ + ethr_sint_t *sint = ethr_atomic_addr(var); + *sint = val; +} + +ERTS_GLB_INLINE erts_aint_t +erts_atomic_read_dirty(erts_atomic_t *var) +{ + ethr_sint_t *sint = ethr_atomic_addr(var); + return *sint; +} + #endif /* 32-bit atomics */ @@ -1102,6 +1155,7 @@ erts_atomic32_read_bset_rb(erts_atomic32_t *var, #define erts_atomic32_cmpxchg_wb ethr_atomic32_cmpxchg_wb #if ERTS_GLB_INLINE_INCL_FUNC_DEF + ERTS_GLB_INLINE erts_aint32_t erts_atomic32_read_bset_wb(erts_atomic32_t *var, erts_aint32_t mask, @@ -1112,10 +1166,29 @@ erts_atomic32_read_bset_wb(erts_atomic32_t *var, ethr_atomic32_cmpxchg_wb, var, mask, set); } + #endif #undef ERTS_ATOMIC_BSET_IMPL__ +#if ERTS_GLB_INLINE_INCL_FUNC_DEF + +ERTS_GLB_INLINE void +erts_atomic32_set_dirty(erts_atomic32_t *var, erts_aint32_t val) +{ + ethr_sint32_t *sint = ethr_atomic32_addr(var); + *sint = val; +} + +ERTS_GLB_INLINE erts_aint32_t +erts_atomic32_read_dirty(erts_atomic32_t *var) +{ + ethr_sint32_t *sint = ethr_atomic32_addr(var); + return *sint; +} + +#endif + #else /* !USE_THREADS */ /* Double word size atomics */ @@ -1155,6 +1228,9 @@ erts_atomic32_read_bset_wb(erts_atomic32_t *var, #define erts_dw_atomic_read_wb erts_no_dw_atomic_read #define erts_dw_atomic_cmpxchg_wb erts_no_dw_atomic_cmpxchg +#define erts_dw_atomic_set_dirty erts_no_dw_atomic_set +#define erts_dw_atomic_read_dirty erts_no_dw_atomic_read + /* Word size atomics */ #define erts_atomic_init_nob erts_no_atomic_set @@ -1262,6 +1338,9 @@ erts_atomic32_read_bset_wb(erts_atomic32_t *var, #define erts_atomic_cmpxchg_wb erts_no_atomic_cmpxchg #define erts_atomic_read_bset_wb erts_no_atomic_read_bset +#define erts_atomic_set_dirty erts_no_atomic_set +#define erts_atomic_read_dirty erts_no_atomic_read + /* 32-bit atomics */ #define erts_atomic32_init_nob erts_no_atomic32_set @@ -1369,6 +1448,9 @@ erts_atomic32_read_bset_wb(erts_atomic32_t *var, #define erts_atomic32_cmpxchg_wb erts_no_atomic32_cmpxchg #define erts_atomic32_read_bset_wb erts_no_atomic32_read_bset +#define erts_atomic32_set_dirty erts_no_atomic32_set +#define erts_atomic32_read_dirty erts_no_atomic32_read + #endif /* !USE_THREADS */ #if ERTS_GLB_INLINE_INCL_FUNC_DEF diff --git a/erts/emulator/beam/erl_unicode.c b/erts/emulator/beam/erl_unicode.c index 80982f3760..fa53fd0937 100644 --- a/erts/emulator/beam/erl_unicode.c +++ b/erts/emulator/beam/erl_unicode.c @@ -2747,3 +2747,11 @@ int erts_utf8_to_latin1(byte* dest, const byte* source, int slen) return dp - dest; } +BIF_RETTYPE io_printable_range_0(BIF_ALIST_0) +{ + if (erts_get_printable_characters() == ERL_PRINTABLE_CHARACTERS_UNICODE) { + BIF_RET(am_unicode); + } else { + BIF_RET(am_latin1); + } +} diff --git a/erts/emulator/beam/sys.h b/erts/emulator/beam/sys.h index 9416a91480..05bff430e3 100644 --- a/erts/emulator/beam/sys.h +++ b/erts/emulator/beam/sys.h @@ -1040,11 +1040,24 @@ char* win32_errorstr(int); #define ERL_FILENAME_WARNING_IGNORE (1) #define ERL_FILENAME_WARNING_ERROR (2) +/*********************************************************************** + * The user can request a range of character that he/she consider + * printable. Currently this can be either latin1 or unicode, but + * in the future a set of ranges, or languages, could be specified. + ***********************************************************************/ +#define ERL_PRINTABLE_CHARACTERS_LATIN1 (0) +#define ERL_PRINTABLE_CHARACTERS_UNICODE (1) + int erts_get_native_filename_encoding(void); /* The set function is only to be used by erl_init! */ void erts_set_user_requested_filename_encoding(int encoding, int warning); int erts_get_user_requested_filename_encoding(void); int erts_get_filename_warning_type(void); +/* This function is called from erl_init. The setting is read by BIF's + in io/io_lib. Setting is not atomic. */ +void erts_set_printable_characters(int range); +/* Get the setting (ERL_PRINTABLE_CHARACTERS_{LATIN1|UNICODE} */ +int erts_get_printable_characters(void); void erts_init_sys_common_misc(void); diff --git a/erts/emulator/drivers/common/efile_drv.c b/erts/emulator/drivers/common/efile_drv.c index 2279fec72a..22328fcd11 100644 --- a/erts/emulator/drivers/common/efile_drv.c +++ b/erts/emulator/drivers/common/efile_drv.c @@ -1160,7 +1160,14 @@ static void invoke_read_line(void *data) /* Need more place */ ErlDrvSizeT need = (d->c.read_line.read_size >= DEFAULT_LINEBUF_SIZE) ? d->c.read_line.read_size + DEFAULT_LINEBUF_SIZE : DEFAULT_LINEBUF_SIZE; - ErlDrvBinary *newbin = driver_alloc_binary(need); + ErlDrvBinary *newbin; +#if !ALWAYS_READ_LINE_AHEAD + /* Use read_ahead size if need does not exceed it */ + if (need < (d->c.read_line.binp)->orig_size && + d->c.read_line.read_ahead) + need = (d->c.read_line.binp)->orig_size; +#endif + newbin = driver_alloc_binary(need); if (newbin == NULL) { d->result_ok = 0; d->errInfo.posix_errno = ENOMEM; diff --git a/erts/emulator/drivers/common/inet_drv.c b/erts/emulator/drivers/common/inet_drv.c index f0c22e9ebe..3832cf1227 100644 --- a/erts/emulator/drivers/common/inet_drv.c +++ b/erts/emulator/drivers/common/inet_drv.c @@ -7834,7 +7834,7 @@ static ErlDrvSSizeT inet_ctl(inet_descriptor* desc, int cmd, char* buf, if (!IS_CONNECTED(desc)) return ctl_error(ENOTCONN, rbuf, rsize); - if (!desc->stype == SOCK_STREAM) + if (desc->stype != SOCK_STREAM) return ctl_error(EINVAL, rbuf, rsize); if (*buf == 1 && !desc->is_ignored) { @@ -8816,7 +8816,7 @@ static int tcp_recv_error(tcp_descriptor* desc, int err) if (desc->inet.exitf) driver_exit(desc->inet.port, err); else - desc_close(INETP(desc)); + desc_close_read(INETP(desc)); } return -1; } diff --git a/erts/emulator/hipe/hipe_bif0.c b/erts/emulator/hipe/hipe_bif0.c index 1562748f2d..059c013322 100644 --- a/erts/emulator/hipe/hipe_bif0.c +++ b/erts/emulator/hipe/hipe_bif0.c @@ -1791,7 +1791,7 @@ BIF_RETTYPE hipe_bifs_remove_refs_from_1(BIF_ALIST_1) if (BIF_ARG_1 == am_all) { hipe_purge_all_refs(); - BIF_RET(NIL); + BIF_RET(am_ok); } if (!term_to_mfa(BIF_ARG_1, &mfa)) @@ -1828,7 +1828,7 @@ BIF_RETTYPE hipe_bifs_remove_refs_from_1(BIF_ALIST_1) caller_mfa->refers_to = NULL; } hipe_mfa_info_table_unlock(); - BIF_RET(NIL); + BIF_RET(am_ok); } diff --git a/erts/emulator/hipe/hipe_native_bif.c b/erts/emulator/hipe/hipe_native_bif.c index 3be821f8f7..af1c36777f 100644 --- a/erts/emulator/hipe/hipe_native_bif.c +++ b/erts/emulator/hipe/hipe_native_bif.c @@ -503,9 +503,7 @@ static int validate_unicode(Eterm arg) { if (is_not_small(arg) || arg > make_small(0x10FFFFUL) || - (make_small(0xD800UL) <= arg && arg <= make_small(0xDFFFUL)) || - arg == make_small(0xFFFEUL) || - arg == make_small(0xFFFFUL)) + (make_small(0xD800UL) <= arg && arg <= make_small(0xDFFFUL))) return 0; return 1; } diff --git a/erts/emulator/sys/common/erl_sys_common_misc.c b/erts/emulator/sys/common/erl_sys_common_misc.c index 0b31c125e5..31ad3b82d5 100644 --- a/erts/emulator/sys/common/erl_sys_common_misc.c +++ b/erts/emulator/sys/common/erl_sys_common_misc.c @@ -49,10 +49,15 @@ static int filename_encoding = ERL_FILENAME_UNKNOWN; static int filename_warning = ERL_FILENAME_WARNING_WARNING; #if defined(__WIN32__) || defined(__DARWIN__) -static int user_filename_encoding = ERL_FILENAME_UTF8; /* Default unicode on windows */ +/* Default unicode on windows and MacOS X */ +static int user_filename_encoding = ERL_FILENAME_UTF8; #else static int user_filename_encoding = ERL_FILENAME_LATIN1; #endif +/* This controls the heuristic in printing characters in shell and w/ + io:format("~tp", ...) etc. */ +static int printable_character_set = ERL_PRINTABLE_CHARACTERS_LATIN1; + void erts_set_user_requested_filename_encoding(int encoding, int warning) { user_filename_encoding = encoding; @@ -69,6 +74,15 @@ int erts_get_filename_warning_type(void) return filename_warning; } +void erts_set_printable_characters(int range) { + /* Not an atomic */ + printable_character_set = range; +} + +int erts_get_printable_characters(void) { + return printable_character_set; +} + void erts_init_sys_common_misc(void) { #if defined(__WIN32__) diff --git a/erts/emulator/test/efile_SUITE.erl b/erts/emulator/test/efile_SUITE.erl index 9ac004200e..ddf23f90fd 100644 --- a/erts/emulator/test/efile_SUITE.erl +++ b/erts/emulator/test/efile_SUITE.erl @@ -21,6 +21,8 @@ init_per_group/2,end_per_group/2]). -export([iter_max_files/1]). +-export([do_iter_max_files/2]). + -include_lib("test_server/include/test_server.hrl"). suite() -> [{ct_hooks,[ts_install_cth]}]. @@ -51,11 +53,17 @@ end_per_group(_GroupName, Config) -> iter_max_files(suite) -> []; iter_max_files(Config) when is_list(Config) -> - ?line DataDir = ?config(data_dir,Config), - ?line TestFile = filename:join(DataDir, "existing_file"), - ?line L = do_iter_max_files(10, TestFile), - ?line io:format("Number of files opened in each test:~n~w\n", [L]), - ?line all_equal(L), + DataDir = ?config(data_dir,Config), + TestFile = filename:join(DataDir, "existing_file"), + N = 10, + %% Run on a different node in order to set the max ports + Dir = filename:dirname(code:which(?MODULE)), + {ok,Node} = test_server:start_node(test_iter_max_files,slave, + [{args,"+Q 1524 -pa " ++ Dir}]), + L = rpc:call(Node,?MODULE,do_iter_max_files,[N, TestFile]), + test_server:stop_node(Node), + io:format("Number of files opened in each test:~n~w\n", [L]), + all_equal(L), Head = hd(L), if Head >= 2 -> ok; true -> ?line test_server:fail(too_few_files) @@ -91,6 +99,6 @@ open_files(Name) -> {ok, Fd} -> [Fd| open_files(Name)]; {error, Reason} -> - io:format("Error reason: ~p", [Reason]), +% io:format("Error reason: ~p", [Reason]), [] end. diff --git a/erts/emulator/test/hash_SUITE.erl b/erts/emulator/test/hash_SUITE.erl index 898eae8c15..e34050cd07 100644 --- a/erts/emulator/test/hash_SUITE.erl +++ b/erts/emulator/test/hash_SUITE.erl @@ -1,3 +1,4 @@ +%% -*- coding: utf-8 -*- %% %% %CopyrightBegin% %% @@ -363,6 +364,15 @@ phash2_test() -> %% (cannot use block_hash due to compatibility issues...) {abc,26499}, {abd,26500}, + {'åäö', 62518}, + %% 81 runes as an atom, 'ᚠᚡᚢᚣᚤᚥᚦᚧᚨᚩᚪᚫᚬᚭᚮᚯᚰᚱᚲᚳᚴᚵᚶᚷᚸᚹᚺᚻᚼᚽᚾᚿᛀᛁᛂᛃᛄᛅᛆᛇᛈᛉᛊᛋᛌᛍᛎᛏᛐᛑᛒᛓᛔᛕᛖᛗᛘᛙᛚᛛᛜᛝᛞᛟᛠᛡᛢᛣᛤᛥᛦᛧᛨᛩᛪ᛫᛬᛭ᛮᛯᛰ' + {erlang:binary_to_term(<<131, 118, 0, 243, (unicode:characters_to_binary(lists:seq(5792, 5872)))/binary >>), 241561024}, + %% åäö dynamic + {erlang:binary_to_term(<<131, 118, 0, 6, 195, 165, 195, 164, 195, 182>>),62518}, + %% the atom '゙゚゛゜ゝゞゟ゠ァアィイゥウェエォオカガキギクグケゲコゴサザシジスズ' + {erlang:binary_to_term(<<131, 118, 0, 102, (unicode:characters_to_binary(lists:seq(12441, 12542)))/binary>>), 246053818}, + %% the atom, '😃' + {erlang:binary_to_term(<<131, 118, 0, 4, 240, 159, 152, 131>>), 1026307}, %% small {0,3175731469}, diff --git a/erts/etc/common/ct_run.c b/erts/etc/common/ct_run.c index 7aaab716f7..02a026c0fe 100644 --- a/erts/etc/common/ct_run.c +++ b/erts/etc/common/ct_run.c @@ -85,7 +85,6 @@ static char* strsave(char* string); static void push_words(char* src); static int run_erlang(char* name, char** argv); static char* get_default_emulator(char* progname); -static void print_deprecation_warning(char *progname); #ifdef __WIN32__ static char* possibly_quote(char* arg); #endif @@ -132,8 +131,6 @@ main(int argc, char** argv) int erl_args; char** argv0 = argv; - print_deprecation_warning(argv[0]); - emulator = get_default_emulator(argv[0]); /* @@ -447,15 +444,6 @@ static char *simple_basename(char *path) return path; } -static void print_deprecation_warning(char* progpath) -{ - char *basename = simple_basename(progpath); - if(strcmp(basename,"run_test") == 0 || - strcmp(basename, "run_test.exe") == 0) { - printf("---***---\nDeprecated: run_test is deprecated and will be removed in R16B,\n please use ct_run instead\n---***---\n"); - } -} - static char* get_default_emulator(char* progname) { diff --git a/erts/etc/common/erlexec.c b/erts/etc/common/erlexec.c index 577554c43d..9d674a7c65 100644 --- a/erts/etc/common/erlexec.c +++ b/erts/etc/common/erlexec.c @@ -912,6 +912,16 @@ int main(int argc, char **argv) i++; } break; + case 'p': + if (argv[i][2] != 'c' || argv[i][3] != '\0') + goto the_default; + if (i+1 >= argc) + usage(argv[i]); + argv[i][0] = '-'; + add_Eargs(argv[i]); + add_Eargs(argv[i+1]); + i++; + break; case 'z': if (!is_one_of_strings(&argv[i][2], plusz_val_switches)) { goto the_default; diff --git a/erts/etc/unix/Install.src b/erts/etc/unix/Install.src index 2dcd070a6d..53836449b3 100644 --- a/erts/etc/unix/Install.src +++ b/erts/etc/unix/Install.src @@ -92,9 +92,6 @@ cp -p "$ERL_ROOT/erts-%I_VSN%/bin/typer" . cp -p "$ERL_ROOT/erts-%I_VSN%/bin/ct_run" . cp -p "$ERL_ROOT/erts-%I_VSN%/bin/escript" . -# Remove in R16B -ln -s ct_run run_test - # # Set a soft link to epmd # This should not be done for an embedded system! diff --git a/erts/etc/win32/Install.c b/erts/etc/win32/Install.c index d680b67dd6..d0c69679f1 100644 --- a/erts/etc/win32/Install.c +++ b/erts/etc/win32/Install.c @@ -171,20 +171,6 @@ int main(int argc, char **argv) fprintf(stderr,"Continuing installation anyway...\n"); } } - - // Remove in R16B - sprintf(fromname,"%s\\%s",bin_dir,"ct_run.exe"); - sprintf(toname,"%s\\%s",bin_dir,"run_test.exe"); - if (GetFileAttributes(fromname) == 0xFFFFFFFF) { - fprintf(stderr,"Could not find file %s\n", - fromname); - exit(1); - } - if (!CopyFile(fromname,toname,FALSE)) { - fprintf(stderr,"Could not copy file %s to %s\n", - fromname,toname); - fprintf(stderr,"Continuing installation anyway...\n"); - } for (i = 0; scripts[i] != NULL; ++i) { sprintf(fromname,"%s\\%s",release_dir,scripts[i]); diff --git a/erts/include/internal/erl_printf_format.h b/erts/include/internal/erl_printf_format.h index 064c4a5c09..0f35c41044 100644 --- a/erts/include/internal/erl_printf_format.h +++ b/erts/include/internal/erl_printf_format.h @@ -28,6 +28,22 @@ #include <stdarg.h> #include <stdlib.h> +#include "erl_int_sizes_config.h" + +#if SIZEOF_VOID_P == SIZEOF_LONG +typedef unsigned long ErlPfUWord; +typedef long ErlPfSWord; +#elif SIZEOF_VOID_P == SIZEOF_INT +typedef unsigned int ErlPfUWord; +typedef int ErlPfSWord; +#elif SIZEOF_VOID_P == SIZEOF_LONG_LONG +typedef unsigned long long ErlPfUWord; +typedef long long ErlPfSWord; +#else +#error Found no appropriate type to use for 'Eterm', 'Uint' and 'Sint' +#endif + + typedef int (*fmtfn_t)(void*, char*, size_t); extern int erts_printf_format(fmtfn_t, void*, char*, va_list); @@ -36,11 +52,21 @@ extern int erts_printf_char(fmtfn_t, void*, char); extern int erts_printf_string(fmtfn_t, void*, char *); extern int erts_printf_buf(fmtfn_t, void*, char *, size_t); extern int erts_printf_pointer(fmtfn_t, void*, void *); -extern int erts_printf_ulong(fmtfn_t, void*, char, int, int, unsigned long); -extern int erts_printf_slong(fmtfn_t, void*, char, int, int, signed long); +extern int erts_printf_uword(fmtfn_t, void*, char, int, int, ErlPfUWord); +extern int erts_printf_sword(fmtfn_t, void*, char, int, int, ErlPfSWord); extern int erts_printf_double(fmtfn_t, void *, char, int, int, double); -extern int (*erts_printf_eterm_func)(fmtfn_t, void*, unsigned long, long, unsigned long*); - +#ifdef HALFWORD_HEAP_EMULATOR +# if SIZEOF_INT != 4 +# error Unsupported integer size for HALFWORD_HEAP_EMULATOR +# endif +typedef unsigned int ErlPfEterm; +#else +typedef ErlPfUWord ErlPfEterm; #endif +extern int (*erts_printf_eterm_func)(fmtfn_t, void*, ErlPfEterm, long, ErlPfEterm*); + + +#endif /* ERL_PRINTF_FORMAT_H__ */ + diff --git a/erts/include/internal/ethread.h b/erts/include/internal/ethread.h index aef31e282a..6c006b3f07 100644 --- a/erts/include/internal/ethread.h +++ b/erts/include/internal/ethread.h @@ -59,10 +59,6 @@ # undef ETHR_TRY_INLINE_FUNCS #endif -#if !defined(ETHR_DISABLE_NATIVE_IMPLS) && (defined(PURIFY)||defined(VALGRIND)) -# define ETHR_DISABLE_NATIVE_IMPLS -#endif - /* Assume 64-byte cache line size */ #define ETHR_CACHE_LINE_SIZE 64 #define ETHR_CACHE_LINE_MASK (ETHR_CACHE_LINE_SIZE - 1) @@ -413,7 +409,11 @@ extern ethr_runtime_t ethr_runtime__; # endif #endif -#include "ethr_optimized_fallbacks.h" +#ifdef VALGRIND /* mutex as fallback for spinlock for VALGRIND */ +# undef ETHR_HAVE_NATIVE_SPINLOCKS +#else +# include "ethr_optimized_fallbacks.h" +#endif typedef struct { void *(*thread_create_prepare_func)(void); diff --git a/erts/lib_src/common/erl_misc_utils.c b/erts/lib_src/common/erl_misc_utils.c index 11e2c56f61..9e9c142449 100644 --- a/erts/lib_src/common/erl_misc_utils.c +++ b/erts/lib_src/common/erl_misc_utils.c @@ -192,7 +192,8 @@ struct erts_cpu_info_t_ { static __forceinline int get_proc_affinity(erts_cpu_info_t *cpuinfo, cpu_set_t *cpuset) { - DWORD pamask, samask; + DWORD_PTR pamask; + DWORD_PTR samask; if (GetProcessAffinityMask(GetCurrentProcess(), &pamask, &samask)) { *cpuset = (cpu_set_t) pamask; return 0; diff --git a/erts/lib_src/common/erl_printf_format.c b/erts/lib_src/common/erl_printf_format.c index 00df3f068f..5034ea6668 100644 --- a/erts/lib_src/common/erl_printf_format.c +++ b/erts/lib_src/common/erl_printf_format.c @@ -165,7 +165,7 @@ static char heX[] = "0123456789ABCDEF"; #define SIGN(X) ((X) > 0 ? 1 : ((X) < 0 ? -1 : 0)) #define USIGN(X) ((X) == 0 ? 0 : 1) -int (*erts_printf_eterm_func)(fmtfn_t, void*, unsigned long, long, unsigned long*) = NULL; +int (*erts_printf_eterm_func)(fmtfn_t, void*, ErlPfEterm, long, ErlPfEterm*) = NULL; static int noop_fn(void *vfp, char* buf, size_t len) @@ -234,7 +234,7 @@ static int fmt_fld(fmtfn_t fn,void* arg, return 0; } -static int fmt_long(fmtfn_t fn,void* arg,int sign,unsigned long uval, +static int fmt_uword(fmtfn_t fn,void* arg,int sign,ErlPfUWord uval, int width,int precision,int fmt,int* count) { char buf[32]; @@ -475,7 +475,7 @@ int erts_printf_format(fmtfn_t fn, void* arg, char* fmt, va_list ap) int res = 0; while(*ptr) { - unsigned long ul_val; + ErlPfUWord ul_val; int fmt = 0; int width = -1; int precision = -1; @@ -661,22 +661,22 @@ int erts_printf_format(fmtfn_t fn, void* arg, char* fmt, va_list ap) switch(fmt & FMTL_MASK) { case FMTL_hh: { signed char tval = (signed char) va_arg(ap,int); - ul_val = (unsigned long) (tval < 0 ? (-tval) : tval); - res = fmt_long(fn,arg,SIGN(tval),ul_val, + ul_val = (ErlPfUWord) (tval < 0 ? (-tval) : tval); + res = fmt_uword(fn,arg,SIGN(tval),ul_val, width,precision,fmt,&count); break; } case FMTL_h: { signed short tval = (signed short) va_arg(ap,int); - ul_val = (unsigned long) (tval < 0 ? (-tval) : tval); - res = fmt_long(fn,arg,SIGN(tval),ul_val, + ul_val = (ErlPfUWord) (tval < 0 ? (-tval) : tval); + res = fmt_uword(fn,arg,SIGN(tval),ul_val, width,precision,fmt,&count); break; } case FMTL_l: { signed long tval = (signed long) va_arg(ap,long); - ul_val = (unsigned long) (tval < 0 ? (-tval) : tval); - res = fmt_long(fn,arg,SIGN(tval),ul_val, + ul_val = (ErlPfUWord) (tval < 0 ? (-tval) : tval); + res = fmt_uword(fn,arg,SIGN(tval),ul_val, width,precision,fmt,&count); break; } @@ -693,8 +693,8 @@ int erts_printf_format(fmtfn_t fn, void* arg, char* fmt, va_list ap) #endif default: { signed int tval = (signed int) va_arg(ap,int); - ul_val = (unsigned long) (tval < 0 ? (-tval) : tval); - res = fmt_long(fn,arg,SIGN(tval),ul_val, + ul_val = (ErlPfUWord) (tval < 0 ? (-tval) : tval); + res = fmt_uword(fn,arg,SIGN(tval),ul_val, width,precision,fmt,&count); break; } @@ -707,21 +707,21 @@ int erts_printf_format(fmtfn_t fn, void* arg, char* fmt, va_list ap) switch(fmt & FMTL_MASK) { case FMTL_hh: { unsigned char tval = (unsigned char) va_arg(ap,int); - ul_val = (unsigned long) tval; - res = fmt_long(fn,arg,USIGN(tval),ul_val, + ul_val = (ErlPfUWord) tval; + res = fmt_uword(fn,arg,USIGN(tval),ul_val, width,precision,fmt,&count); break; } case FMTL_h: { unsigned short tval = (unsigned short) va_arg(ap,int); - ul_val = (unsigned long) tval; - res = fmt_long(fn,arg,USIGN(tval),ul_val, + ul_val = (ErlPfUWord) tval; + res = fmt_uword(fn,arg,USIGN(tval),ul_val, width,precision,fmt,&count); break; } case FMTL_l: { - ul_val = (unsigned long) va_arg(ap,long); - res = fmt_long(fn,arg,USIGN(ul_val),ul_val, + ul_val = (ErlPfUWord) va_arg(ap,long); + res = fmt_uword(fn,arg,USIGN(ul_val),ul_val, width,precision,fmt,&count); break; } @@ -736,8 +736,8 @@ int erts_printf_format(fmtfn_t fn, void* arg, char* fmt, va_list ap) #endif default: { unsigned int tval = (unsigned int) va_arg(ap,int); - ul_val = (unsigned long) tval; - res = fmt_long(fn,arg,USIGN(tval),ul_val, + ul_val = (ErlPfUWord) tval; + res = fmt_uword(fn,arg,USIGN(tval),ul_val, width,precision,fmt,&count); break; } @@ -795,10 +795,10 @@ int erts_printf_format(fmtfn_t fn, void* arg, char* fmt, va_list ap) case FMTC_p: { void* addr = va_arg(ap, void*); - res = fmt_long(fn, + res = fmt_uword(fn, arg, - USIGN((unsigned long) addr), - (unsigned long) addr, + USIGN((ErlPfUWord) addr), + (ErlPfUWord) addr, width < 0 ? ((int) 2*sizeof(void *)) : width, (precision < 0 ? ((int) 2*sizeof(void *)) @@ -822,8 +822,8 @@ int erts_printf_format(fmtfn_t fn, void* arg, char* fmt, va_list ap) case FMTC_T: /* Eterm */ case FMTC_R: { /* Eterm, Eterm* base (base ignored if !HALFWORD_HEAP) */ long prec; - unsigned long eterm; - unsigned long* eterm_base; + ErlPfEterm eterm; + ErlPfEterm* eterm_base; if (!erts_printf_eterm_func) return -EINVAL; @@ -833,9 +833,9 @@ int erts_printf_format(fmtfn_t fn, void* arg, char* fmt, va_list ap) prec = LONG_MAX; else prec = (long) precision; - eterm = va_arg(ap, unsigned long); + eterm = va_arg(ap, ErlPfEterm); eterm_base = ((fmt & FMTC_MASK) == FMTC_R) ? - va_arg(ap, unsigned long*) : NULL; + va_arg(ap, ErlPfEterm*) : NULL; if (width > 0 && !(fmt & FMTF_adj)) { res = (*erts_printf_eterm_func)(noop_fn, NULL, eterm, prec, eterm_base); if (res < 0) @@ -890,8 +890,8 @@ int erts_printf_pointer(fmtfn_t fn, void *arg, void *ptr) { int count = 0; - int res = fmt_long(fn, arg, USIGN((unsigned long) ptr), - (unsigned long) ptr, 2*sizeof(void *), + int res = fmt_uword(fn, arg, USIGN((ErlPfUWord) ptr), + (ErlPfUWord) ptr, 2*sizeof(void *), 2*sizeof(void *), FMTC_x|FMTF_pad|FMTF_alt, &count); if (res < 0) return res; @@ -899,8 +899,8 @@ erts_printf_pointer(fmtfn_t fn, void *arg, void *ptr) } int -erts_printf_ulong(fmtfn_t fn, void *arg, char conv, int pad, int width, - unsigned long val) +erts_printf_uword(fmtfn_t fn, void *arg, char conv, int pad, int width, + ErlPfUWord val) { int count = 0; int res; @@ -917,21 +917,21 @@ erts_printf_ulong(fmtfn_t fn, void *arg, char conv, int pad, int width, } if (pad) prec = width; - res = fmt_long(fn, arg, USIGN(val), val, width, prec, fmt, &count); + res = fmt_uword(fn, arg, USIGN(val), val, width, prec, fmt, &count); if (res < 0) return res; return count; } -extern int -erts_printf_slong(fmtfn_t fn, void *arg, char conv, int pad, int width, - signed long val) +int +erts_printf_sword(fmtfn_t fn, void *arg, char conv, int pad, int width, + ErlPfSWord val) { int count = 0; int res; int fmt = 0; int prec = -1; - unsigned long ul_val; + ErlPfUWord ul_val; switch (conv) { case 'd': fmt |= FMTC_d; break; case 'i': fmt |= FMTC_d; break; @@ -943,8 +943,8 @@ erts_printf_slong(fmtfn_t fn, void *arg, char conv, int pad, int width, } if (pad) prec = width; - ul_val = (unsigned long) (val < 0 ? -val : val); - res = fmt_long(fn, arg, SIGN(val), ul_val, width, prec, fmt, &count); + ul_val = (ErlPfUWord) (val < 0 ? -val : val); + res = fmt_uword(fn, arg, SIGN(val), ul_val, width, prec, fmt, &count); if (res < 0) return res; return count; diff --git a/erts/preloaded/ebin/prim_file.beam b/erts/preloaded/ebin/prim_file.beam Binary files differindex f7b3aac376..360887de9d 100644 --- a/erts/preloaded/ebin/prim_file.beam +++ b/erts/preloaded/ebin/prim_file.beam diff --git a/erts/preloaded/src/prim_file.erl b/erts/preloaded/src/prim_file.erl index bf8879c2a0..489e8ca4ea 100644 --- a/erts/preloaded/src/prim_file.erl +++ b/erts/preloaded/src/prim_file.erl @@ -933,7 +933,12 @@ list_dir_int(Port, Dir) -> fun(P) -> case list_dir_response(P, []) of {ok, RawNames} -> - {ok, list_dir_convert(RawNames)}; + try + {ok, list_dir_convert(RawNames)} + catch + throw:Reason -> + Reason + end; Error -> Error end @@ -979,7 +984,7 @@ list_dir_convert([Name|Names]) -> {error, ignore} -> list_dir_convert(Names); {error, error} -> - {error, {no_translation, Name}}; + throw({error, {no_translation, Name}}); Converted when is_list(Converted) -> [Converted|list_dir_convert(Names)] end; @@ -990,9 +995,9 @@ list_dir_convert_all([Name|Names]) -> %% a binary. case prim_file:internal_native2name(Name) of {error, _} -> - [Name|list_dir_convert(Names)]; + [Name|list_dir_convert_all(Names)]; Converted when is_list(Converted) -> - [Converted|list_dir_convert(Names)] + [Converted|list_dir_convert_all(Names)] end; list_dir_convert_all([]) -> []. diff --git a/erts/test/otp_SUITE.erl b/erts/test/otp_SUITE.erl index 51f07b5432..374255bbe6 100644 --- a/erts/test/otp_SUITE.erl +++ b/erts/test/otp_SUITE.erl @@ -273,7 +273,7 @@ call_to_size_1(Config) when is_list(Config) -> Server = ?config(xref_server, Config), %% Applications that do not call erlang:size/1: - Apps = [compiler,debugger,kernel,observer,parsetools, + Apps = [asn1,compiler,debugger,kernel,observer,parsetools, runtime_tools,stdlib,tools,webtool], Fs = [{erlang,size,1}], |