diff options
Diffstat (limited to 'erts/emulator')
75 files changed, 1124 insertions, 524 deletions
diff --git a/erts/emulator/Makefile.in b/erts/emulator/Makefile.in index a2cef8a8a5..a5d8217545 100644 --- a/erts/emulator/Makefile.in +++ b/erts/emulator/Makefile.in @@ -198,6 +198,7 @@ RM = @RM@ MKDIR = @MKDIR@ USING_MINGW=@MIXED_CYGWIN_MINGW@ +MIXED_MSYS=@MIXED_MSYS@ ifeq ($(TARGET),win32) LIB_PREFIX= @@ -237,9 +238,12 @@ ifeq ($(TARGET), win32) GEN_OPT_FLGS = $(OPT_LEVEL) UNROLL_FLG = RC=rc.sh +ifeq ($(MIXED_MSYS), yes) +MAKE_PRELOAD_EXTRA = -msys +endif ifeq ($(USING_MINGW), yes) -RES_EXT=@OBJEXT@ -MAKE_PRELOAD_EXTRA=-windres +RES_EXT = @OBJEXT@ +MAKE_PRELOAD_EXTRA += " -windres" else RES_EXT=res endif @@ -359,7 +363,6 @@ ERLANG_OSTYPE = @ERLANG_OSTYPE@ ENABLE_ALLOC_TYPE_VARS += @ERLANG_OSTYPE@ -EMULATOR_EXECUTABLE_ELIB = beam.elib$(TF_MARKER) ifeq ($(TARGET), win32) EMULATOR_EXECUTABLE = beam$(TF_MARKER).dll else @@ -942,7 +945,6 @@ $(TARGET)/Makefile: Makefile.in #SED_REPL_WIN_DRIVE=s|\([ ]\)\([A-Za-z]\):|\1/cygdrive/\2|g;s|^\([A-Za-z]\):|/cygdrive/\1|g SED_REPL_O=s|^\([^:]*:\)|$$(OBJDIR)/\1|g -SED_REPL_ELIB_O=s|^\([^:]*\).o[ ]*:|$$(OBJDIR)/\1.elib.o:|g SED_REPL_TTF_DIR=s|$(TTF_DIR)/|$$(TTF_DIR)/|g SED_REPL_ERL_TOP=s|\([ ]\)$(ERL_TOP)/|\1$$(ERL_TOP)/|g;s|^$(ERL_TOP)/|$$(ERL_TOP)/|g SED_REPL_POLL=s|$$(OBJDIR)/erl_poll.o|$$(OBJDIR)/erl_poll.kp.o $$(OBJDIR)/erl_poll.nkp.o|g @@ -962,7 +964,6 @@ SED_SUFFIX= endif SED_DEPEND=sed '$(SED_PREFIX)$(SED_REPL_O);$(SED_REPL_TTF_DIR);$(SED_REPL_ERL_TOP)$(SED_SUFFIX)' -SED_ELIB_DEPEND=sed '$(SED_PREFIX)$(SED_REPL_ELIB_O);$(SED_REPL_TTF_DIR);$(SED_REPL_ERL_TOP)$(SED_SUFFIX)' ifdef HIPE_ENABLED HIPE_SRC=$(wildcard hipe/*.c) @@ -1018,10 +1019,6 @@ depend: | $(SED_DEPEND) >> $(TARGET)/depend.mk $(DEP_CC) $(DEP_FLAGS) $(TARGET_SRC) \ | $(SED_DEPEND) >> $(TARGET)/depend.mk -ifneq ($(TARGET),win32) - $(DEP_CC) $(DEP_FLAGS) $(ELIB_C_FILES) \ - | $(SED_ELIB_DEPEND) >> $(TARGET)/depend.mk -endif ifdef HIPE_ENABLED $(DEP_CC) $(DEP_FLAGS) $(HIPE_SRC) \ | $(SED_DEPEND) >> $(TARGET)/depend.mk diff --git a/erts/emulator/beam/atom.h b/erts/emulator/beam/atom.h index cb245a87b1..6127a658bb 100644 --- a/erts/emulator/beam/atom.h +++ b/erts/emulator/beam/atom.h @@ -34,7 +34,7 @@ /* Internal atom cache needs MAX_ATOM_TABLE_SIZE to be less than an unsigned 32 bit integer. See external.c(erts_encode_ext_dist_header_setup) for more details. */ -#define MAX_ATOM_TABLE_SIZE ((MAX_ATOM_INDEX + 1 < (1UL << 32)) ? MAX_ATOM_INDEX + 1 : (1UL << 32)) +#define MAX_ATOM_TABLE_SIZE ((MAX_ATOM_INDEX + 1 < (UWORD_CONSTANT(1) << 32)) ? MAX_ATOM_INDEX + 1 : (UWORD_CONSTANT(1) << 32)) #else #define MAX_ATOM_TABLE_SIZE (MAX_ATOM_INDEX + 1) #endif diff --git a/erts/emulator/beam/beam_bif_load.c b/erts/emulator/beam/beam_bif_load.c index bc8c001454..78a9d76a20 100644 --- a/erts/emulator/beam/beam_bif_load.c +++ b/erts/emulator/beam/beam_bif_load.c @@ -578,7 +578,7 @@ check_process_code(Process* rp, Module* modp) } #define in_area(ptr,start,nbytes) \ - ((unsigned long)((char*)(ptr) - (char*)(start)) < (nbytes)) + ((UWord)((char*)(ptr) - (char*)(start)) < (nbytes)) static int any_heap_ref_ptrs(Eterm* start, Eterm* end, char* mod_start, Uint mod_size) diff --git a/erts/emulator/beam/beam_bp.c b/erts/emulator/beam/beam_bp.c index dd31376a2d..692fa61fe8 100644 --- a/erts/emulator/beam/beam_bp.c +++ b/erts/emulator/beam/beam_bp.c @@ -495,16 +495,6 @@ erts_find_local_func(Eterm mfa[3]) { return NULL; } -/* bp_hash */ -ERTS_INLINE Uint bp_sched2ix() { -#ifdef ERTS_SMP - ErtsSchedulerData *esdp; - esdp = erts_get_scheduler_data(); - return esdp->no - 1; -#else - return 0; -#endif -} static void bp_hash_init(bp_time_hash_t *hash, Uint n) { Uint size = sizeof(bp_data_time_item_t)*n; Uint i; @@ -1347,7 +1337,7 @@ static BpData *is_break(BeamInstr *pc, BeamInstr break_op) { return NULL; } - bd = ebd = rs[bp_sched2ix()]; + bd = ebd = rs[erts_bp_sched2ix()]; ASSERT(bd); if ( (break_op == 0) || (bd->this_instr == break_op)) { return bd; diff --git a/erts/emulator/beam/beam_bp.h b/erts/emulator/beam/beam_bp.h index 2ec5818688..167069552f 100644 --- a/erts/emulator/beam/beam_bp.h +++ b/erts/emulator/beam/beam_bp.h @@ -144,8 +144,6 @@ extern erts_smp_spinlock_t erts_bp_lock; #define ErtsSmpBPUnlock(BDC) #endif -ERTS_INLINE Uint bp_sched2ix(void); - #ifdef ERTS_SMP #define bp_sched2ix_proc(p) ((p)->scheduler_data->no - 1) #else @@ -247,4 +245,19 @@ BpData *erts_get_time_break(Process *p, BeamInstr *pc); BeamInstr *erts_find_local_func(Eterm mfa[3]); +ERTS_GLB_INLINE Uint erts_bp_sched2ix(void); + +#if ERTS_GLB_INLINE_INCL_FUNC_DEF +ERTS_GLB_INLINE Uint erts_bp_sched2ix(void) +{ +#ifdef ERTS_SMP + ErtsSchedulerData *esdp; + esdp = erts_get_scheduler_data(); + return esdp->no - 1; +#else + return 0; +#endif +} +#endif + #endif /* _BEAM_BP_H */ diff --git a/erts/emulator/beam/beam_emu.c b/erts/emulator/beam/beam_emu.c index 68e6383f7f..c65b2be106 100644 --- a/erts/emulator/beam/beam_emu.c +++ b/erts/emulator/beam/beam_emu.c @@ -45,7 +45,7 @@ /* #define HARDDEBUG 1 */ #if defined(NO_JUMP_TABLE) -# define OpCase(OpCode) case op_##OpCode: lb_##OpCode +# define OpCase(OpCode) case op_##OpCode # define CountCase(OpCode) case op_count_##OpCode # define OpCode(OpCode) ((Uint*)op_##OpCode) # define Goto(Rel) {Go = (int)(Rel); goto emulator_loop;} @@ -53,7 +53,7 @@ #else # define OpCase(OpCode) lb_##OpCode # define CountCase(OpCode) lb_count_##OpCode -# define Goto(Rel) goto *(Rel) +# define Goto(Rel) goto *((void *)Rel) # define LabelAddr(Label) &&Label # define OpCode(OpCode) (&&lb_##OpCode) #endif @@ -199,7 +199,7 @@ do { \ } \ } while (0) -#define ClauseFail() goto lb_jump_f +#define ClauseFail() goto jump_f #define SAVE_CP(X) \ do { \ @@ -234,6 +234,12 @@ BeamInstr beam_return_trace[1]; /* OpCode(i_return_trace) */ BeamInstr beam_exception_trace[1]; /* UGLY also OpCode(i_return_trace) */ BeamInstr beam_return_time_trace[1]; /* OpCode(i_return_time_trace) */ + +/* + * We should warn only once for tuple funs. + */ +static erts_smp_atomic_t warned_for_tuple_funs; + /* * All Beam instructions in numerical order. */ @@ -1015,6 +1021,7 @@ init_emulator(void) #if defined(VXWORKS) init_done = 0; #endif + erts_smp_atomic_init_nob(&warned_for_tuple_funs, (erts_aint_t) 0); process_main(); } @@ -2540,6 +2547,7 @@ void process_main(void) lb_Cl_error: { if (Arg(0) != 0) { OpCase(jump_f): { + jump_f: SET_I((BeamInstr *) Arg(0)); Goto(*I); } @@ -3113,7 +3121,7 @@ void process_main(void) /* Fall through */ OpCase(error_action_code): { - no_error_handler: + handle_error: reg[0] = r(0); SWAPOUT; I = handle_error(c_p, NULL, reg, NULL); @@ -3274,7 +3282,7 @@ void process_main(void) OpCase(i_func_info_IaaI): { c_p->freason = EXC_FUNCTION_CLAUSE; c_p->current = I + 2; - goto lb_error_action_code; + goto handle_error; } OpCase(try_case_end_s): @@ -4960,7 +4968,7 @@ void process_main(void) if (I) { Goto(*I); } - goto no_error_handler; + goto handle_error; } @@ -6187,6 +6195,26 @@ call_fun(Process* p, /* Current process. */ if (!is_atom(module) || !is_atom(function)) { goto badfun; } + + /* + * If this is the first time a tuple fun is used, + * send a warning to the logger. + */ + if (erts_smp_atomic_xchg_nob(&warned_for_tuple_funs, + (erts_aint_t) 1) == 0) { + erts_dsprintf_buf_t* dsbufp; + + dsbufp = erts_create_logger_dsbuf(); + erts_dsprintf(dsbufp, "Call to tuple fun {%T,%T}.\n\n" + "Tuple funs are deprecated and will be removed " + "in R16. Use \"fun M:F/A\" instead, for example " + "\"fun %T:%T/%d\".\n\n" + "(This warning will only be shown the first time " + "a tuple fun is called.)\n", + module, function, module, function, arity); + erts_send_warning_to_logger(p->group_leader, dsbufp); + } + if ((ep = erts_find_export_entry(module, function, arity)) == NULL) { ep = erts_find_export_entry(erts_proc_get_error_handler(p), am_undefined_function, 3); diff --git a/erts/emulator/beam/beam_load.c b/erts/emulator/beam/beam_load.c index d8434c098e..e6fbdc0d45 100644 --- a/erts/emulator/beam/beam_load.c +++ b/erts/emulator/beam/beam_load.c @@ -1434,7 +1434,7 @@ static int read_literal_table(LoaderState* stp) { int i; - BeamInstr uncompressed_sz; + uLongf uncompressed_sz; byte* uncompressed = 0; GetInt(stp, 4, uncompressed_sz); @@ -1444,7 +1444,7 @@ read_literal_table(LoaderState* stp) LoadError0(stp, "failed to uncompress literal table (constant pool)"); } stp->file_p = uncompressed; - stp->file_left = uncompressed_sz; + stp->file_left = (unsigned) uncompressed_sz; GetInt(stp, 4, stp->num_literals); stp->literals = (Literal *) erts_alloc(ERTS_ALC_T_LOADER_TMP, stp->num_literals * sizeof(Literal)); @@ -3500,7 +3500,6 @@ gen_jump_tab(LoaderState* stp, GenOpArg S, GenOpArg Fail, GenOpArg Size, GenOpAr } size = max - min + 1; - /* * Allocate structure and fill in the fixed fields. */ @@ -3532,7 +3531,7 @@ gen_jump_tab(LoaderState* stp, GenOpArg S, GenOpArg Fail, GenOpArg Size, GenOpAr op->a[i] = Fail; } for (i = 0; i < Size.val; i += 2) { - int index; + Sint index; index = fixed_args+Rest[i].val-min; ASSERT(fixed_args <= index && index < arity); op->a[index] = Rest[i+1]; diff --git a/erts/emulator/beam/bif.c b/erts/emulator/beam/bif.c index 8ab363a1ec..26f1b4facb 100644 --- a/erts/emulator/beam/bif.c +++ b/erts/emulator/beam/bif.c @@ -870,8 +870,6 @@ BIF_RETTYPE spawn_opt_1(BIF_ALIST_1) } } else if (arg == am_scheduler && is_small(val)) { Sint scheduler = signed_val(val); - if (erts_common_run_queue && erts_no_schedulers > 1) - goto error; if (scheduler < 0 || erts_no_schedulers < scheduler) goto error; so.scheduler = (int) scheduler; @@ -1535,8 +1533,6 @@ BIF_RETTYPE process_flag_2(BIF_ALIST_2) ErtsRunQueue *old; ErtsRunQueue *new; Sint sched; - if (erts_common_run_queue && erts_no_schedulers > 1) - goto error; if (!is_small(BIF_ARG_2)) goto error; sched = signed_val(BIF_ARG_2); @@ -4128,8 +4124,20 @@ BIF_RETTYPE system_flag_2(BIF_ALIST_2) if (is_value(res)) BIF_RET(res); } else if (ERTS_IS_ATOM_STR("cpu_topology", BIF_ARG_1)) { + erts_send_warning_to_logger_str( + BIF_P->group_leader, + "A call to erlang:system_flag(cpu_topology, _) was made.\n" + "The cpu_topology argument is deprecated and scheduled\n" + "for removal in erts-5.10/OTP-R16. For more information\n" + "see the erlang:system_flag/2 documentation.\n"); BIF_TRAP1(set_cpu_topology_trap, BIF_P, BIF_ARG_2); } else if (ERTS_IS_ATOM_STR("scheduler_bind_type", BIF_ARG_1)) { + erts_send_warning_to_logger_str( + BIF_P->group_leader, + "A call to erlang:system_flag(scheduler_bind_type, _) was\n" + "made. The scheduler_bind_type argument is deprecated and\n" + "scheduled for removal in erts-5.10/OTP-R16. For more\n" + "information see the erlang:system_flag/2 documentation.\n"); return erts_bind_schedulers(BIF_P, BIF_ARG_2); } error: diff --git a/erts/emulator/beam/big.c b/erts/emulator/beam/big.c index 46db9ca99c..976f05c990 100644 --- a/erts/emulator/beam/big.c +++ b/erts/emulator/beam/big.c @@ -1325,7 +1325,7 @@ static dsize_t I_lshift(ErtsDigit* x, dsize_t xl, Sint y, return 1; } else { - long ay = (y < 0) ? -y : y; + SWord ay = (y < 0) ? -y : y; int bw = ay / D_EXP; int sw = ay % D_EXP; dsize_t rl; @@ -1450,6 +1450,20 @@ erts_make_integer(Uint x, Process *p) return uint_to_big(x,hp); } } +/* + * As erts_make_integer, but from a whole UWord. + */ +Eterm +erts_make_integer_from_uword(UWord x, Process *p) +{ + Eterm* hp; + if (IS_USMALL(0,x)) + return make_small(x); + else { + hp = HAlloc(p, BIG_UWORD_HEAP_SIZE(x)); + return uword_to_big(x,hp); + } +} /* ** convert Uint to bigint diff --git a/erts/emulator/beam/big.h b/erts/emulator/beam/big.h index 256f1c2b45..7eb1e5afe2 100644 --- a/erts/emulator/beam/big.h +++ b/erts/emulator/beam/big.h @@ -145,6 +145,7 @@ Eterm small_to_big(Sint, Eterm*); Eterm uint_to_big(Uint, Eterm*); Eterm uword_to_big(UWord, Eterm*); Eterm erts_make_integer(Uint, Process *); +Eterm erts_make_integer_from_uword(UWord x, Process *p); dsize_t big_bytes(Eterm); Eterm bytes_to_big(byte*, dsize_t, int, Eterm*); diff --git a/erts/emulator/beam/binary.c b/erts/emulator/beam/binary.c index 29461877c5..3d2725e239 100644 --- a/erts/emulator/beam/binary.c +++ b/erts/emulator/beam/binary.c @@ -47,7 +47,7 @@ erts_init_binary(void) away. If not, this test is not very expensive... */ erl_exit(ERTS_ABORT_EXIT, "Internal error: Address of orig_bytes[0] of a Binary" - "is *not* 8-byte aligned\n"); + " is *not* 8-byte aligned\n"); } } diff --git a/erts/emulator/beam/break.c b/erts/emulator/beam/break.c index 784e55ecd2..0d3b6a4dba 100644 --- a/erts/emulator/beam/break.c +++ b/erts/emulator/beam/break.c @@ -182,6 +182,7 @@ print_process_info(int to, void *to_arg, Process *p) { int garbing = 0; int running = 0; + time_t tmp_t; struct saved_calls *scb; /* display the PID */ @@ -244,8 +245,8 @@ print_process_info(int to, void *to_arg, Process *p) } erts_print(to, to_arg, "Spawned by: %T\n", p->parent); - - erts_print(to, to_arg, "Started: %s", ctime((time_t*)&p->started.tv_sec)); + tmp_t = p->started.tv_sec; + erts_print(to, to_arg, "Started: %s", ctime(&tmp_t)); ERTS_SMP_MSGQ_MV_INQ2PRIVQ(p); erts_print(to, to_arg, "Message queue length: %d\n", p->msg.len); diff --git a/erts/emulator/beam/dist.c b/erts/emulator/beam/dist.c index 44c5ba1e26..cfcdb72636 100644 --- a/erts/emulator/beam/dist.c +++ b/erts/emulator/beam/dist.c @@ -536,7 +536,7 @@ alloc_dist_obuf(Uint size) Binary *bin = erts_bin_drv_alloc(obuf_size); bin->flags = BIN_FLAG_DRV; erts_refc_init(&bin->refc, 1); - bin->orig_size = (long) obuf_size; + bin->orig_size = (SWord) obuf_size; obuf = (ErtsDistOutputBuf *) &bin->orig_bytes[0]; #ifdef DEBUG obuf->dbg_pattern = ERTS_DIST_OUTPUT_BUF_DBG_PATTERN; diff --git a/erts/emulator/beam/erl_alloc.c b/erts/emulator/beam/erl_alloc.c index 140a84d5fc..1379f8645a 100644 --- a/erts/emulator/beam/erl_alloc.c +++ b/erts/emulator/beam/erl_alloc.c @@ -3117,10 +3117,10 @@ void *safe_realloc(void *ptr, Uint sz) \* */ #define ERTS_ALC_TEST_ABORT erl_exit(ERTS_ABORT_EXIT, "%s:%d: Internal error\n") -unsigned long erts_alc_test(unsigned long op, - unsigned long a1, - unsigned long a2, - unsigned long a3) +UWord erts_alc_test(UWord op, + UWord a1, + UWord a2, + UWord a3) { switch (op >> 8) { case 0x0: return erts_alcu_test(op, a1, a2); @@ -3134,24 +3134,24 @@ unsigned long erts_alc_test(unsigned long op, case 0xf00: #ifdef USE_THREADS if (((Allctr_t *) a1)->thread_safe) - return (unsigned long) erts_alcu_alloc_ts(ERTS_ALC_T_UNDEF, + return (UWord) erts_alcu_alloc_ts(ERTS_ALC_T_UNDEF, (void *) a1, (Uint) a2); else #endif - return (unsigned long) erts_alcu_alloc(ERTS_ALC_T_UNDEF, + return (UWord) erts_alcu_alloc(ERTS_ALC_T_UNDEF, (void *) a1, (Uint) a2); case 0xf01: #ifdef USE_THREADS if (((Allctr_t *) a1)->thread_safe) - return (unsigned long) erts_alcu_realloc_ts(ERTS_ALC_T_UNDEF, + return (UWord) erts_alcu_realloc_ts(ERTS_ALC_T_UNDEF, (void *) a1, (void *) a2, (Uint) a3); else #endif - return (unsigned long) erts_alcu_realloc(ERTS_ALC_T_UNDEF, + return (UWord) erts_alcu_realloc(ERTS_ALC_T_UNDEF, (void *) a1, (void *) a2, (Uint) a3); @@ -3181,7 +3181,7 @@ unsigned long erts_alc_test(unsigned long op, if (argv[i][0] == '-' && argv[i][1] == 't') handle_au_arg(&init, &argv[i][2], argv, &i); else - return (unsigned long) NULL; + return (UWord) NULL; i++; } } @@ -3222,25 +3222,25 @@ unsigned long erts_alc_test(unsigned long op, break; } - return (unsigned long) allctr; + return (UWord) allctr; } case 0xf04: erts_alcu_stop((Allctr_t *) a1); erts_free(ERTS_ALC_T_UNDEF, (void *) a1); break; #ifdef USE_THREADS - case 0xf05: return (unsigned long) 1; - case 0xf06: return (unsigned long) ((Allctr_t *) a1)->thread_safe; + case 0xf05: return (UWord) 1; + case 0xf06: return (UWord) ((Allctr_t *) a1)->thread_safe; #ifdef ETHR_NO_FORKSAFETY - case 0xf07: return (unsigned long) 0; + case 0xf07: return (UWord) 0; #else - case 0xf07: return (unsigned long) ((Allctr_t *) a1)->thread_safe; + case 0xf07: return (UWord) ((Allctr_t *) a1)->thread_safe; #endif case 0xf08: { ethr_mutex *mtx = erts_alloc(ERTS_ALC_T_UNDEF, sizeof(ethr_mutex)); if (ethr_mutex_init(mtx) != 0) ERTS_ALC_TEST_ABORT; - return (unsigned long) mtx; + return (UWord) mtx; } case 0xf09: { ethr_mutex *mtx = (ethr_mutex *) a1; @@ -3259,7 +3259,7 @@ unsigned long erts_alc_test(unsigned long op, ethr_cond *cnd = erts_alloc(ERTS_ALC_T_UNDEF, sizeof(ethr_cond)); if (ethr_cond_init(cnd) != 0) ERTS_ALC_TEST_ABORT; - return (unsigned long) cnd; + return (UWord) cnd; } case 0xf0d: { ethr_cond *cnd = (ethr_cond *) a1; @@ -3285,7 +3285,7 @@ unsigned long erts_alc_test(unsigned long op, (void *) a2, NULL) != 0) ERTS_ALC_TEST_ABORT; - return (unsigned long) tid; + return (UWord) tid; } case 0xf11: { ethr_tid *tid = (ethr_tid *) a1; @@ -3302,13 +3302,13 @@ unsigned long erts_alc_test(unsigned long op, default: break; } - return (unsigned long) 0; + return (UWord) 0; default: break; } ASSERT(0); - return ~((unsigned long) 0); + return ~((UWord) 0); } #ifdef DEBUG @@ -3544,7 +3544,7 @@ check_memory_fence(void *ptr, Uint *size, ErtsAlcType_t n, int func) erl_exit(ERTS_ABORT_EXIT, "ERROR: Fence at beginning of memory block (p=0x%u) " "clobbered.\n", - (unsigned long) ptr); + (UWord) ptr); } memcpy((void *) &post_pattern, (void *) (((char *)ptr)+sz), sizeof(UWord)); @@ -3561,12 +3561,12 @@ check_memory_fence(void *ptr, Uint *size, ErtsAlcType_t n, int func) erl_exit(ERTS_ABORT_EXIT, "ERROR: Fence at end of memory block (p=0x%u, sz=%u) " "clobbered.\n", - (unsigned long) ptr, (unsigned long) sz); + (UWord) ptr, (UWord) sz); if (found_type != GET_TYPE_OF_PATTERN(post_pattern)) erl_exit(ERTS_ABORT_EXIT, "ERROR: Fence around memory block (p=0x%u, sz=%u) " "clobbered.\n", - (unsigned long) ptr, (unsigned long) sz); + (UWord) ptr, (UWord) sz); ftype = type_no_str(found_type); if (!ftype) { @@ -3589,7 +3589,7 @@ check_memory_fence(void *ptr, Uint *size, ErtsAlcType_t n, int func) erl_exit(ERTS_ABORT_EXIT, "ERROR: Memory block (p=0x%u, sz=%u) allocated as type \"%s\"," " but %s as type \"%s\".\n", - (unsigned long) ptr, (unsigned long) sz, ftype, op_str, otype); + (UWord) ptr, (UWord) sz, ftype, op_str, otype); } #ifdef HARD_DEBUG diff --git a/erts/emulator/beam/erl_alloc.h b/erts/emulator/beam/erl_alloc.h index f4133cdb1a..991061c48e 100644 --- a/erts/emulator/beam/erl_alloc.h +++ b/erts/emulator/beam/erl_alloc.h @@ -80,10 +80,10 @@ void erts_alloc_late_init(void); #if defined(GET_ERTS_ALC_TEST) || defined(ERTS_ALC_INTERNAL__) /* Only for testing */ -unsigned long erts_alc_test(unsigned long, - unsigned long, - unsigned long, - unsigned long); +UWord erts_alc_test(UWord, + UWord, + UWord, + UWord); #endif #define ERTS_ALC_O_ALLOC 0 diff --git a/erts/emulator/beam/erl_alloc_util.h b/erts/emulator/beam/erl_alloc_util.h index df560a0de2..fc1eddb116 100644 --- a/erts/emulator/beam/erl_alloc_util.h +++ b/erts/emulator/beam/erl_alloc_util.h @@ -227,7 +227,7 @@ erts_aint32_t erts_alcu_fix_alloc_shrink(Allctr_t *, erts_aint32_t); extern int erts_have_sbmbc_alloc; -typedef union {char c[8]; long l; double d;} Unit_t; +typedef union {char c[ERTS_ALLOC_ALIGN_BYTES]; long l; double d;} Unit_t; typedef struct Carrier_t_ Carrier_t; struct Carrier_t_ { diff --git a/erts/emulator/beam/erl_bif_guard.c b/erts/emulator/beam/erl_bif_guard.c index 01e6977a2c..dff59de69b 100644 --- a/erts/emulator/beam/erl_bif_guard.c +++ b/erts/emulator/beam/erl_bif_guard.c @@ -52,7 +52,7 @@ BIF_RETTYPE abs_1(BIF_ALIST_1) /* integer arguments */ if (is_small(BIF_ARG_1)) { i0 = signed_val(BIF_ARG_1); - i = labs(i0); + i = ERTS_SMALL_ABS(i0); if (i0 == MIN_SMALL) { hp = HAlloc(BIF_P, BIG_UINT_HEAP_SIZE); BIF_RET(uint_to_big(i, hp)); @@ -467,7 +467,7 @@ Eterm erts_gc_abs_1(Process* p, Eterm* reg, Uint live) /* integer arguments */ if (is_small(arg)) { i0 = signed_val(arg); - i = labs(i0); + i = ERTS_SMALL_ABS(i0); if (i0 == MIN_SMALL) { if (ERTS_NEED_GC(p, BIG_UINT_HEAP_SIZE)) { erts_garbage_collect(p, BIG_UINT_HEAP_SIZE, reg, live+1); diff --git a/erts/emulator/beam/erl_bif_info.c b/erts/emulator/beam/erl_bif_info.c index a79feaebdb..5a806777fe 100644 --- a/erts/emulator/beam/erl_bif_info.c +++ b/erts/emulator/beam/erl_bif_info.c @@ -78,7 +78,6 @@ static char erts_system_version[] = ("Erlang " ERLANG_OTP_RELEASE #ifdef ERTS_SMP " [smp:%beu:%beu]" #endif - " [rq:%beu]" #ifdef USE_THREADS " [async-threads:%d]" #endif @@ -301,9 +300,7 @@ erts_print_system_version(int to, void *arg, Process *c_p) #endif return erts_print(to, arg, erts_system_version #ifdef ERTS_SMP - , total, online, erts_no_run_queues -#else - , 1 + , total, online #endif #ifdef USE_THREADS , erts_async_max_threads @@ -3230,7 +3227,7 @@ BIF_RETTYPE statistics_1(BIF_ALIST_1) res = TUPLE2(hp, b1, b2); BIF_RET(res); } else if (BIF_ARG_1 == am_runtime) { - unsigned long u1, u2, dummy; + UWord u1, u2, dummy; Eterm b1, b2; elapsed_time_both(&u1,&dummy,&u2,&dummy); b1 = erts_make_integer(u1,BIF_P); diff --git a/erts/emulator/beam/erl_bif_port.c b/erts/emulator/beam/erl_bif_port.c index 6b8f1b21fd..1f6b62817d 100644 --- a/erts/emulator/beam/erl_bif_port.c +++ b/erts/emulator/beam/erl_bif_port.c @@ -1077,7 +1077,7 @@ struct packet_callback_args }; #define in_area(ptr,start,nbytes) \ - ((unsigned long)((char*)(ptr) - (char*)(start)) < (nbytes)) + ((UWord)((char*)(ptr) - (char*)(start)) < (nbytes)) static Eterm http_bld_string(struct packet_callback_args* pca, Uint **hpp, Uint *szp, diff --git a/erts/emulator/beam/erl_cpu_topology.c b/erts/emulator/beam/erl_cpu_topology.c index 03c0ef904a..fe3693d0ca 100644 --- a/erts/emulator/beam/erl_cpu_topology.c +++ b/erts/emulator/beam/erl_cpu_topology.c @@ -486,10 +486,7 @@ erts_sched_check_cpu_bind_post_suspend(ErtsSchedulerData *esdp) erts_thr_set_main_status(1, (int) esdp->no); /* Make sure we check if we should bind to a cpu or not... */ - if (esdp->run_queue->flags & ERTS_RUNQ_FLG_SHARED_RUNQ) - erts_smp_atomic32_set_nob(&esdp->chk_cpu_bind, 1); - else - esdp->run_queue->flags |= ERTS_RUNQ_FLG_CHK_CPU_BIND; + esdp->run_queue->flags |= ERTS_RUNQ_FLG_CHK_CPU_BIND; } #endif @@ -502,11 +499,7 @@ erts_sched_check_cpu_bind(ErtsSchedulerData *esdp) erts_cpu_groups_callback_list_t *cgcl; erts_cpu_groups_callback_call_t *cgcc; #ifdef ERTS_SMP - if (erts_common_run_queue) - erts_smp_atomic32_set_nob(&esdp->chk_cpu_bind, 0); - else { - esdp->run_queue->flags &= ~ERTS_RUNQ_FLG_CHK_CPU_BIND; - } + esdp->run_queue->flags &= ~ERTS_RUNQ_FLG_CHK_CPU_BIND; #endif erts_smp_runq_unlock(esdp->run_queue); erts_smp_rwmtx_rwlock(&cpuinfo_rwmtx); @@ -1729,16 +1722,8 @@ erts_init_cpu_topology(void) scheduler2cpu_map[ix].bound_id = -1; } - if (cpu_bind_order == ERTS_CPU_BIND_UNDEFINED) { - int ncpus = erts_get_cpu_configured(cpuinfo); - if (ncpus < 1 || erts_no_schedulers < ncpus) - cpu_bind_order = ERTS_CPU_BIND_NONE; - else - cpu_bind_order = ((system_cpudata || user_cpudata) - && (erts_bind_to_cpu(cpuinfo, -1) != -ENOTSUP) - ? ERTS_CPU_BIND_DEFAULT_BIND - : ERTS_CPU_BIND_NONE); - } + if (cpu_bind_order == ERTS_CPU_BIND_UNDEFINED) + cpu_bind_order = ERTS_CPU_BIND_NONE; reader_groups_map = add_cpu_groups(reader_groups, reader_groups_callback, diff --git a/erts/emulator/beam/erl_db.c b/erts/emulator/beam/erl_db.c index 38b4a2d460..eb89baf1c9 100644 --- a/erts/emulator/beam/erl_db.c +++ b/erts/emulator/beam/erl_db.c @@ -2853,10 +2853,10 @@ void init_db(void) bits = erts_fit_in_bits(db_max_tabs-1); if (bits > SMALL_BITS) { erl_exit(1,"Max limit for ets tabled too high %u (max %u).", - db_max_tabs, 1L<<SMALL_BITS); + db_max_tabs, ((Uint)1)<<SMALL_BITS); } - meta_main_tab_slot_mask = (1L<<bits) - 1; - meta_main_tab_seq_incr = (1L<<bits); + meta_main_tab_slot_mask = (((Uint)1)<<bits) - 1; + meta_main_tab_seq_incr = (((Uint)1)<<bits); size = sizeof(*meta_main_tab)*db_max_tabs; meta_main_tab = erts_db_alloc_nt(ERTS_ALC_T_DB_TABLES, size); @@ -2869,7 +2869,7 @@ void init_db(void) SET_NEXT_FREE_SLOT(db_max_tabs-1, (Uint)-1); meta_main_tab_first_free = 0; - meta_name_tab_mask = (1L<<(bits-1)) - 1; /* At least half the size of main tab */ + meta_name_tab_mask = (((Uint) 1)<<(bits-1)) - 1; /* At least half the size of main tab */ size = sizeof(struct meta_name_tab_entry)*(meta_name_tab_mask+1); meta_name_tab = erts_db_alloc_nt(ERTS_ALC_T_DB_TABLES, size); ERTS_ETS_MISC_MEM_ADD(size); diff --git a/erts/emulator/beam/erl_driver.h b/erts/emulator/beam/erl_driver.h index ae0c9def90..25483380ed 100644 --- a/erts/emulator/beam/erl_driver.h +++ b/erts/emulator/beam/erl_driver.h @@ -160,10 +160,15 @@ typedef struct { /* * Integer types */ - +#if defined(__WIN32__) && (SIZEOF_VOID_P == 8) +typedef unsigned __int64 ErlDrvTermData; +typedef unsigned __int64 ErlDrvUInt; +typedef signed __int64 ErlDrvSInt; +#else typedef unsigned long ErlDrvTermData; typedef unsigned long ErlDrvUInt; typedef signed long ErlDrvSInt; +#endif #if defined(__WIN32__) typedef unsigned __int64 ErlDrvUInt64; @@ -184,7 +189,7 @@ typedef long long ErlDrvSInt64; */ typedef struct erl_drv_binary { - long orig_size; /* total length of binary */ + ErlDrvSInt orig_size; /* total length of binary */ char orig_bytes[1]; /* the data (char instead of byte!) */ } ErlDrvBinary; diff --git a/erts/emulator/beam/erl_gc.h b/erts/emulator/beam/erl_gc.h index 807ef8ae8d..0ba1009bd3 100644 --- a/erts/emulator/beam/erl_gc.h +++ b/erts/emulator/beam/erl_gc.h @@ -62,7 +62,7 @@ do { \ } while(0) #define in_area(ptr,start,nbytes) \ - ((unsigned long)((char*)(ptr) - (char*)(start)) < (nbytes)) + ((UWord)((char*)(ptr) - (char*)(start)) < (nbytes)) extern Uint erts_test_long_gc_sleep; diff --git a/erts/emulator/beam/erl_init.c b/erts/emulator/beam/erl_init.c index 6c4ba2af68..717315d8bd 100644 --- a/erts/emulator/beam/erl_init.c +++ b/erts/emulator/beam/erl_init.c @@ -111,7 +111,6 @@ Eterm erts_error_logger_warnings; /* What to map warning logs to, am_error, int erts_compat_rel; -static int use_multi_run_queue; static int no_schedulers; static int no_schedulers_online; @@ -254,8 +253,7 @@ erl_init(int ncpu) erts_init_time(); erts_init_sys_common_misc(); erts_init_process(ncpu); - erts_init_scheduling(use_multi_run_queue, - no_schedulers, + erts_init_scheduling(no_schedulers, no_schedulers_online); erts_init_cpu_topology(); /* Must be after init_scheduling */ erts_alloc_late_init(); @@ -613,7 +611,6 @@ early_init(int *argc, char **argv) /* 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; display_items = 200; @@ -1257,12 +1254,8 @@ erl_start(int argc, char **argv) erts_usage(); } } - else if (sys_strcmp("mrq", sub_param) == 0) - use_multi_run_queue = 1; else if (sys_strcmp("nsp", sub_param) == 0) erts_use_sender_punish = 0; - else if (sys_strcmp("srq", sub_param) == 0) - use_multi_run_queue = 0; else if (sys_strcmp("wt", sub_param) == 0) { arg = get_arg(sub_param+2, argv[i+1], &i); if (erts_sched_set_wakeup_limit(arg) != 0) { diff --git a/erts/emulator/beam/erl_lock_check.c b/erts/emulator/beam/erl_lock_check.c index 44da6b6c51..09e85893c3 100644 --- a/erts/emulator/beam/erl_lock_check.c +++ b/erts/emulator/beam/erl_lock_check.c @@ -173,7 +173,6 @@ static erts_lc_lock_order_t erts_lock_order[] = { { "pix_lock", "address" }, { "run_queues_lists", NULL }, { "sched_stat", NULL }, - { "run_queue_sleep_list", "address" }, #endif { "async_init_mtx", NULL }, #ifdef ERTS_SMP @@ -1253,7 +1252,7 @@ erts_lc_init_lock(erts_lc_lock_t *lck, char *name, Uint16 flags) { lck->id = erts_lc_get_lock_order_id(name); - lck->extra = &lck->extra; + lck->extra = (UWord) &lck->extra; ASSERT(is_not_immed(lck->extra)); lck->flags = flags; lck->inited = ERTS_LC_INITITALIZED; diff --git a/erts/emulator/beam/erl_nif.c b/erts/emulator/beam/erl_nif.c index 62798bb2c1..58a09986d2 100644 --- a/erts/emulator/beam/erl_nif.c +++ b/erts/emulator/beam/erl_nif.c @@ -531,7 +531,7 @@ int enif_alloc_binary(size_t size, ErlNifBinary* bin) } refbin->flags = BIN_FLAG_DRV; /* BUGBUG: Flag? */ erts_refc_init(&refbin->refc, 1); - refbin->orig_size = (long) size; + refbin->orig_size = (SWord) size; bin->size = size; bin->data = (unsigned char*) refbin->orig_bytes; @@ -744,7 +744,8 @@ int enif_get_int(ErlNifEnv* env, Eterm term, int* ip) { #if SIZEOF_INT == ERTS_SIZEOF_ETERM return term_to_Sint(term, (Sint*)ip); -#elif SIZEOF_LONG == ERTS_SIZEOF_ETERM +#elif (SIZEOF_LONG == ERTS_SIZEOF_ETERM) || \ + (SIZEOF_LONG_LONG == ERTS_SIZEOF_ETERM) Sint i; if (!term_to_Sint(term, &i) || i < INT_MIN || i > INT_MAX) { return 0; @@ -760,7 +761,8 @@ int enif_get_uint(ErlNifEnv* env, Eterm term, unsigned* ip) { #if SIZEOF_INT == ERTS_SIZEOF_ETERM return term_to_Uint(term, (Uint*)ip); -#elif SIZEOF_LONG == ERTS_SIZEOF_ETERM +#elif (SIZEOF_LONG == ERTS_SIZEOF_ETERM) || \ + (SIZEOF_LONG_LONG == ERTS_SIZEOF_ETERM) Uint i; if (!term_to_Uint(term, &i) || i > UINT_MAX) { return 0; @@ -776,6 +778,13 @@ int enif_get_long(ErlNifEnv* env, Eterm term, long* ip) return term_to_Sint(term, ip); #elif SIZEOF_LONG == 8 return term_to_Sint64(term, ip); +#elif SIZEOF_LONG == SIZEOF_INT + int tmp,ret; + ret = enif_get_int(env,term,&tmp); + if (ret) { + *ip = (long) tmp; + } + return ret; #else # error Unknown long word size #endif @@ -787,6 +796,14 @@ int enif_get_ulong(ErlNifEnv* env, Eterm term, unsigned long* ip) return term_to_Uint(term, ip); #elif SIZEOF_LONG == 8 return term_to_Uint64(term, ip); +#elif SIZEOF_LONG == SIZEOF_INT + int ret; + unsigned int tmp; + ret = enif_get_uint(env,term,&tmp); + if (ret) { + *ip = (unsigned long) tmp; + } + return ret; #else # error Unknown long word size #endif @@ -847,7 +864,8 @@ ERL_NIF_TERM enif_make_int(ErlNifEnv* env, int i) { #if SIZEOF_INT == ERTS_SIZEOF_ETERM return IS_SSMALL(i) ? make_small(i) : small_to_big(i,alloc_heap(env,2)); -#elif SIZEOF_LONG == ERTS_SIZEOF_ETERM +#elif (SIZEOF_LONG == ERTS_SIZEOF_ETERM) || \ + (SIZEOF_LONG_LONG == ERTS_SIZEOF_ETERM) return make_small(i); #endif } @@ -856,7 +874,8 @@ ERL_NIF_TERM enif_make_uint(ErlNifEnv* env, unsigned i) { #if SIZEOF_INT == ERTS_SIZEOF_ETERM return IS_USMALL(0,i) ? make_small(i) : uint_to_big(i,alloc_heap(env,2)); -#elif SIZEOF_LONG == ERTS_SIZEOF_ETERM +#elif (SIZEOF_LONG == ERTS_SIZEOF_ETERM) || \ + (SIZEOF_LONG_LONG == ERTS_SIZEOF_ETERM) return make_small(i); #endif } @@ -868,6 +887,8 @@ ERL_NIF_TERM enif_make_long(ErlNifEnv* env, long i) } #if SIZEOF_LONG == ERTS_SIZEOF_ETERM return small_to_big(i, alloc_heap(env,2)); +#elif SIZEOF_LONG_LONG == ERTS_SIZEOF_ETERM + return make_small(i); #elif SIZEOF_LONG == 8 ensure_heap(env,3); return erts_sint64_to_big(i, &env->hp); @@ -881,6 +902,8 @@ ERL_NIF_TERM enif_make_ulong(ErlNifEnv* env, unsigned long i) } #if SIZEOF_LONG == ERTS_SIZEOF_ETERM return uint_to_big(i,alloc_heap(env,2)); +#elif SIZEOF_LONG_LONG == ERTS_SIZEOF_ETERM + return make_small(i); #elif SIZEOF_LONG == 8 ensure_heap(env,3); return erts_uint64_to_big(i, &env->hp); @@ -1157,7 +1180,7 @@ static ErlNifResourceType* find_resource_type(Eterm module, Eterm name) } #define in_area(ptr,start,nbytes) \ - ((unsigned long)((char*)(ptr) - (char*)(start)) < (nbytes)) + ((UWord)((char*)(ptr) - (char*)(start)) < (nbytes)) static void close_lib(struct erl_module_nif* lib) @@ -1484,6 +1507,7 @@ BIF_RETTYPE load_nif_2(BIF_ALIST_2) Eterm ret = am_ok; int veto; struct erl_module_nif* lib = NULL; + int reload_warning = 0; len = list_length(BIF_ARG_1); if (len < 0) { @@ -1623,6 +1647,7 @@ BIF_RETTYPE load_nif_2(BIF_ALIST_2) else { mod->nif->entry = NULL; /* to prevent 'unload' callback */ erts_unload_nif(mod->nif); + reload_warning = 1; } } else { @@ -1669,7 +1694,7 @@ BIF_RETTYPE load_nif_2(BIF_ALIST_2) } else { /* Function traced, patch the original instruction word */ BpData** bps = (BpData**) code_ptr[1]; - BpData* bp = (BpData*) bps[bp_sched2ix()]; + BpData* bp = (BpData*) bps[erts_bp_sched2ix()]; bp->orig_instr = (BeamInstr) BeamOp(op_call_nif); } code_ptr[5+1] = (BeamInstr) entry->funcs[i].fptr; @@ -1691,6 +1716,15 @@ BIF_RETTYPE load_nif_2(BIF_ALIST_2) erts_smp_thr_progress_unblock(); erts_smp_proc_lock(BIF_P, ERTS_PROC_LOCK_MAIN); erts_free(ERTS_ALC_T_TMP, lib_name); + + if (reload_warning) { + erts_dsprintf_buf_t* dsbufp = erts_create_logger_dsbuf(); + erts_dsprintf(dsbufp, + "Repeated calls to erlang:load_nif from module '%T'.\n\n" + "The NIF reload mechanism is deprecated and must not " + "be used in production systems.\n", mod_atom); + erts_send_warning_to_logger(BIF_P->group_leader, dsbufp); + } BIF_RET(ret); } diff --git a/erts/emulator/beam/erl_nif.h b/erts/emulator/beam/erl_nif.h index fea527f954..e5d99dc4f1 100644 --- a/erts/emulator/beam/erl_nif.h +++ b/erts/emulator/beam/erl_nif.h @@ -87,7 +87,11 @@ typedef long long ErlNifSInt64; typedef unsigned int ERL_NIF_TERM; #else # define ERL_NIF_VM_VARIANT "beam.vanilla" +# if SIZEOF_LONG == SIZEOF_VOID_P typedef unsigned long ERL_NIF_TERM; +# elif SIZEOF_LONG_LONG == SIZEOF_VOID_P +typedef unsigned long long ERL_NIF_TERM; +# endif #endif struct enif_environment_t; diff --git a/erts/emulator/beam/erl_nmgc.c b/erts/emulator/beam/erl_nmgc.c index d7bfb2ab12..2a8c819360 100644 --- a/erts/emulator/beam/erl_nmgc.c +++ b/erts/emulator/beam/erl_nmgc.c @@ -1391,7 +1391,7 @@ Eterm *erts_inc_alloc(int need) if (ma_gc_flags & GC_MAJOR) { if (need > 254) { blackmap[(Eterm*)this - global_old_heap] = 255; - *(int*)((long)(&blackmap[(Eterm*)this - global_old_heap]+4) & ~3) = + *(int*)((UWord)(&blackmap[(Eterm*)this - global_old_heap]+4) & ~3) = need; } else blackmap[(Eterm*)this - global_old_heap] = need; diff --git a/erts/emulator/beam/erl_node_container_utils.h b/erts/emulator/beam/erl_node_container_utils.h index 2c67e781e0..329a2204cc 100644 --- a/erts/emulator/beam/erl_node_container_utils.h +++ b/erts/emulator/beam/erl_node_container_utils.h @@ -176,7 +176,7 @@ extern int erts_use_r9_pids_ports; * 32-bit CPU. */ -#define ERTS_MAX_PROCESSES ((1L << 27)-1) +#define ERTS_MAX_PROCESSES ((SWORD_CONSTANT(1) << 27)-1) #if (ERTS_MAX_PROCESSES > MAX_SMALL) # error "The maximum number of processes must fit in a SMALL." #endif diff --git a/erts/emulator/beam/erl_port_task.c b/erts/emulator/beam/erl_port_task.c index 87b8e5131b..2b5e65b11a 100644 --- a/erts/emulator/beam/erl_port_task.c +++ b/erts/emulator/beam/erl_port_task.c @@ -1048,8 +1048,6 @@ erts_port_migrate(Port *prt, int *prt_locked, ERTS_SMP_LC_CHK_RUNQ_LOCK(from_rq, *from_locked); ERTS_SMP_LC_CHK_RUNQ_LOCK(to_rq, *to_locked); - ASSERT(!erts_common_run_queue); - if (!*from_locked || !*to_locked) { if (from_rq < to_rq) { if (!*to_locked) { diff --git a/erts/emulator/beam/erl_process.c b/erts/emulator/beam/erl_process.c index 84c0ded016..ec4b1dcd98 100644 --- a/erts/emulator/beam/erl_process.c +++ b/erts/emulator/beam/erl_process.c @@ -196,8 +196,6 @@ do { \ erts_sched_stat_t erts_sched_stat; -ErtsRunQueue *erts_common_run_queue; - #ifdef USE_THREADS static erts_tsd_key_t sched_data_key; #endif @@ -225,10 +223,6 @@ typedef union { static ErtsAlignedSchedulerSleepInfo *aligned_sched_sleep_info; -#ifndef BM_COUNTERS -static int processes_busy; -#endif - Process** process_tab; static Uint last_reductions; static Uint last_exact_reductions; @@ -497,9 +491,6 @@ erts_init_process(int ncpu) p_serial_shift = erts_fit_in_bits(erts_max_processes - 1); p_serial_mask = ((~(~((Uint) 0) << proc_bits)) >> p_serial_shift); erts_process_tab_index_mask = ~(~((Uint) 0) << p_serial_shift); -#ifndef BM_COUNTERS - processes_busy = 0; -#endif last_reductions = 0; last_exact_reductions = 0; erts_default_process_flags = 0; @@ -1724,21 +1715,12 @@ scheduler_wait(int *fcalls, ErtsSchedulerData *esdp, ErtsRunQueue *rq) ERTS_SMP_LC_ASSERT(erts_smp_lc_runq_is_locked(rq)); - erts_smp_spin_lock(&rq->sleepers.lock); flgs = sched_prep_spin_wait(ssi); if (flgs & ERTS_SSI_FLG_SUSPENDED) { /* Go suspend instead... */ - erts_smp_spin_unlock(&rq->sleepers.lock); return; } - ssi->prev = NULL; - ssi->next = rq->sleepers.list; - if (rq->sleepers.list) - rq->sleepers.list->prev = ssi; - rq->sleepers.list = ssi; - erts_smp_spin_unlock(&rq->sleepers.lock); - /* * If all schedulers are waiting, one of them *should* * be waiting in erl_sys_schedule() @@ -1997,10 +1979,10 @@ ssi_flags_set_wake(ErtsSchedulerSleepInfo *ssi) } static void -wake_scheduler(ErtsRunQueue *rq, int incq, int one) +wake_scheduler(ErtsRunQueue *rq, int incq) { ErtsSchedulerSleepInfo *ssi; - ErtsSchedulerSleepList *sl; + erts_aint32_t flgs; /* * The unlocked run queue is not strictly necessary @@ -2012,56 +1994,13 @@ wake_scheduler(ErtsRunQueue *rq, int incq, int one) */ ERTS_SMP_LC_ASSERT(!erts_smp_lc_runq_is_locked(rq)); - sl = &rq->sleepers; + ssi = rq->scheduler->ssi; - erts_smp_spin_lock(&sl->lock); - ssi = sl->list; - if (!ssi) - erts_smp_spin_unlock(&sl->lock); - else if (one) { - erts_aint32_t flgs; - if (ssi->prev) - ssi->prev->next = ssi->next; - else { - ASSERT(sl->list == ssi); - sl->list = ssi->next; - } - if (ssi->next) - ssi->next->prev = ssi->prev; - - erts_smp_spin_unlock(&sl->lock); + flgs = ssi_flags_set_wake(ssi); + erts_sched_finish_poke(ssi, flgs); - flgs = ssi_flags_set_wake(ssi); - erts_sched_finish_poke(ssi, flgs); - - if (incq && !erts_common_run_queue && (flgs & ERTS_SSI_FLG_WAITING)) - non_empty_runq(rq); - } - else { - sl->list = NULL; - erts_smp_spin_unlock(&sl->lock); - - ERTS_THR_MEMORY_BARRIER; - do { - ErtsSchedulerSleepInfo *wake_ssi = ssi; - ssi = ssi->next; - erts_sched_finish_poke(wake_ssi, ssi_flags_set_wake(wake_ssi)); - } while (ssi); - } -} - -static void -wake_all_schedulers(void) -{ - if (erts_common_run_queue) - wake_scheduler(erts_common_run_queue, 0, 0); - else { - int ix; - for (ix = 0; ix < erts_no_run_queues; ix++) { - ErtsRunQueue *rq = ERTS_RUNQ_IX(ix); - wake_scheduler(rq, 0, 1); - } - } + if (incq && (flgs & ERTS_SSI_FLG_WAITING)) + non_empty_runq(rq); } #define ERTS_NO_USED_RUNQS_SHIFT 16 @@ -2154,7 +2093,7 @@ chk_wake_sched(ErtsRunQueue *crq, int ix, int activate) erts_smp_xrunq_unlock(crq, wrq); } } - wake_scheduler(wrq, 0, 1); + wake_scheduler(wrq, 0); return 1; } return 0; @@ -2202,7 +2141,7 @@ smp_notify_inc_runq(ErtsRunQueue *runq) { #ifdef ERTS_SMP if (runq) - wake_scheduler(runq, 1, 1); + wake_scheduler(runq, 1); #endif } @@ -2217,19 +2156,12 @@ erts_sched_notify_check_cpu_bind(void) { #ifdef ERTS_SMP int ix; - if (erts_common_run_queue) { - for (ix = 0; ix < erts_no_schedulers; ix++) - erts_smp_atomic32_set_relb(&ERTS_SCHEDULER_IX(ix)->chk_cpu_bind, 1); - wake_all_schedulers(); - } - else { - for (ix = 0; ix < erts_no_run_queues; ix++) { - ErtsRunQueue *rq = ERTS_RUNQ_IX(ix); - erts_smp_runq_lock(rq); - rq->flags |= ERTS_RUNQ_FLG_CHK_CPU_BIND; - erts_smp_runq_unlock(rq); - wake_scheduler(rq, 0, 1); - }; + for (ix = 0; ix < erts_no_run_queues; ix++) { + ErtsRunQueue *rq = ERTS_RUNQ_IX(ix); + erts_smp_runq_lock(rq); + rq->flags |= ERTS_RUNQ_FLG_CHK_CPU_BIND; + erts_smp_runq_unlock(rq); + wake_scheduler(rq, 0); } #else erts_sched_check_cpu_bind(erts_get_scheduler_data()); @@ -2498,7 +2430,7 @@ evacuate_run_queue(ErtsRunQueue *evac_rq, ErtsRunQueue *rq) if (notify_to_rq) smp_notify_inc_runq(rq); - wake_scheduler(evac_rq, 0, 1); + wake_scheduler(evac_rq, 0); } static int @@ -2656,9 +2588,6 @@ static int try_steal_task(ErtsRunQueue *rq) { int res, rq_locked, vix, active_rqs, blnc_rqs; - - if (erts_common_run_queue) - return 0; /* * We are not allowed to steal jobs to this run queue @@ -3335,14 +3264,10 @@ init_aux_work_data(ErtsAuxWorkData *awdp, ErtsSchedulerData *esdp) } void -erts_init_scheduling(int mrq, int no_schedulers, int no_schedulers_online) +erts_init_scheduling(int no_schedulers, int no_schedulers_online) { int ix, n, no_ssi; -#ifndef ERTS_SMP - mrq = 0; -#endif - init_misc_op_list_alloc(); ASSERT(no_schedulers_online <= no_schedulers); @@ -3351,7 +3276,7 @@ erts_init_scheduling(int mrq, int no_schedulers, int no_schedulers_online) /* Create and initialize run queues */ - n = (int) (mrq ? no_schedulers : 1); + n = no_schedulers; erts_aligned_run_queues = erts_alloc_permanent_cache_aligned(ERTS_ALC_T_RUNQS, @@ -3376,14 +3301,9 @@ erts_init_scheduling(int mrq, int no_schedulers, int no_schedulers_online) erts_smp_mtx_init_x(&rq->mtx, "run_queue", make_small(ix + 1)); erts_smp_cnd_init(&rq->cnd); -#ifdef ERTS_SMP - erts_smp_spinlock_init(&rq->sleepers.lock, "run_queue_sleep_list"); - rq->sleepers.list = NULL; -#endif - rq->waiting = 0; rq->woken = 0; - rq->flags = !mrq ? ERTS_RUNQ_FLG_SHARED_RUNQ : 0; + rq->flags = 0; rq->check_balance_reds = ERTS_RUNQ_CALL_CHECK_BALANCE_REDS; rq->full_reds_history_sum = 0; for (rix = 0; rix < ERTS_FULL_REDS_HISTORY_SIZE; rix++) { @@ -3429,8 +3349,6 @@ erts_init_scheduling(int mrq, int no_schedulers, int no_schedulers_online) rq->ports.end = NULL; } - erts_common_run_queue = !mrq ? ERTS_RUNQ_IX(0) : NULL; - #ifdef ERTS_SMP if (erts_no_run_queues != 1) { @@ -3507,18 +3425,9 @@ erts_init_scheduling(int mrq, int no_schedulers, int no_schedulers_online) erts_init_atom_cache_map(&esdp->atom_cache_map); - if (erts_common_run_queue) { - esdp->run_queue = erts_common_run_queue; - esdp->run_queue->scheduler = NULL; - } - else { - esdp->run_queue = ERTS_RUNQ_IX(ix); - esdp->run_queue->scheduler = esdp; - } + esdp->run_queue = ERTS_RUNQ_IX(ix); + esdp->run_queue->scheduler = esdp; -#ifdef ERTS_SMP - erts_smp_atomic32_init_nob(&esdp->chk_cpu_bind, 0); -#endif init_aux_work_data(&esdp->aux_work_data, esdp); } @@ -3541,8 +3450,7 @@ erts_init_scheduling(int mrq, int no_schedulers, int no_schedulers_online) schdlr_sspnd.msb.ongoing = 0; erts_smp_atomic32_init_nob(&schdlr_sspnd.active, no_schedulers); schdlr_sspnd.msb.procs = NULL; - init_no_runqs(no_schedulers, - erts_common_run_queue ? 1 : no_schedulers_online); + init_no_runqs(no_schedulers, no_schedulers_online); balance_info.last_active_runqs = no_schedulers; erts_smp_mtx_init(&balance_info.update_mtx, "migration_info_update"); balance_info.forced_check_balance = 0; @@ -3555,16 +3463,9 @@ erts_init_scheduling(int mrq, int no_schedulers, int no_schedulers_online) balance_info.n = 0; if (no_schedulers_online < no_schedulers) { - if (erts_common_run_queue) { - for (ix = no_schedulers_online; ix < no_schedulers; ix++) - erts_smp_atomic32_read_bor_nob(&ERTS_SCHED_SLEEP_INFO_IX(ix)->flags, - ERTS_SSI_FLG_SUSPENDED); - } - else { - for (ix = no_schedulers_online; ix < erts_no_run_queues; ix++) - evacuate_run_queue(ERTS_RUNQ_IX(ix), - ERTS_RUNQ_IX(ix % no_schedulers_online)); - } + for (ix = no_schedulers_online; ix < erts_no_run_queues; ix++) + evacuate_run_queue(ERTS_RUNQ_IX(ix), + ERTS_RUNQ_IX(ix % no_schedulers_online)); } schdlr_sspnd.wait_curr_online = no_schedulers_online; @@ -3609,8 +3510,6 @@ ErtsRunQueue * erts_schedid2runq(Uint id) { int ix; - if (erts_common_run_queue) - return erts_common_run_queue; ix = (int) id - 1; ASSERT(0 <= ix && ix < erts_no_run_queues); return ERTS_RUNQ_IX(ix); @@ -3901,9 +3800,11 @@ suspend_scheduler(ErtsSchedulerData *esdp) wake = 0; } - flgs = erts_smp_atomic32_read_acqb(&ssi->flags); - if (!(flgs & ERTS_SSI_FLG_SUSPENDED)) - break; + if (curr_online && !ongoing_multi_scheduling_block()) { + flgs = erts_smp_atomic32_read_acqb(&ssi->flags); + if (!(flgs & ERTS_SSI_FLG_SUSPENDED)) + break; + } erts_smp_mtx_unlock(&schdlr_sspnd.mtx); while (1) { @@ -4095,10 +3996,6 @@ erts_set_schedulers_online(Process *p, for (ix = online; ix < no; ix++) erts_sched_poke(ERTS_SCHED_SLEEP_INFO_IX(ix)); } - else if (erts_common_run_queue) { - for (ix = online; ix < no; ix++) - scheduler_ix_resume_wake(ix); - } else { if (plocks) { have_unlocked_plocks = 1; @@ -4146,15 +4043,6 @@ erts_set_schedulers_online(Process *p, for (ix = no; ix < online; ix++) erts_sched_poke(ERTS_SCHED_SLEEP_INFO_IX(ix)); } - else if (erts_common_run_queue) { - for (ix = no; ix < online; ix++) { - ErtsSchedulerSleepInfo *ssi; - ssi = ERTS_SCHED_SLEEP_INFO_IX(ix); - erts_smp_atomic32_read_bor_nob(&ssi->flags, - ERTS_SSI_FLG_SUSPENDED); - } - wake_all_schedulers(); - } else { if (plocks) { have_unlocked_plocks = 1; @@ -4181,7 +4069,7 @@ erts_set_schedulers_online(Process *p, erts_smp_mtx_lock(&schdlr_sspnd.mtx); for (ix = no; ix < online; ix++) { ErtsRunQueue *rq = ERTS_RUNQ_IX(ix); - wake_scheduler(rq, 0, 1); + wake_scheduler(rq, 0); } } } @@ -4274,33 +4162,26 @@ erts_block_multi_scheduling(Process *p, ErtsProcLocks plocks, int on, int all) res = ERTS_SCHDLR_SSPND_YIELD_DONE_MSCHED_BLOCKED; schdlr_sspnd.msb.wait_active = 2; } - if (erts_common_run_queue) { - for (ix = 1; ix < online; ix++) - erts_smp_atomic32_read_bor_nob(&ERTS_SCHED_SLEEP_INFO_IX(ix)->flags, - ERTS_SSI_FLG_SUSPENDED); - wake_all_schedulers(); - } - else { - erts_smp_mtx_unlock(&schdlr_sspnd.mtx); - erts_smp_mtx_lock(&balance_info.update_mtx); - set_no_used_runqs(1); - for (ix = 0; ix < online; ix++) { - ErtsRunQueue *rq = ERTS_RUNQ_IX(ix); - erts_smp_runq_lock(rq); - ASSERT(!(rq->flags & ERTS_RUNQ_FLG_SUSPENDED)); - ERTS_RUNQ_RESET_MIGRATION_PATHS(rq, 0x7); - erts_smp_runq_unlock(rq); - } - /* - * Evacuate all activities in all other run queues - * into the first run queue. Note order is important, - * online run queues has to be evacuated last. - */ - for (ix = erts_no_run_queues-1; ix >= 1; ix--) - evacuate_run_queue(ERTS_RUNQ_IX(ix), ERTS_RUNQ_IX(0)); - erts_smp_mtx_unlock(&balance_info.update_mtx); - erts_smp_mtx_lock(&schdlr_sspnd.mtx); + + erts_smp_mtx_unlock(&schdlr_sspnd.mtx); + erts_smp_mtx_lock(&balance_info.update_mtx); + set_no_used_runqs(1); + for (ix = 0; ix < online; ix++) { + ErtsRunQueue *rq = ERTS_RUNQ_IX(ix); + erts_smp_runq_lock(rq); + ASSERT(!(rq->flags & ERTS_RUNQ_FLG_SUSPENDED)); + ERTS_RUNQ_RESET_MIGRATION_PATHS(rq, 0x7); + erts_smp_runq_unlock(rq); } + /* + * Evacuate all activities in all other run queues + * into the first run queue. Note order is important, + * online run queues has to be evacuated last. + */ + for (ix = erts_no_run_queues-1; ix >= 1; ix--) + evacuate_run_queue(ERTS_RUNQ_IX(ix), ERTS_RUNQ_IX(0)); + erts_smp_mtx_unlock(&balance_info.update_mtx); + erts_smp_mtx_lock(&schdlr_sspnd.mtx); if (erts_smp_atomic32_read_nob(&schdlr_sspnd.active) != schdlr_sspnd.msb.wait_active) { @@ -4412,12 +4293,6 @@ erts_block_multi_scheduling(Process *p, ErtsProcLocks plocks, int on, int all) ASSERT(erts_smp_atomic32_read_nob(&schdlr_sspnd.active) == 1); ERTS_SCHDLR_SSPND_CHNG_SET(0, ERTS_SCHDLR_SSPND_CHNG_MSB); } - else if (erts_common_run_queue) { - for (ix = 1; ix < schdlr_sspnd.online; ix++) - erts_smp_atomic32_read_band_nob(&ERTS_SCHED_SLEEP_INFO_IX(ix)->flags, - ~ERTS_SSI_FLG_SUSPENDED); - wake_all_schedulers(); - } else { int online = schdlr_sspnd.online; erts_smp_mtx_unlock(&schdlr_sspnd.mtx); @@ -5096,7 +4971,7 @@ suspend_process_2(BIF_ALIST_2) /* This is really a piece of cake without SMP support... */ if (!smon->active) { - suspend_process(erts_common_run_queue, suspendee); + suspend_process(ERTS_RUNQ_IX(0), suspendee); smon->active++; res = am_true; } @@ -5666,8 +5541,6 @@ erts_proc_migrate(Process *p, ErtsProcLocks *plcks, || from_locked); ERTS_SMP_LC_CHK_RUNQ_LOCK(from_rq, *from_locked); ERTS_SMP_LC_CHK_RUNQ_LOCK(to_rq, *to_locked); - - ASSERT(!erts_common_run_queue); /* * If we have the lock on the run queue to migrate to, @@ -5818,25 +5691,17 @@ erts_process_status(Process *c_p, ErtsProcLocks c_p_locks, int i; ErtsSchedulerData *esdp; - if (erts_common_run_queue) - erts_smp_runq_lock(erts_common_run_queue); - for (i = 0; i < erts_no_schedulers; i++) { esdp = ERTS_SCHEDULER_IX(i); - if (!erts_common_run_queue) - erts_smp_runq_lock(esdp->run_queue); + erts_smp_runq_lock(esdp->run_queue); if (esdp->free_process && esdp->free_process->id == rpid) { res = am_free; - if (!erts_common_run_queue) - erts_smp_runq_unlock(esdp->run_queue); + erts_smp_runq_unlock(esdp->run_queue); break; } - if (!erts_common_run_queue) - erts_smp_runq_unlock(esdp->run_queue); + erts_smp_runq_unlock(esdp->run_queue); } - if (erts_common_run_queue) - erts_smp_runq_unlock(erts_common_run_queue); #endif } @@ -6147,10 +6012,8 @@ Process *schedule(Process *p, int calls) #ifdef ERTS_SMP - if (!(rq->flags & ERTS_RUNQ_FLG_SHARED_RUNQ) - && rq->check_balance_reds <= 0) { + if (rq->check_balance_reds <= 0) check_balance(rq); - } ERTS_SMP_LC_ASSERT(!erts_thr_progress_is_blocking()); ERTS_SMP_LC_ASSERT(erts_smp_lc_runq_is_locked(rq)); @@ -6160,20 +6023,15 @@ Process *schedule(Process *p, int calls) continue_check_activities_to_run: - if (rq->flags & (ERTS_RUNQ_FLG_SHARED_RUNQ - | ERTS_RUNQ_FLG_CHK_CPU_BIND + if (rq->flags & (ERTS_RUNQ_FLG_CHK_CPU_BIND | ERTS_RUNQ_FLG_SUSPENDED)) { - if ((rq->flags & ERTS_RUNQ_FLG_SUSPENDED) - || (erts_smp_atomic32_read_acqb(&esdp->ssi->flags) - & ERTS_SSI_FLG_SUSPENDED)) { + if (rq->flags & ERTS_RUNQ_FLG_SUSPENDED) { ASSERT(erts_smp_atomic32_read_nob(&esdp->ssi->flags) & ERTS_SSI_FLG_SUSPENDED); suspend_scheduler(esdp); } - if ((rq->flags & ERTS_RUNQ_FLG_CHK_CPU_BIND) - || erts_smp_atomic32_read_acqb(&esdp->chk_cpu_bind)) { + if (rq->flags & ERTS_RUNQ_FLG_CHK_CPU_BIND) erts_sched_check_cpu_bind(esdp); - } } { @@ -6215,16 +6073,11 @@ Process *schedule(Process *p, int calls) empty_runq(rq); - if (rq->flags & (ERTS_RUNQ_FLG_SHARED_RUNQ - | ERTS_RUNQ_FLG_SUSPENDED)) { - if ((rq->flags & ERTS_RUNQ_FLG_SUSPENDED) - || (erts_smp_atomic32_read_acqb(&esdp->ssi->flags) - & ERTS_SSI_FLG_SUSPENDED)) { - ASSERT(erts_smp_atomic32_read_nob(&esdp->ssi->flags) - & ERTS_SSI_FLG_SUSPENDED); - non_empty_runq(rq); - goto continue_check_activities_to_run; - } + if (rq->flags & ERTS_RUNQ_FLG_SUSPENDED) { + ASSERT(erts_smp_atomic32_read_nob(&esdp->ssi->flags) + & ERTS_SSI_FLG_SUSPENDED); + non_empty_runq(rq); + goto continue_check_activities_to_run; } else if (!(rq->flags & ERTS_RUNQ_FLG_INACTIVE)) { /* @@ -6289,11 +6142,7 @@ Process *schedule(Process *p, int calls) else if (rq->wakeup_other < wakeup_other_limit) rq->wakeup_other += rq->len*wo_reds + ERTS_WAKEUP_OTHER_FIXED_INC; else { - if (erts_common_run_queue) { - if (erts_common_run_queue->waiting) - wake_scheduler(erts_common_run_queue, 0, 1); - } - else if (erts_smp_atomic32_read_acqb(&no_empty_run_queues) != 0) { + if (erts_smp_atomic32_read_acqb(&no_empty_run_queues) != 0) { wake_scheduler_on_empty_runq(rq); rq->wakeup_other = 0; } @@ -6892,7 +6741,9 @@ erl_create_process(Process* parent, /* Parent of process (default group leader). goto error; } +#ifdef BM_COUNTERS processes_busy++; +#endif BM_COUNT(processes_spawned); #ifndef HYBRID @@ -8415,7 +8266,9 @@ continue_exit_process(Process *p pbt = ERTS_PROC_SET_CALL_TIME(p, ERTS_PROC_LOCKS_ALL, NULL); erts_smp_proc_unlock(p, ERTS_PROC_LOCKS_ALL); +#ifdef BM_COUNTERS processes_busy--; +#endif if (dep) { erts_do_net_exits(dep, reason); diff --git a/erts/emulator/beam/erl_process.h b/erts/emulator/beam/erl_process.h index 69ff423133..a51b380bb0 100644 --- a/erts/emulator/beam/erl_process.h +++ b/erts/emulator/beam/erl_process.h @@ -144,12 +144,10 @@ extern int erts_sched_thread_suggested_stack_size; (((Uint32) 1) << (ERTS_RUNQ_FLG_BASE2 + 1)) #define ERTS_RUNQ_FLG_SUSPENDED \ (((Uint32) 1) << (ERTS_RUNQ_FLG_BASE2 + 2)) -#define ERTS_RUNQ_FLG_SHARED_RUNQ \ - (((Uint32) 1) << (ERTS_RUNQ_FLG_BASE2 + 3)) #define ERTS_RUNQ_FLG_CHK_CPU_BIND \ - (((Uint32) 1) << (ERTS_RUNQ_FLG_BASE2 + 4)) + (((Uint32) 1) << (ERTS_RUNQ_FLG_BASE2 + 3)) #define ERTS_RUNQ_FLG_INACTIVE \ - (((Uint32) 1) << (ERTS_RUNQ_FLG_BASE2 + 5)) + (((Uint32) 1) << (ERTS_RUNQ_FLG_BASE2 + 4)) #define ERTS_RUNQ_FLGS_MIGRATION_QMASKS \ (ERTS_RUNQ_FLGS_EMIGRATE_QMASK \ @@ -272,11 +270,6 @@ typedef enum { typedef struct ErtsSchedulerSleepInfo_ ErtsSchedulerSleepInfo; -typedef struct { - erts_smp_spinlock_t lock; - ErtsSchedulerSleepInfo *list; -} ErtsSchedulerSleepList; - struct ErtsSchedulerSleepInfo_ { #ifdef ERTS_SMP ErtsSchedulerSleepInfo *next; @@ -339,10 +332,6 @@ struct ErtsRunQueue_ { erts_smp_mtx_t mtx; erts_smp_cnd_t cnd; -#ifdef ERTS_SMP - ErtsSchedulerSleepList sleepers; -#endif - ErtsSchedulerData *scheduler; int waiting; /* < 0 in sys schedule; > 0 on cnd variable */ int woken; @@ -388,7 +377,6 @@ typedef union { } ErtsAlignedRunQueue; extern ErtsAlignedRunQueue *erts_aligned_run_queues; -extern ErtsRunQueue *erts_common_run_queue; #define ERTS_PROC_REDUCTIONS_EXECUTED(RQ, PRIO, REDS, AREDS) \ do { \ @@ -469,11 +457,6 @@ struct ErtsSchedulerData_ { ErtsSchedAllocData alloc_data; -#ifdef ERTS_SMP - /* NOTE: These fields are modified under held mutexes by other threads */ - erts_smp_atomic32_t chk_cpu_bind; /* Only used when common run queue */ -#endif - #ifdef ERTS_DO_VERIFY_UNUSED_TEMP_ALLOC erts_alloc_verify_func_t verify_unused_temp_alloc; Allctr_t *verify_unused_temp_alloc_data; @@ -1079,7 +1062,7 @@ extern struct erts_system_profile_flags_t erts_system_profile_flags; void erts_pre_init_process(void); void erts_late_init_process(void); void erts_early_init_scheduling(int); -void erts_init_scheduling(int, int, int); +void erts_init_scheduling(int, int); ErtsProcList *erts_proclist_create(Process *); void erts_proclist_destroy(ErtsProcList *); @@ -1464,8 +1447,7 @@ erts_get_runq_proc(Process *p) ASSERT(p->run_queue); return p->run_queue; #else - ASSERT(erts_common_run_queue); - return erts_common_run_queue; + return ERTS_RUNQ_IX(0); #endif } @@ -1478,8 +1460,7 @@ erts_get_runq_current(ErtsSchedulerData *esdp) esdp = erts_get_scheduler_data(); return esdp->run_queue; #else - ASSERT(erts_common_run_queue); - return erts_common_run_queue; + return ERTS_RUNQ_IX(0); #endif } diff --git a/erts/emulator/beam/erl_process_lock.c b/erts/emulator/beam/erl_process_lock.c index b4d20480c5..a5a753b798 100644 --- a/erts/emulator/beam/erl_process_lock.c +++ b/erts/emulator/beam/erl_process_lock.c @@ -123,10 +123,10 @@ erts_init_proc_lock(int cpus) erts_smp_spinlock_init(&qs_lock, "proc_lck_qs_alloc"); for (i = 0; i < ERTS_NO_OF_PIX_LOCKS; i++) { #ifdef ERTS_ENABLE_LOCK_COUNT - erts_smp_spinlock_init_x(&erts_pix_locks[i].u.spnlck, - "pix_lock", make_small(i)); + erts_mtx_init_x(&erts_pix_locks[i].u.mtx, + "pix_lock", make_small(i)); #else - erts_smp_spinlock_init(&erts_pix_locks[i].u.spnlck, "pix_lock"); + erts_mtx_init(&erts_pix_locks[i].u.mtx, "pix_lock"); #endif } queue_free_list = NULL; diff --git a/erts/emulator/beam/erl_process_lock.h b/erts/emulator/beam/erl_process_lock.h index 97f250138e..97e554914e 100644 --- a/erts/emulator/beam/erl_process_lock.h +++ b/erts/emulator/beam/erl_process_lock.h @@ -255,8 +255,8 @@ void erts_proc_lc_unrequire_lock(Process *p, ErtsProcLocks locks); typedef struct { union { - erts_smp_spinlock_t spnlck; - char buf[64]; /* Try to get locks in different cache lines */ + erts_mtx_t mtx; + char buf[ERTS_ALC_CACHE_LINE_ALIGN_SIZE(sizeof(erts_mtx_t))]; } u; } erts_pix_lock_t; @@ -380,18 +380,18 @@ ERTS_GLB_INLINE void erts_proc_lock_op_debug(Process *, ErtsProcLocks, int); ERTS_GLB_INLINE void erts_pix_lock(erts_pix_lock_t *pixlck) { ERTS_LC_ASSERT(pixlck); - erts_smp_spin_lock(&pixlck->u.spnlck); + erts_mtx_lock(&pixlck->u.mtx); } ERTS_GLB_INLINE void erts_pix_unlock(erts_pix_lock_t *pixlck) { ERTS_LC_ASSERT(pixlck); - erts_smp_spin_unlock(&pixlck->u.spnlck); + erts_mtx_unlock(&pixlck->u.mtx); } ERTS_GLB_INLINE int erts_lc_pix_lock_is_locked(erts_pix_lock_t *pixlck) { - return erts_smp_lc_spinlock_is_locked(&pixlck->u.spnlck); + return erts_lc_mtx_is_locked(&pixlck->u.mtx); } /* diff --git a/erts/emulator/beam/erl_term.h b/erts/emulator/beam/erl_term.h index bc20b2d798..c270d13365 100644 --- a/erts/emulator/beam/erl_term.h +++ b/erts/emulator/beam/erl_term.h @@ -253,15 +253,15 @@ _ET_DECLARE_CHECKED(Eterm*,list_val,Wterm) #define SMALL_BITS (28) #define SMALL_DIGITS (8) #endif -#define MAX_SMALL ((1L << (SMALL_BITS-1))-1) -#define MIN_SMALL (-(1L << (SMALL_BITS-1))) +#define MAX_SMALL ((SWORD_CONSTANT(1) << (SMALL_BITS-1))-1) +#define MIN_SMALL (-(SWORD_CONSTANT(1) << (SMALL_BITS-1))) #define make_small(x) (((Uint)(x) << _TAG_IMMED1_SIZE) + _TAG_IMMED1_SMALL) #define is_small(x) (((x) & _TAG_IMMED1_MASK) == _TAG_IMMED1_SMALL) #define is_not_small(x) (!is_small((x))) #define is_byte(x) (((x) & ((~(Uint)0 << (_TAG_IMMED1_SIZE+8)) + _TAG_IMMED1_MASK)) == _TAG_IMMED1_SMALL) #define is_valid_bit_size(x) (((Sint)(x)) >= 0 && ((x) & 0x7F) == _TAG_IMMED1_SMALL) #define is_not_valid_bit_size(x) (!is_valid_bit_size((x))) -#define MY_IS_SSMALL(x) (((Uint) (((x) >> (SMALL_BITS-1)) + 1)) < 2) +#define MY_IS_SSMALL(x) (((Uint) ((((x)) >> (SMALL_BITS-1)) + 1)) < 2) #define _unchecked_unsigned_val(x) ((x) >> _TAG_IMMED1_SIZE) _ET_DECLARE_CHECKED(Uint,unsigned_val,Eterm) #define unsigned_val(x) _ET_APPLY(unsigned_val,(x)) diff --git a/erts/emulator/beam/erl_time.h b/erts/emulator/beam/erl_time.h index 7a09d30ff6..6c6e193818 100644 --- a/erts/emulator/beam/erl_time.h +++ b/erts/emulator/beam/erl_time.h @@ -20,7 +20,11 @@ #ifndef ERL_TIME_H__ #define ERL_TIME_H__ -extern erts_smp_atomic_t do_time; /* set at clock interrupt */ +#define ERTS_SHORT_TIME_T_MAX ERTS_AINT32_T_MAX +#define ERTS_SHORT_TIME_T_MIN ERTS_AINT32_T_MIN +typedef erts_aint32_t erts_short_time_t; + +extern erts_smp_atomic32_t do_time; /* set at clock interrupt */ extern SysTimeval erts_first_emu_time; /* @@ -71,22 +75,32 @@ void erts_cancel_smp_ptimer(ErtsSmpPTimer *ptimer); void erts_init_time(void); void erts_set_timer(ErlTimer*, ErlTimeoutProc, ErlCancelProc, void*, Uint); void erts_cancel_timer(ErlTimer*); -void erts_bump_timer(erts_aint_t); +void erts_bump_timer(erts_short_time_t); Uint erts_timer_wheel_memory_size(void); Uint erts_time_left(ErlTimer *); -erts_aint_t erts_next_time(void); +erts_short_time_t erts_next_time(void); #ifdef DEBUG void erts_p_slpq(void); #endif -ERTS_GLB_INLINE erts_aint_t erts_do_time_read_and_reset(void); -ERTS_GLB_INLINE void erts_do_time_add(long); +ERTS_GLB_INLINE erts_short_time_t erts_do_time_read_and_reset(void); +ERTS_GLB_INLINE void erts_do_time_add(erts_short_time_t); #if ERTS_GLB_INLINE_INCL_FUNC_DEF -ERTS_GLB_INLINE erts_aint_t erts_do_time_read_and_reset(void) { return erts_smp_atomic_xchg_acqb(&do_time, 0L); } -ERTS_GLB_INLINE void erts_do_time_add(long elapsed) { erts_smp_atomic_add_relb(&do_time, elapsed); } +ERTS_GLB_INLINE erts_short_time_t erts_do_time_read_and_reset(void) +{ + erts_short_time_t time = erts_smp_atomic32_xchg_acqb(&do_time, 0); + if (time < 0) + erl_exit(ERTS_ABORT_EXIT, "Internal time management error\n"); + return time; +} + +ERTS_GLB_INLINE void erts_do_time_add(erts_short_time_t elapsed) +{ + erts_smp_atomic32_add_relb(&do_time, elapsed); +} #endif /* #if ERTS_GLB_INLINE_INCL_FUNC_DEF */ @@ -105,7 +119,7 @@ void erts_get_now_cpu(Uint* megasec, Uint* sec, Uint* microsec); #endif void erts_get_timeval(SysTimeval *tv); -long erts_get_time(void); +erts_time_t erts_get_time(void); void erts_get_emu_time(SysTimeval *); ERTS_GLB_INLINE int erts_cmp_timeval(SysTimeval *t1p, SysTimeval *t2p); diff --git a/erts/emulator/beam/erl_time_sup.c b/erts/emulator/beam/erl_time_sup.c index ca4b54188e..b319288f7d 100644 --- a/erts/emulator/beam/erl_time_sup.c +++ b/erts/emulator/beam/erl_time_sup.c @@ -371,7 +371,7 @@ static void init_erts_deliver_time(const SysTimeval *inittv) static void do_erts_deliver_time(const SysTimeval *current) { SysTimeval cur_time; - long elapsed; + erts_time_t elapsed; /* calculate and deliver appropriate number of ticks */ cur_time = *current; @@ -385,7 +385,10 @@ static void do_erts_deliver_time(const SysTimeval *current) this by simply pretend as if the time stood still. :) */ if (elapsed > 0) { - erts_do_time_add(elapsed); + + ASSERT(elapsed < ((erts_time_t) ERTS_SHORT_TIME_T_MAX)); + + erts_do_time_add((erts_short_time_t) elapsed); last_delivered = cur_time; } } @@ -421,11 +424,11 @@ erts_init_time_sup(void) /* info functions */ void -elapsed_time_both(unsigned long *ms_user, unsigned long *ms_sys, - unsigned long *ms_user_diff, unsigned long *ms_sys_diff) +elapsed_time_both(UWord *ms_user, UWord *ms_sys, + UWord *ms_user_diff, UWord *ms_sys_diff) { - unsigned long prev_total_user, prev_total_sys; - unsigned long total_user, total_sys; + UWord prev_total_user, prev_total_sys; + UWord total_user, total_sys; SysTimes now; sys_times(&now); @@ -456,9 +459,9 @@ elapsed_time_both(unsigned long *ms_user, unsigned long *ms_sys, /* wall clock routines */ void -wall_clock_elapsed_time_both(unsigned long *ms_total, unsigned long *ms_diff) +wall_clock_elapsed_time_both(UWord *ms_total, UWord *ms_diff) { - unsigned long prev_total; + UWord prev_total; SysTimeval tv; erts_smp_mtx_lock(&erts_timeofday_mtx); @@ -592,10 +595,10 @@ static const int mdays[14] = {0, 31, 28, 31, 30, 31, 30, * greater of equal to 1600 , and month [1-12] and day [1-31] * are within range. Otherwise it returns -1. */ -static int long gregday(int year, int month, int day) +static time_t gregday(int year, int month, int day) { - int long ndays = 0; - int gyear, pyear, m; + time_t ndays = 0; + time_t gyear, pyear, m; /* number of days in previous years */ gyear = year - 1600; @@ -798,13 +801,14 @@ void erts_deliver_time(void) { void erts_time_remaining(SysTimeval *rem_time) { - int ticks; + erts_time_t ticks; SysTimeval cur_time; - long elapsed; + erts_time_t elapsed; /* erts_next_time() returns no of ticks to next timeout or -1 if none */ - if ((ticks = erts_next_time()) == -1) { + ticks = (erts_time_t) erts_next_time(); + if (ticks == (erts_time_t) -1) { /* timer queue empty */ /* this will cause at most 100000000 ticks */ rem_time->tv_sec = 100000; @@ -839,7 +843,7 @@ void erts_get_timeval(SysTimeval *tv) erts_smp_mtx_unlock(&erts_timeofday_mtx); } -long +erts_time_t erts_get_time(void) { SysTimeval sys_tv; diff --git a/erts/emulator/beam/external.c b/erts/emulator/beam/external.c index 4b867f2b10..152dbcf085 100644 --- a/erts/emulator/beam/external.c +++ b/erts/emulator/beam/external.c @@ -46,7 +46,7 @@ #ifdef HIPE #include "hipe_mode_switch.h" #endif -#define in_area(ptr,start,nbytes) ((Uint)((char*)(ptr) - (char*)(start)) < (nbytes)) +#define in_area(ptr,start,nbytes) ((UWord)((char*)(ptr) - (char*)(start)) < (nbytes)) #define MAX_STRING_LEN 0xffff diff --git a/erts/emulator/beam/global.h b/erts/emulator/beam/global.h index b247576f1c..f98232246b 100644 --- a/erts/emulator/beam/global.h +++ b/erts/emulator/beam/global.h @@ -172,7 +172,7 @@ struct port { DistEntry *dist_entry; /* Dist entry used in DISTRIBUTION */ char *name; /* String used in the open */ erts_driver_t* drv_ptr; - long drv_data; + UWord drv_data; ErtsProcList *suspended; /* List of suspended processes. */ LineBuf *linebuf; /* Buffer to hold data not ready for process to get (line oriented I/O)*/ @@ -205,7 +205,7 @@ erts_port_runq(Port *prt) rq1 = rq2; } #else - return erts_common_run_queue; + return ERTS_RUNQ_IX(0); #endif } @@ -398,7 +398,7 @@ extern Eterm erts_ddll_monitor_driver(Process *p, typedef struct binary { ERTS_INTERNAL_BINARY_FIELDS - long orig_size; + SWord orig_size; char orig_bytes[1]; /* to be continued */ } Binary; @@ -407,7 +407,7 @@ typedef struct binary { typedef struct { ERTS_INTERNAL_BINARY_FIELDS - long orig_size; + SWord orig_size; void (*destructor)(Binary *); char magic_bin_data[1]; } ErtsMagicBinary; diff --git a/erts/emulator/beam/io.c b/erts/emulator/beam/io.c index 132dc78515..759621d3c2 100644 --- a/erts/emulator/beam/io.c +++ b/erts/emulator/beam/io.c @@ -445,7 +445,7 @@ setup_port(Port* prt, Eterm pid, erts_driver_t *driver, prt->control_flags = 0; prt->connected = pid; - prt->drv_data = (long) drv_data; + prt->drv_data = (SWord) drv_data; prt->bytes_in = 0; prt->bytes_out = 0; prt->dist_entry = NULL; @@ -644,11 +644,10 @@ erts_open_driver(erts_driver_t* driver, /* Pointer to driver. */ name, opts); erts_unblock_fpe(fpe_was_unmasked); port->caller = NIL; - erts_unblock_fpe(fpe_was_unmasked); if (IS_TRACED_FL(port, F_TRACE_SCHED_PORTS)) { trace_sched_ports_where(port, am_out, am_start); } - if (error_number_ptr && ((long) drv_data) == (long) -2) + if (error_number_ptr && ((SWord) drv_data) == (SWord) -2) *error_number_ptr = errno; #ifdef ERTS_SMP if (port->xports) @@ -657,10 +656,10 @@ erts_open_driver(erts_driver_t* driver, /* Pointer to driver. */ #endif } - if (((long)drv_data) == -1 || - ((long)drv_data) == -2 || - ((long)drv_data) == -3) { - int res = (int) ((long) drv_data); + if (((SWord)drv_data) == -1 || + ((SWord)drv_data) == -2 || + ((SWord)drv_data) == -3) { + int res = (int) ((SWord) drv_data); if (res == -3 && error_number_ptr) { *error_number_ptr = BADARG; @@ -689,7 +688,7 @@ erts_open_driver(erts_driver_t* driver, /* Pointer to driver. */ erts_port_release(port); return res; } - port->drv_data = (long) drv_data; + port->drv_data = (SWord) drv_data; return port_ix; } @@ -3083,7 +3082,7 @@ driver_deliver_term(ErlDrvPort port, Binary* bp = erts_bin_nrml_alloc(size); ASSERT(bufp); bp->flags = 0; - bp->orig_size = (long) size; + bp->orig_size = (SWord) size; erts_refc_init(&bp->refc, 1); sys_memcpy((void *) bp->orig_bytes, (void *) bufp, size); pbp = (ProcBin *) hp; @@ -3449,7 +3448,7 @@ driver_alloc_binary(int size) return NULL; /* The driver write must take action */ bin->flags = BIN_FLAG_DRV; erts_refc_init(&bin->refc, 1); - bin->orig_size = (long) size; + bin->orig_size = (SWord) size; return Binary2ErlDrvBinary(bin); } @@ -4076,7 +4075,7 @@ drv_cancel_timer(Port *prt) erts_port_task_abort(prt->id, &prt->timeout_task); } -int driver_set_timer(ErlDrvPort ix, UWord t) +int driver_set_timer(ErlDrvPort ix, unsigned long t) { Port* prt = erts_drvport2port(ix); diff --git a/erts/emulator/beam/sys.h b/erts/emulator/beam/sys.h index 94c36c8c59..efc6dd2c6b 100644 --- a/erts/emulator/beam/sys.h +++ b/erts/emulator/beam/sys.h @@ -221,7 +221,8 @@ int real_printf(const char *fmt, ...); */ #if !((SIZEOF_VOID_P >= 4) && (SIZEOF_VOID_P == SIZEOF_SIZE_T) \ - && ((SIZEOF_VOID_P == SIZEOF_INT) || (SIZEOF_VOID_P == SIZEOF_LONG))) + && ((SIZEOF_VOID_P == SIZEOF_INT) || (SIZEOF_VOID_P == SIZEOF_LONG) || \ + (SIZEOF_VOID_P == SIZEOF_LONG_LONG))) #error Cannot handle this combination of int/long/void*/size_t sizes #endif @@ -262,9 +263,18 @@ typedef int Sint; #if SIZEOF_VOID_P == SIZEOF_LONG typedef unsigned long UWord; typedef long SWord; +#define SWORD_CONSTANT(Const) Const##L +#define UWORD_CONSTANT(Const) Const##UL #elif SIZEOF_VOID_P == SIZEOF_INT typedef unsigned int UWord; typedef int SWord; +#define SWORD_CONSTANT(Const) Const +#define UWORD_CONSTANT(Const) Const##U +#elif SIZEOF_VOID_P == SIZEOF_LONG_LONG +typedef unsigned long long UWord; +typedef long long SWord; +#define SWORD_CONSTANT(Const) Const##LL +#define UWORD_CONSTANT(Const) Const##ULL #else #error Found no appropriate type to use for 'Eterm', 'Uint' and 'Sint' #endif @@ -275,12 +285,23 @@ typedef int SWord; typedef unsigned long Eterm; typedef unsigned long Uint; typedef long Sint; +#define SWORD_CONSTANT(Const) Const##L +#define UWORD_CONSTANT(Const) Const##UL #define ERTS_SIZEOF_ETERM SIZEOF_LONG #elif SIZEOF_VOID_P == SIZEOF_INT typedef unsigned int Eterm; typedef unsigned int Uint; typedef int Sint; +#define SWORD_CONSTANT(Const) Const +#define UWORD_CONSTANT(Const) Const##U #define ERTS_SIZEOF_ETERM SIZEOF_INT +#elif SIZEOF_VOID_P == SIZEOF_LONG_LONG +typedef unsigned long long Eterm; +typedef unsigned long long Uint; +typedef long long Sint; +#define SWORD_CONSTANT(Const) Const##LL +#define UWORD_CONSTANT(Const) Const##ULL +#define ERTS_SIZEOF_ETERM SIZEOF_LONG_LONG #else #error Found no appropriate type to use for 'Eterm', 'Uint' and 'Sint' #endif @@ -615,10 +636,11 @@ extern char *erts_sys_ddll_error(int code); /* * System interfaces for startup. */ +#include "erl_time.h" void erts_sys_schedule_interrupt(int set); #ifdef ERTS_SMP -void erts_sys_schedule_interrupt_timed(int set, long msec); +void erts_sys_schedule_interrupt_timed(int set, erts_short_time_t msec); void erts_sys_main_thread(void); #endif @@ -635,10 +657,10 @@ Preload* sys_preloaded(void); unsigned char* sys_preload_begin(Preload*); void sys_preload_end(Preload*); int sys_get_key(int); -void elapsed_time_both(unsigned long *ms_user, unsigned long *ms_sys, - unsigned long *ms_user_diff, unsigned long *ms_sys_diff); -void wall_clock_elapsed_time_both(unsigned long *ms_total, - unsigned long *ms_diff); +void elapsed_time_both(UWord *ms_user, UWord *ms_sys, + UWord *ms_user_diff, UWord *ms_sys_diff); +void wall_clock_elapsed_time_both(UWord *ms_total, + UWord *ms_diff); void get_time(int *hour, int *minute, int *second); void get_date(int *year, int *month, int *day); void get_localtime(int *year, int *month, int *day, @@ -968,6 +990,19 @@ void erl_bin_write(unsigned char *, int, int); #endif +#ifdef __WIN32__ +#ifdef ARCH_64 +#define ERTS_ALLOC_ALIGN_BYTES 16 +#define ERTS_SMALL_ABS(Small) _abs64(Small) +#else +#define ERTS_ALLOC_ALIGN_BYTES 8 +#define ERTS_SMALL_ABS(Small) labs(Small) +#endif +#else +#define ERTS_ALLOC_ALIGN_BYTES 8 +#define ERTS_SMALL_ABS(Small) labs(Small) +#endif + #ifdef __WIN32__ diff --git a/erts/emulator/beam/time.c b/erts/emulator/beam/time.c index db9a24e0a3..932d157cd8 100644 --- a/erts/emulator/beam/time.c +++ b/erts/emulator/beam/time.c @@ -107,20 +107,31 @@ static ErlTimer *tiw_min_ptr; /* Actual interval time chosen by sys_init_time() */ static int itime; /* Constant after init */ -erts_smp_atomic_t do_time; /* set at clock interrupt */ -static ERTS_INLINE erts_aint_t do_time_read(void) { return erts_smp_atomic_read_acqb(&do_time); } -static ERTS_INLINE erts_aint_t do_time_update(void) { return do_time_read(); } -static ERTS_INLINE void do_time_init(void) { erts_smp_atomic_init_nob(&do_time, 0L); } +erts_smp_atomic32_t do_time; /* set at clock interrupt */ +static ERTS_INLINE erts_short_time_t do_time_read(void) +{ + return erts_smp_atomic32_read_acqb(&do_time); +} + +static ERTS_INLINE erts_short_time_t do_time_update(void) +{ + return do_time_read(); +} + +static ERTS_INLINE void do_time_init(void) +{ + erts_smp_atomic32_init_nob(&do_time, 0); +} /* get the time (in units of itime) to the next timeout, or -1 if there are no timeouts */ -static erts_aint_t next_time_internal(void) /* PRE: tiw_lock taken by caller */ +static erts_short_time_t next_time_internal(void) /* PRE: tiw_lock taken by caller */ { int i, tm, nto; - unsigned int min; + Uint32 min; ErlTimer* p; - erts_aint_t dt; + erts_short_time_t dt; if (tiw_nto == 0) return -1; /* no timeouts in wheel */ @@ -133,7 +144,7 @@ static erts_aint_t next_time_internal(void) /* PRE: tiw_lock taken by caller */ /* start going through wheel to find next timeout */ tm = nto = 0; - min = (unsigned int) -1; /* max unsigned int */ + min = (Uint32) -1; /* max Uint32 */ i = tiw_pos; do { p = tiw[i]; @@ -162,7 +173,11 @@ static erts_aint_t next_time_internal(void) /* PRE: tiw_lock taken by caller */ i = (i + 1) % TIW_SIZE; } while (i != tiw_pos); dt = do_time_read(); - return ((min >= dt) ? (min - dt) : 0); + if (min <= (Uint32) dt) + return 0; + if ((min - (Uint32) dt) > (Uint32) ERTS_SHORT_TIME_T_MAX) + return ERTS_SHORT_TIME_T_MAX; + return (erts_short_time_t) (min - (Uint32) dt); } static void remove_timer(ErlTimer *p) { @@ -191,9 +206,9 @@ static void remove_timer(ErlTimer *p) { } /* Private export to erl_time_sup.c */ -erts_aint_t erts_next_time(void) +erts_short_time_t erts_next_time(void) { - erts_aint_t ret; + erts_short_time_t ret; erts_smp_mtx_lock(&tiw_lock); (void)do_time_update(); @@ -202,7 +217,7 @@ erts_aint_t erts_next_time(void) return ret; } -static ERTS_INLINE void bump_timer_internal(erts_aint_t dt) /* PRE: tiw_lock is write-locked */ +static ERTS_INLINE void bump_timer_internal(erts_short_time_t dt) /* PRE: tiw_lock is write-locked */ { Uint keep_pos; Uint count; @@ -273,7 +288,7 @@ static ERTS_INLINE void bump_timer_internal(erts_aint_t dt) /* PRE: tiw_lock is } } -void erts_bump_timer(erts_aint_t dt) /* dt is value from do_time */ +void erts_bump_timer(erts_short_time_t dt) /* dt is value from do_time */ { erts_smp_mtx_lock(&tiw_lock); bump_timer_internal(dt); @@ -378,8 +393,8 @@ erts_set_timer(ErlTimer* p, ErlTimeoutProc timeout, ErlCancelProc cancel, insert_timer(p, t); erts_smp_mtx_unlock(&tiw_lock); #if defined(ERTS_SMP) - if (t <= (Uint) LONG_MAX) - erts_sys_schedule_interrupt_timed(1, (long) t); + if (t <= (Uint) ERTS_SHORT_TIME_T_MAX) + erts_sys_schedule_interrupt_timed(1, (erts_short_time_t) t); #endif } @@ -419,7 +434,7 @@ Uint erts_time_left(ErlTimer *p) { Uint left; - erts_aint_t dt; + erts_short_time_t dt; erts_smp_mtx_lock(&tiw_lock); diff --git a/erts/emulator/beam/utils.c b/erts/emulator/beam/utils.c index e4ad7dcb24..df03f5e42c 100644 --- a/erts/emulator/beam/utils.c +++ b/erts/emulator/beam/utils.c @@ -45,6 +45,7 @@ #include "erl_thr_progress.h" #include "erl_thr_queue.h" #include "erl_sched_spec_pre_alloc.h" +#include "beam_bp.h" #undef M_TRIM_THRESHOLD #undef M_TOP_PAD @@ -2647,7 +2648,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 diff --git a/erts/emulator/drivers/common/efile_drv.c b/erts/emulator/drivers/common/efile_drv.c index 901d98c09d..5c52b99348 100644 --- a/erts/emulator/drivers/common/efile_drv.c +++ b/erts/emulator/drivers/common/efile_drv.c @@ -55,6 +55,7 @@ #define FILE_READ_LINE 29 #define FILE_FDATASYNC 30 #define FILE_FADVISE 31 +#define FILE_SENDFILE 32 /* Return codes */ @@ -98,7 +99,13 @@ # include "config.h" #endif #include <stdlib.h> + +// Need (NON)BLOCKING macros for sendfile +#ifndef WANT_NONBLOCKING +#define WANT_NONBLOCKING +#endif #include "sys.h" + #include "erl_driver.h" #include "erl_efile.h" #include "erl_threads.h" @@ -225,9 +232,16 @@ static void file_outputv(ErlDrvData, ErlIOVec*); static void file_async_ready(ErlDrvData, ErlDrvThreadData); static void file_flush(ErlDrvData); +#ifdef HAVE_SENDFILE +static void file_ready_output(ErlDrvData data, ErlDrvEvent event); +static void file_stop_select(ErlDrvEvent event, void* _); +#endif /* HAVE_SENDFILE */ enum e_timer {timer_idle, timer_again, timer_write}; +#ifdef HAVE_SENDFILE +enum e_sendfile {sending, not_sending}; +#endif /* HAVE_SENDFILE */ struct t_data; @@ -242,6 +256,9 @@ typedef struct { struct t_data *cq_head; /* Queue of incoming commands */ struct t_data *cq_tail; /* -""- */ enum e_timer timer_state; +#ifdef HAVE_SENDFILE + enum e_sendfile sendfile_state; +#endif /* HAVE_SENDFILE */ size_t read_bufsize; ErlDrvBinary *read_binp; size_t read_offset; @@ -264,7 +281,11 @@ struct erl_drv_entry efile_driver_entry = { file_stop, file_output, NULL, +#ifdef HAVE_SENDFILE + file_ready_output, +#else NULL, +#endif /* HAVE_SENDFILE */ "efile", NULL, NULL, @@ -279,7 +300,13 @@ struct erl_drv_entry efile_driver_entry = { ERL_DRV_EXTENDED_MAJOR_VERSION, ERL_DRV_EXTENDED_MINOR_VERSION, ERL_DRV_FLAG_USE_PORT_LOCKING, + NULL, + NULL, +#ifdef HAVE_SENDFILE + file_stop_select +#else NULL +#endif /* HAVE_SENDFILE */ }; @@ -398,6 +425,14 @@ struct t_data Sint64 length; int advise; } fadvise; +#ifdef HAVE_SENDFILE + struct { + int out_fd; + off_t offset; + Uint64 nbytes; + Uint64 written; + } sendfile; +#endif /* HAVE_SENDFILE */ } c; char b[1]; }; @@ -485,7 +520,6 @@ static void *ef_safe_realloc(void *op, Uint s) : 0) - #if 0 static void ev_clear(ErlIOVec *ev) { @@ -613,7 +647,6 @@ static struct t_data *cq_deq(file_descriptor *desc) { } - /********************************************************************* * Driver entry point -> init */ @@ -628,6 +661,7 @@ file_init(void) ? atoi(buf) : 0); driver_system_info(&sys_info, sizeof(ErlDrvSysInfo)); + return 0; } @@ -655,6 +689,9 @@ file_start(ErlDrvPort port, char* command) desc->cq_head = NULL; desc->cq_tail = NULL; desc->timer_state = timer_idle; +#ifdef HAVE_SENDFILE + desc->sendfile_state = not_sending; +#endif desc->read_bufsize = 0; desc->read_binp = NULL; desc->read_offset = 0; @@ -893,8 +930,6 @@ static int reply_eof(file_descriptor *desc) { driver_output2(desc->port, &c, 1, NULL, 0); return 0; } - - static void invoke_name(void *data, int (*f)(Efile_error *, char *)) { @@ -1694,6 +1729,66 @@ static void invoke_fadvise(void *data) d->result_ok = efile_fadvise(&d->errInfo, fd, offset, length, advise); } +#ifdef HAVE_SENDFILE +static void invoke_sendfile(void *data) +{ + struct t_data *d = (struct t_data *)data; + int fd = d->fd; + int out_fd = (int)d->c.sendfile.out_fd; + Uint64 nbytes = d->c.sendfile.nbytes; + int result = 0; + d->again = 0; + + result = efile_sendfile(&d->errInfo, fd, out_fd, &d->c.sendfile.offset, &nbytes, NULL); + + d->c.sendfile.written += nbytes; + + if (result == 1) { + if (sys_info.async_threads != 0) { + d->result_ok = 0; + } else if (d->c.sendfile.nbytes == 0 && nbytes != 0) { + d->result_ok = 1; + } else if ((d->c.sendfile.nbytes - nbytes) != 0) { + d->result_ok = 1; + d->c.sendfile.nbytes -= nbytes; + } else { + d->result_ok = 0; + } + } else if (result == 0 && (d->errInfo.posix_errno == EAGAIN + || d->errInfo.posix_errno == EINTR)) { + d->result_ok = 1; + } else { + d->result_ok = -1; + } +} + +static void free_sendfile(void *data) { + EF_FREE(data); +} + +static void file_ready_output(ErlDrvData data, ErlDrvEvent event) +{ + file_descriptor* fd = (file_descriptor*) data; + + switch (fd->d->command) { + case FILE_SENDFILE: + driver_select(fd->port, event, + (int)ERL_DRV_WRITE,(int) 0); + invoke_sendfile((void *)fd->d); + file_async_ready(data, (ErlDrvThreadData)fd->d); + break; + default: + break; + } +} + +static void file_stop_select(ErlDrvEvent event, void* _) +{ + +} +#endif /* HAVE_SENDFILE */ + + static void free_readdir(void *data) { struct t_data *d = (struct t_data *) data; @@ -1755,6 +1850,10 @@ static void cq_execute(file_descriptor *desc) { register void *void_ptr; /* Soft cast variable */ if (desc->timer_state == timer_again) return; +#ifdef HAVE_SENDFILE + if (desc->sendfile_state == sending) + return; +#endif if (! (d = cq_deq(desc))) return; TRACE_F(("x%i", (int) d->command)); @@ -2105,6 +2204,37 @@ file_async_ready(ErlDrvData e, ErlDrvThreadData data) } free_preadv(data); break; +#ifdef HAVE_SENDFILE + case FILE_SENDFILE: + if (d->result_ok == -1) { + desc->sendfile_state = not_sending; + reply_error(desc, &d->errInfo); + if (sys_info.async_threads != 0) { + SET_NONBLOCKING(d->c.sendfile.out_fd); + free_sendfile(data); + } else { + driver_select(desc->port, (ErlDrvEvent)(long)d->c.sendfile.out_fd, + ERL_DRV_USE, 0); + free_sendfile(data); + } + } else if (d->result_ok == 0) { + desc->sendfile_state = not_sending; + reply_Sint64(desc, d->c.sendfile.written); + if (sys_info.async_threads != 0) { + SET_NONBLOCKING(d->c.sendfile.out_fd); + free_sendfile(data); + } else { + driver_select(desc->port, (ErlDrvEvent)(long)d->c.sendfile.out_fd, ERL_DRV_USE, 0); + free_sendfile(data); + } + } else if (d->result_ok == 1) { // If we are using select to send the rest of the data + desc->sendfile_state = sending; + desc->d = d; + driver_select(desc->port, (ErlDrvEvent)(long)d->c.sendfile.out_fd, + ERL_DRV_USE|ERL_DRV_WRITE, 1); + } + break; +#endif default: abort(); } @@ -3245,9 +3375,69 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { goto done; } /* case FILE_OPT_DELAYED_WRITE: */ } ASSERT(0); goto done; /* case FILE_SETOPT: */ - + + case FILE_SENDFILE: { + +#ifdef HAVE_SENDFILE + struct t_data *d; + Uint32 out_fd, offsetH, offsetL, hd_len, tl_len; + Uint64 nbytes; + char flags; + + if (ev->size < 1 + 7 * sizeof(Uint32) + sizeof(char) + || !EV_GET_UINT32(ev, &out_fd, &p, &q) + || !EV_GET_CHAR(ev, &flags, &p, &q) + || !EV_GET_UINT32(ev, &offsetH, &p, &q) + || !EV_GET_UINT32(ev, &offsetL, &p, &q) + || !EV_GET_UINT64(ev, &nbytes, &p, &q) + || !EV_GET_UINT32(ev, &hd_len, &p, &q) + || !EV_GET_UINT32(ev, &tl_len, &p, &q)) { + /* Buffer has wrong length to contain all the needed values */ + reply_posix_error(desc, EINVAL); + goto done; + } + + if (hd_len != 0 || tl_len != 0 || flags != 0) { + // We do not allow header, trailers and/or flags right now + reply_posix_error(desc, EINVAL); + goto done; + } + + d = EF_SAFE_ALLOC(sizeof(struct t_data)); + d->fd = desc->fd; + d->command = command; + d->invoke = invoke_sendfile; + d->free = NULL; + d->level = 2; + + d->c.sendfile.out_fd = (int) out_fd; + d->c.sendfile.written = 0; + + #if SIZEOF_OFF_T == 4 + if (offsetH != 0) { + reply_posix_error(desc, EINVAL); + goto done; + } + d->c.sendfile.offset = (off_t) offsetL; + #else + d->c.sendfile.offset = ((off_t) offsetH << 32) | offsetL; + #endif + + d->c.sendfile.nbytes = nbytes; + + if (sys_info.async_threads != 0) { + SET_BLOCKING(d->c.sendfile.out_fd); + } + + cq_enq(desc, d); +#else + reply_posix_error(desc, ENOTSUP); +#endif + goto done; + } /* case FILE_SENDFILE: */ + } /* switch(command) */ - + if (lseek_flush_read(desc, &err) < 0) { reply_posix_error(desc, err); goto done; diff --git a/erts/emulator/drivers/common/erl_efile.h b/erts/emulator/drivers/common/erl_efile.h index 3097ded3f1..349ab0e17b 100644 --- a/erts/emulator/drivers/common/erl_efile.h +++ b/erts/emulator/drivers/common/erl_efile.h @@ -118,6 +118,19 @@ typedef struct _Efile_info { */ } Efile_info; + +#ifdef HAVE_SENDFILE +/* + * Described the structure of header/trailers for sendfile + */ +struct t_sendfile_hdtl { + SysIOVec *headers; + int hdr_cnt; + SysIOVec *trailers; + int trl_cnt; +}; +#endif /* HAVE_SENDFILE */ + /* * Functions. */ @@ -162,3 +175,7 @@ int efile_symlink(Efile_error* errInfo, char* old, char* new); int efile_may_openfile(Efile_error* errInfo, char *name); int efile_fadvise(Efile_error* errInfo, int fd, Sint64 offset, Sint64 length, int advise); +#ifdef HAVE_SENDFILE +int efile_sendfile(Efile_error* errInfo, int in_fd, int out_fd, + off_t *offset, Uint64 *nbytes, struct t_sendfile_hdtl *hdtl); +#endif /* HAVE_SENDFILE */ diff --git a/erts/emulator/drivers/common/gzio.c b/erts/emulator/drivers/common/gzio.c index 741cb6ae20..a9303d55bc 100644 --- a/erts/emulator/drivers/common/gzio.c +++ b/erts/emulator/drivers/common/gzio.c @@ -27,7 +27,9 @@ #endif #ifdef __WIN32__ +#ifndef HAVE_CONFLICTING_FREAD_DECLARATION #define HAVE_CONFLICTING_FREAD_DECLARATION +#endif #define FILENAMES_16BIT 1 #endif diff --git a/erts/emulator/drivers/common/inet_drv.c b/erts/emulator/drivers/common/inet_drv.c index dcc2954b02..e0d869f328 100644 --- a/erts/emulator/drivers/common/inet_drv.c +++ b/erts/emulator/drivers/common/inet_drv.c @@ -110,6 +110,77 @@ #undef EWOULDBLOCK #undef ETIMEDOUT +#ifdef EINPROGRESS +#undef EINPROGRESS +#endif +#ifdef EALREADY +#undef EALREADY +#endif +#ifdef ENOTSOCK +#undef ENOTSOCK +#endif +#ifdef EDESTADDRREQ +#undef EDESTADDRREQ +#endif +#ifdef EMSGSIZE +#undef EMSGSIZE +#endif +#ifdef EPROTOTYPE +#undef EPROTOTYPE +#endif +#ifdef ENOPROTOOPT +#undef ENOPROTOOPT +#endif +#ifdef EPROTONOSUPPORT +#undef EPROTONOSUPPORT +#endif +#ifdef EOPNOTSUPP +#undef EOPNOTSUPP +#endif +#ifdef EAFNOSUPPORT +#undef EAFNOSUPPORT +#endif +#ifdef EADDRINUSE +#undef EADDRINUSE +#endif +#ifdef EADDRNOTAVAIL +#undef EADDRNOTAVAIL +#endif +#ifdef ENETDOWN +#undef ENETDOWN +#endif +#ifdef ENETUNREACH +#undef ENETUNREACH +#endif +#ifdef ENETRESET +#undef ENETRESET +#endif +#ifdef ECONNABORTED +#undef ECONNABORTED +#endif +#ifdef ECONNRESET +#undef ECONNRESET +#endif +#ifdef ENOBUFS +#undef ENOBUFS +#endif +#ifdef EISCONN +#undef EISCONN +#endif +#ifdef ENOTCONN +#undef ENOTCONN +#endif +#ifdef ECONNREFUSED +#undef ECONNREFUSED +#endif +#ifdef ELOOP +#undef ELOOP +#endif +#ifdef EHOSTUNREACH +#undef EHOSTUNREACH +#endif + + #define HAVE_MULTICAST_SUPPORT #define ERRNO_BLOCK WSAEWOULDBLOCK @@ -445,6 +516,7 @@ static int my_strncasecmp(const char *s1, const char *s2, size_t n) driver_select(port, e, mode | (on?ERL_DRV_USE:0), on) #define sock_select(d, flags, onoff) do { \ + ASSERT(!onoff || !(d)->is_ignored); \ (d)->event_mask = (onoff) ? \ ((d)->event_mask | (flags)) : \ ((d)->event_mask & ~(flags)); \ @@ -538,6 +610,8 @@ static int my_strncasecmp(const char *s1, const char *s2, size_t n) #define INET_REQ_GETIFADDRS 25 #define INET_REQ_ACCEPT 26 #define INET_REQ_LISTEN 27 +#define INET_REQ_IGNOREFD 28 + /* TCP requests */ /* #define TCP_REQ_ACCEPT 40 MOVED */ /* #define TCP_REQ_LISTEN 41 MERGED */ @@ -725,6 +799,11 @@ static int my_strncasecmp(const char *s1, const char *s2, size_t n) /* Max interface name */ #define INET_IFNAMSIZ 16 +/* INET Ignore states */ +#define INET_IGNORE_NONE 0 +#define INET_IGNORE_READ 1 +#define INET_IGNORE_WRITE 1 << 1 + /* Max length of Erlang Term Buffer (for outputting structured terms): */ #ifdef HAVE_SCTP #define PACKET_ERL_DRV_TERM_DATA_LEN 512 @@ -864,6 +943,9 @@ typedef struct { double send_avg; /* average packet size sent */ subs_list empty_out_q_subs; /* Empty out queue subscribers */ + int is_ignored; /* if a fd is ignored by from the inet_drv, + this should be set to true when the fd is used + outside of inet_drv. */ } inet_descriptor; @@ -4222,6 +4304,31 @@ static int inet_ctl_getiflist(inet_descriptor* desc, char** rbuf, int rsize) return sp - sbuf; } +#ifdef HAVE_LIBDLPI_H +#include <libdlpi.h> +static int hwaddr_libdlpi_lookup(const char *ifnm, + uchar_t *addr, size_t *alen) +{ + dlpi_handle_t handle; + dlpi_info_t linkinfo; + int ret = -1; + + if (dlpi_open(ifnm, &handle, 0) != DLPI_SUCCESS) { + return -1; + } + + if (dlpi_get_physaddr(handle, DL_CURR_PHYS_ADDR, + addr, alen) == DLPI_SUCCESS && + dlpi_info(handle, &linkinfo, 0) == DLPI_SUCCESS) + { + ret = 0; + } + + dlpi_close(handle); + return ret; +} +#endif + /* FIXME: temporary hack */ #ifndef IFHWADDRLEN #define IFHWADDRLEN 6 @@ -4257,7 +4364,24 @@ static int inet_ctl_ifget(inet_descriptor* desc, char* buf, int len, break; case INET_IFOPT_HWADDR: { -#ifdef SIOCGIFHWADDR +#ifdef HAVE_LIBDLPI_H + /* + ** OpenSolaris have SIGCGIFHWADDR, but no ifr_hwaddr member.. + ** The proper way to get the mac address would be to + ** use libdlpi... + */ + uchar_t addr[DLPI_PHYSADDR_MAX]; + size_t alen = sizeof(addr); + + if (hwaddr_libdlpi_lookup(ifreq.ifr_name, addr, &alen) == 0) { + buf_check(sptr, s_end, 1+2+alen); + *sptr++ = INET_IFOPT_HWADDR; + put_int16(alen, sptr); + sptr += 2; + sys_memcpy(sptr, addr, alen); + sptr += alen; + } +#elif defined(SIOCGIFHWADDR) && defined(HAVE_STRUCT_IFREQ_IFR_HWADDR) if (ioctl(desc->s, SIOCGIFHWADDR, (char *)&ifreq) < 0) break; buf_check(sptr, s_end, 1+2+IFHWADDRLEN); @@ -4266,7 +4390,7 @@ static int inet_ctl_ifget(inet_descriptor* desc, char* buf, int len, /* raw memcpy (fix include autoconf later) */ sys_memcpy(sptr, (char*)(&ifreq.ifr_hwaddr.sa_data), IFHWADDRLEN); sptr += IFHWADDRLEN; -#elif defined(SIOCGENADDR) +#elif defined(SIOCGENADDR) && defined(HAVE_STRUCT_IFREQ_IFR_ENADDR) if (ioctl(desc->s, SIOCGENADDR, (char *)&ifreq) < 0) break; buf_check(sptr, s_end, 1+2+sizeof(ifreq.ifr_enaddr)); @@ -7302,6 +7426,8 @@ static ErlDrvData inet_start(ErlDrvPort port, int size, int protocol) sys_memzero((char *)&desc->remote,sizeof(desc->remote)); + desc->is_ignored = 0; + return (ErlDrvData)desc; } @@ -7584,6 +7710,33 @@ static int inet_ctl(inet_descriptor* desc, int cmd, char* buf, int len, return ctl_reply(INET_REP_OK, tbuf, 2, rbuf, rsize); } + case INET_REQ_IGNOREFD: { + DEBUGF(("inet_ctl(%ld): IGNOREFD, IGNORED = %d\r\n", + (long)desc->port,(int)*buf)); + + /* + * FD can only be ignored for connected TCP connections for now, + * possible to add UDP and SCTP support if needed. + */ + if (!IS_CONNECTED(desc)) + return ctl_error(ENOTCONN, rbuf, rsize); + + if (!desc->stype == SOCK_STREAM) + return ctl_error(EINVAL, rbuf, rsize); + + if (*buf == 1 && !desc->is_ignored) { + desc->is_ignored = INET_IGNORE_READ; + sock_select(desc, (FD_READ|FD_WRITE|FD_CLOSE|ERL_DRV_USE_NO_CALLBACK), 0); + } else if (*buf == 0 && desc->is_ignored) { + int flags = (FD_READ|FD_CLOSE|((desc->is_ignored & INET_IGNORE_WRITE)?FD_WRITE:0)); + desc->is_ignored = INET_IGNORE_NONE; + sock_select(desc, flags, 1); + } else + return ctl_error(EINVAL, rbuf, rsize); + + return ctl_reply(INET_REP_OK, NULL, 0, rbuf, rsize); + } + #ifndef VXWORKS case INET_REQ_GETSERVBYNAME: { /* L1 Name-String L2 Proto-String */ @@ -7959,6 +8112,7 @@ static int tcp_inet_ctl(ErlDrvData e, unsigned int cmd, char* buf, int len, char** rbuf, int rsize) { tcp_descriptor* desc = (tcp_descriptor*)e; + switch(cmd) { case INET_REQ_OPEN: { /* open socket and return internal index */ int domain; @@ -8224,13 +8378,14 @@ static int tcp_inet_ctl(ErlDrvData e, unsigned int cmd, char* buf, int len, if (enq_async(INETP(desc), tbuf, TCP_REQ_RECV) < 0) return ctl_error(EALREADY, rbuf, rsize); - if (tcp_recv(desc, n) == 0) { + if (INETP(desc)->is_ignored || tcp_recv(desc, n) == 0) { if (timeout == 0) async_error_am(INETP(desc), am_timeout); else { if (timeout != INET_INFINITY) - driver_set_timer(desc->inet.port, timeout); - sock_select(INETP(desc),(FD_READ|FD_CLOSE),1); + driver_set_timer(desc->inet.port, timeout); + if (!INETP(desc)->is_ignored) + sock_select(INETP(desc),(FD_READ|FD_CLOSE),1); } } return ctl_reply(INET_REP_OK, tbuf, 2, rbuf, rsize); @@ -8970,6 +9125,7 @@ static int tcp_inet_input(tcp_descriptor* desc, HANDLE event) #ifdef DEBUG long port = (long) desc->inet.port; /* Used after driver_exit() */ #endif + ASSERT(!INETP(desc)->is_ignored); DEBUGF(("tcp_inet_input(%ld) {s=%d\r\n", port, desc->inet.s)); if (desc->inet.state == INET_STATE_ACCEPTING) { SOCKET s; @@ -9231,7 +9387,11 @@ static int tcp_sendv(tcp_descriptor* desc, ErlIOVec* ev) DEBUGF(("tcp_sendv(%ld): s=%d, about to send %d,%d bytes\r\n", (long)desc->inet.port, desc->inet.s, h_len, len)); - if (desc->tcp_add_flags & TCP_ADDF_DELAY_SEND) { + + if (INETP(desc)->is_ignored) { + INETP(desc)->is_ignored |= INET_IGNORE_WRITE; + n = 0; + } else if (desc->tcp_add_flags & TCP_ADDF_DELAY_SEND) { n = 0; } else if (IS_SOCKET_ERROR(sock_sendv(desc->inet.s, ev->iov, vsize, &n, 0))) { @@ -9259,7 +9419,8 @@ static int tcp_sendv(tcp_descriptor* desc, ErlIOVec* ev) DEBUGF(("tcp_sendv(%ld): s=%d, Send failed, queuing\r\n", (long)desc->inet.port, desc->inet.s)); driver_enqv(ix, ev, n); - sock_select(INETP(desc),(FD_WRITE|FD_CLOSE), 1); + if (!INETP(desc)->is_ignored) + sock_select(INETP(desc),(FD_WRITE|FD_CLOSE), 1); } return 0; } @@ -9324,7 +9485,10 @@ static int tcp_send(tcp_descriptor* desc, char* ptr, int len) DEBUGF(("tcp_send(%ld): s=%d, about to send %d,%d bytes\r\n", (long)desc->inet.port, desc->inet.s, h_len, len)); - if (desc->tcp_add_flags & TCP_ADDF_DELAY_SEND) { + if (INETP(desc)->is_ignored) { + INETP(desc)->is_ignored |= INET_IGNORE_WRITE; + n = 0; + } else if (desc->tcp_add_flags & TCP_ADDF_DELAY_SEND) { sock_send(desc->inet.s, buf, 0, 0); n = 0; } else if (IS_SOCKET_ERROR(sock_sendv(desc->inet.s,iov,2,&n,0))) { @@ -9355,7 +9519,8 @@ static int tcp_send(tcp_descriptor* desc, char* ptr, int len) n -= h_len; driver_enq(ix, ptr+n, len-n); } - sock_select(INETP(desc),(FD_WRITE|FD_CLOSE), 1); + if (!INETP(desc)->is_ignored) + sock_select(INETP(desc),(FD_WRITE|FD_CLOSE), 1); } return 0; } @@ -9379,6 +9544,7 @@ static int tcp_inet_output(tcp_descriptor* desc, HANDLE event) int ret = 0; ErlDrvPort ix = desc->inet.port; + ASSERT(!INETP(desc)->is_ignored); DEBUGF(("tcp_inet_output(%ld) {s=%d\r\n", (long)desc->inet.port, desc->inet.s)); if (desc->inet.state == INET_STATE_CONNECTING) { diff --git a/erts/emulator/drivers/unix/unix_efile.c b/erts/emulator/drivers/unix/unix_efile.c index 4b3934657c..72911641d3 100644 --- a/erts/emulator/drivers/unix/unix_efile.c +++ b/erts/emulator/drivers/unix/unix_efile.c @@ -33,6 +33,9 @@ #include <sys/types.h> #include <sys/uio.h> #endif +#if defined(HAVE_SENDFILE) && (defined(__linux__) || (defined(__sun) && defined(__SVR4))) +#include <sys/sendfile.h> +#endif #if defined(__APPLE__) && defined(__MACH__) && !defined(__DARWIN__) #define DARWIN 1 @@ -1464,3 +1467,77 @@ efile_fadvise(Efile_error* errInfo, int fd, Sint64 offset, return check_error(0, errInfo); #endif } + +#ifdef HAVE_SENDFILE +#define SENDFILE_CHUNK_SIZE ((1 << 30) -1) + +/* + * sendfile: The implementation of the sendfile system call varies + * a lot on different *nix platforms so to make the api similar in all + * we have to emulate some things in linux and play with variables on + * bsd/darwin. + * + * It could be possible to implement header/trailer in sendfile, though + * you would have to emulate it in linux and on BSD/Darwin some complex + * calculations have to be made when using a non blocking socket to figure + * out how much of the header/file/trailer was sent in each command. + */ + +int +efile_sendfile(Efile_error* errInfo, int in_fd, int out_fd, + off_t *offset, Uint64 *nbytes, struct t_sendfile_hdtl* hdtl) +{ + Uint64 written = 0; +#if defined(__linux__) || (defined(__sun) && defined(__SVR4)) + ssize_t retval; + do { + // check if *nbytes is 0 or greater than the largest size_t + if (*nbytes == 0 || *nbytes > SENDFILE_CHUNK_SIZE) + retval = sendfile(out_fd, in_fd, offset, SENDFILE_CHUNK_SIZE); + else + retval = sendfile(out_fd, in_fd, offset, *nbytes); + if (retval > 0) { + written += retval; + *nbytes -= retval; + } + } while (retval != -1 && retval == SENDFILE_CHUNK_SIZE); + *nbytes = written; + return check_error(retval == -1 ? -1 : 0, errInfo); +#elif defined(DARWIN) + int retval; + off_t len; + do { + // check if *nbytes is 0 or greater than the largest off_t + if(*nbytes > SENDFILE_CHUNK_SIZE) + len = SENDFILE_CHUNK_SIZE; + else + len = *nbytes; + retval = sendfile(in_fd, out_fd, *offset, &len, NULL, 0); + if (retval != -1 || errno == EAGAIN || errno == EINTR) { + *offset += len; + *nbytes -= len; + written += len; + } + } while (len == SENDFILE_CHUNK_SIZE); + *nbytes = written; + return check_error(retval, errInfo); +#elif defined(__FreeBSD__) || defined(__DragonFly__) + off_t len; + int retval; + do { + if (*nbytes > SENDFILE_CHUNK_SIZE) + retval = sendfile(in_fd, out_fd, *offset, SENDFILE_CHUNK_SIZE, + NULL, &len, 0); + else + retval = sendfile(in_fd, out_fd, *offset, *nbytes, NULL, &len, 0); + if (retval != -1 || errno == EAGAIN || errno == EINTR) { + *offset += len; + *nbytes -= len; + written += len; + } + } while(len == SENDFILE_CHUNK_SIZE); + *nbytes = written; + return check_error(retval, errInfo); +#endif +} +#endif /* HAVE_SENDFILE */ diff --git a/erts/emulator/drivers/win32/ttsl_drv.c b/erts/emulator/drivers/win32/ttsl_drv.c index fd88dafd34..e636761c67 100644 --- a/erts/emulator/drivers/win32/ttsl_drv.c +++ b/erts/emulator/drivers/win32/ttsl_drv.c @@ -21,6 +21,9 @@ * smart line for output. */ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif #include "sys.h" #include <ctype.h> #include <stdlib.h> diff --git a/erts/emulator/drivers/win32/win_con.c b/erts/emulator/drivers/win32/win_con.c index c788ad409d..6b45b92cbe 100644 --- a/erts/emulator/drivers/win32/win_con.c +++ b/erts/emulator/drivers/win32/win_con.c @@ -21,6 +21,9 @@ #define _UNICODE 1 #include <tchar.h> #include <stdio.h> +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif #include "sys.h" #include <windowsx.h> #include "resource.h" @@ -34,6 +37,23 @@ #define REALLOC(X,Y) realloc(X,Y) #define FREE(X) free(X) +#if SIZEOF_VOID_P == 8 +#define WIN64 1 +#ifndef GCL_HBRBACKGROUND +#define GCL_HBRBACKGROUND GCLP_HBRBACKGROUND +#endif +#define DIALOG_PROC_RET INT_PTR +#define CF_HOOK_RET INT_PTR +#define CC_HOOK_RET INT_PTR +#define OFN_HOOK_RET INT_PTR +#else +#define DIALOG_PROC_RET BOOL +#define CF_HOOK_RET UINT +#define CC_HOOK_RET UINT +#define OFN_HOOK_RET UINT +#endif + + #ifndef STATE_SYSTEM_INVISIBLE /* Mingw problem with oleacc.h and WIN32_LEAN_AND_MEAN */ #define STATE_SYSTEM_INVISIBLE 0x00008000 @@ -150,7 +170,7 @@ static TCHAR *erlang_window_title = TEXT("Erlang"); static unsigned __stdcall ConThreadInit(LPVOID param); static LRESULT CALLBACK ClientWndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam); static LRESULT CALLBACK FrameWndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam); -static BOOL CALLBACK AboutDlgProc(HWND hDlg, UINT iMsg, WPARAM wParam, LPARAM lParam); +static DIALOG_PROC_RET CALLBACK AboutDlgProc(HWND hDlg, UINT iMsg, WPARAM wParam, LPARAM lParam); static ScreenLine_t *ConNewLine(void); static void DeleteTopLine(void); static void ensure_line_below(void); @@ -1608,7 +1628,7 @@ OnEditSelAll(HWND hwnd) InvalidateRect(hwnd, NULL, TRUE); } -UINT APIENTRY CFHookProc(HWND hDlg,UINT iMsg,WPARAM wParam,LPARAM lParam) +CF_HOOK_RET APIENTRY CFHookProc(HWND hDlg,UINT iMsg,WPARAM wParam,LPARAM lParam) { /* Hook procedure for font dialog box */ HWND hOwner; @@ -1626,11 +1646,11 @@ UINT APIENTRY CFHookProc(HWND hDlg,UINT iMsg,WPARAM wParam,LPARAM lParam) OffsetRect(&rc, -rcDlg.right, -rcDlg.bottom); SetWindowPos(hDlg,HWND_TOP,rcOwner.left + (rc.right / 2), rcOwner.top + (rc.bottom / 2),0,0,SWP_NOSIZE); - return 1; + return (CF_HOOK_RET) 1; default: break; } - return 0; /* Let the default procedure process the message */ + return (CF_HOOK_RET) 0; /* Let the default procedure process the message */ } static BOOL @@ -1705,7 +1725,7 @@ ConSetFont(HWND hwnd) InvalidateRect(hwnd, NULL, TRUE); } -UINT APIENTRY +CC_HOOK_RET APIENTRY CCHookProc(HWND hDlg,UINT iMsg,WPARAM wParam,LPARAM lParam) { /* Hook procedure for choose color dialog box */ @@ -1724,11 +1744,11 @@ CCHookProc(HWND hDlg,UINT iMsg,WPARAM wParam,LPARAM lParam) OffsetRect(&rc, -rcDlg.right, -rcDlg.bottom); SetWindowPos(hDlg,HWND_TOP,rcOwner.left + (rc.right / 2), rcOwner.top + (rc.bottom / 2),0,0,SWP_NOSIZE); - return 1; + return (CC_HOOK_RET) 1; default: break; } - return 0; /* Let the default procedure process the message */ + return (CC_HOOK_RET) 0; /* Let the default procedure process the message */ } void ConChooseColor(HWND hwnd) @@ -1758,7 +1778,8 @@ void ConChooseColor(HWND hwnd) } } -UINT APIENTRY OFNHookProc(HWND hwndDlg,UINT iMsg,WPARAM wParam,LPARAM lParam) +OFN_HOOK_RET APIENTRY OFNHookProc(HWND hwndDlg,UINT iMsg, + WPARAM wParam,LPARAM lParam) { /* Hook procedure for open file dialog box */ HWND hOwner,hDlg; @@ -1777,11 +1798,11 @@ UINT APIENTRY OFNHookProc(HWND hwndDlg,UINT iMsg,WPARAM wParam,LPARAM lParam) OffsetRect(&rc, -rcDlg.right, -rcDlg.bottom); SetWindowPos(hDlg,HWND_TOP,rcOwner.left + (rc.right / 2), rcOwner.top + (rc.bottom / 2),0,0,SWP_NOSIZE); - return 1; + return (OFN_HOOK_RET) 1; default: break; } - return 0; /* the let default procedure process the message */ + return (OFN_HOOK_RET) 0; /* the let default procedure process the message */ } static void @@ -1933,7 +1954,7 @@ write_outbuf(TCHAR *data, int num_chars) return num_chars; } -BOOL CALLBACK AboutDlgProc(HWND hDlg, UINT iMsg, WPARAM wParam, LPARAM lParam) +DIALOG_PROC_RET CALLBACK AboutDlgProc(HWND hDlg, UINT iMsg, WPARAM wParam, LPARAM lParam) { HWND hOwner; RECT rc,rcOwner,rcDlg; @@ -1953,17 +1974,17 @@ BOOL CALLBACK AboutDlgProc(HWND hDlg, UINT iMsg, WPARAM wParam, LPARAM lParam) rcOwner.top + (rc.bottom / 2),0,0,SWP_NOSIZE); SetDlgItemText(hDlg, ID_VERSIONSTRING, TEXT("Erlang emulator version ") TEXT(ERLANG_VERSION)); - return TRUE; + return (DIALOG_PROC_RET) TRUE; case WM_COMMAND: switch (LOWORD(wParam)) { case IDOK: case IDCANCEL: EndDialog(hDlg,0); - return TRUE; + return (DIALOG_PROC_RET) TRUE; } break; } - return FALSE; + return (DIALOG_PROC_RET) FALSE; } static void @@ -2117,7 +2138,7 @@ AddToCmdHistory(void) } } -static TBBUTTON tbb[] = +/*static TBBUTTON tbb[] = { 0, 0, TBSTATE_ENABLED, TBSTYLE_SEP, 0, 0, 0, 0, 0, 0, TBSTATE_ENABLED, TBSTYLE_SEP, 0, 0, 0, 0, @@ -2149,6 +2170,39 @@ static TBBUTTON tbb[] = 2, IDMENU_FONT, TBSTATE_ENABLED, TBSTYLE_AUTOSIZE, 0, 0, 0, 0, 3, IDMENU_ABOUT, TBSTATE_ENABLED, TBSTYLE_AUTOSIZE, 0, 0, 0, 0, 0, 0, TBSTATE_ENABLED, TBSTYLE_SEP, 0, 0, 0, 0, + };*/ +static TBBUTTON tbb[] = +{ + {0, 0, TBSTATE_ENABLED, TBSTYLE_SEP}, + {0, 0, TBSTATE_ENABLED, TBSTYLE_SEP}, + {0, 0, TBSTATE_ENABLED, TBSTYLE_SEP}, + {0, 0, TBSTATE_ENABLED, TBSTYLE_SEP}, + {0, 0, TBSTATE_ENABLED, TBSTYLE_SEP}, + {0, 0, TBSTATE_ENABLED, TBSTYLE_SEP}, + {0, 0, TBSTATE_ENABLED, TBSTYLE_SEP}, + {0, 0, TBSTATE_ENABLED, TBSTYLE_SEP}, + {0, 0, TBSTATE_ENABLED, TBSTYLE_SEP}, + {0, 0, TBSTATE_ENABLED, TBSTYLE_SEP}, + {0, 0, TBSTATE_ENABLED, TBSTYLE_SEP}, + {0, 0, TBSTATE_ENABLED, TBSTYLE_SEP}, + {0, 0, TBSTATE_ENABLED, TBSTYLE_SEP}, + {0, 0, TBSTATE_ENABLED, TBSTYLE_SEP}, + {0, 0, TBSTATE_ENABLED, TBSTYLE_SEP}, + {0, 0, TBSTATE_ENABLED, TBSTYLE_SEP}, + {0, 0, TBSTATE_ENABLED, TBSTYLE_SEP}, + {0, 0, TBSTATE_ENABLED, TBSTYLE_SEP}, + {0, 0, TBSTATE_ENABLED, TBSTYLE_SEP}, + {0, 0, TBSTATE_ENABLED, TBSTYLE_SEP}, + {0, 0, TBSTATE_ENABLED, TBSTYLE_SEP}, + {0, 0, TBSTATE_ENABLED, TBSTYLE_SEP}, + {0, 0, TBSTATE_ENABLED, TBSTYLE_SEP}, + {0, 0, TBSTATE_ENABLED, TBSTYLE_SEP}, + {0, 0, TBSTATE_ENABLED, TBSTYLE_SEP}, + {0, IDMENU_COPY, TBSTATE_ENABLED, TBSTYLE_AUTOSIZE}, + {1, IDMENU_PASTE, TBSTATE_ENABLED, TBSTYLE_AUTOSIZE}, + {2, IDMENU_FONT, TBSTATE_ENABLED, TBSTYLE_AUTOSIZE}, + {3, IDMENU_ABOUT, TBSTATE_ENABLED, TBSTYLE_AUTOSIZE}, + {0, 0, TBSTATE_ENABLED, TBSTYLE_SEP} }; static TBADDBITMAP tbbitmap = @@ -2156,6 +2210,17 @@ static TBADDBITMAP tbbitmap = HINST_COMMCTRL, IDB_STD_SMALL_COLOR, }; +#ifdef HARDDEBUG +/* For really hard GUI startup debugging, place DEBUGBOX() macros in code + and get modal message boxes with the line number. */ +static void debug_box(int line) { + TCHAR buff[1024]; + swprintf(buff,1024,TEXT("DBG:%d"),line); + MessageBox(NULL,buff,TEXT("DBG"),MB_OK|MB_APPLMODAL); +} + +#define DEBUGBOX() debug_box(__LINE__) +#endif static HWND InitToolBar(HWND hwndParent) @@ -2169,7 +2234,6 @@ InitToolBar(HWND hwndParent) COLORMAP colorMap; colorMap.from = RGB(192, 192, 192); colorMap.to = backgroundColor; - /* Create toolbar window with tooltips */ hwndTB = CreateWindowEx(0,TOOLBARCLASSNAME,(TCHAR *)NULL, WS_CHILD|CCS_TOP|WS_CLIPSIBLINGS|TBSTYLE_TOOLTIPS, @@ -2180,9 +2244,10 @@ InitToolBar(HWND hwndParent) tbbitmap.hInst = NULL; tbbitmap.nID = (UINT) CreateMappedBitmap(beam_module, 1,0, &colorMap, 1); SendMessage(hwndTB, TB_ADDBITMAP, (WPARAM) 4, - (WPARAM) &tbbitmap); + (LPARAM) &tbbitmap); + SendMessage(hwndTB,TB_ADDBUTTONS, (WPARAM) 30, - (LPARAM) (LPTBBUTTON) tbb); + (LPARAM) tbb); if (toolbarVisible) ShowWindow(hwndTB, SW_SHOW); diff --git a/erts/emulator/drivers/win32/win_efile.c b/erts/emulator/drivers/win32/win_efile.c index 931bb196f1..0bc701c4cb 100644 --- a/erts/emulator/drivers/win32/win_efile.c +++ b/erts/emulator/drivers/win32/win_efile.c @@ -21,6 +21,9 @@ */ #include <windows.h> +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif #include "sys.h" #include <ctype.h> #include <wchar.h> diff --git a/erts/emulator/hipe/hipe_arm.c b/erts/emulator/hipe/hipe_arm.c index d52f429a9b..e20a8a7969 100644 --- a/erts/emulator/hipe/hipe_arm.c +++ b/erts/emulator/hipe/hipe_arm.c @@ -71,7 +71,7 @@ static struct segment { } curseg; #define in_area(ptr,start,nbytes) \ - ((unsigned long)((char*)(ptr) - (char*)(start)) < (nbytes)) + ((UWord)((char*)(ptr) - (char*)(start)) < (nbytes)) static void *new_code_mapping(void) { diff --git a/erts/emulator/hipe/hipe_ppc.c b/erts/emulator/hipe/hipe_ppc.c index bc25061a16..2d8fd61e1e 100644 --- a/erts/emulator/hipe/hipe_ppc.c +++ b/erts/emulator/hipe/hipe_ppc.c @@ -80,7 +80,7 @@ static struct segment { } curseg; #define in_area(ptr,start,nbytes) \ - ((unsigned long)((char*)(ptr) - (char*)(start)) < (nbytes)) + ((UWord)((char*)(ptr) - (char*)(start)) < (nbytes)) /* Darwin breakage */ #if !defined(MAP_ANONYMOUS) && defined(MAP_ANON) diff --git a/erts/emulator/sys/common/erl_check_io.c b/erts/emulator/sys/common/erl_check_io.c index ba88fd1d39..23a4bf1b04 100644 --- a/erts/emulator/sys/common/erl_check_io.c +++ b/erts/emulator/sys/common/erl_check_io.c @@ -314,7 +314,7 @@ forget_removed(struct pollset_info* psi) erts_smp_mtx_unlock(mtx); if (drv_ptr) { int was_unmasked = erts_block_fpe(); - (*drv_ptr->stop_select) (fd, NULL); + (*drv_ptr->stop_select) ((ErlDrvEvent) fd, NULL); erts_unblock_fpe(was_unmasked); if (drv_ptr->handle) { erts_ddll_dereference_driver(drv_ptr->handle); @@ -1134,7 +1134,8 @@ ERTS_CIO_EXPORT(erts_check_io_interrupt)(int set) } void -ERTS_CIO_EXPORT(erts_check_io_interrupt_timed)(int set, long msec) +ERTS_CIO_EXPORT(erts_check_io_interrupt_timed)(int set, + erts_short_time_t msec) { ERTS_CIO_POLL_INTR_TMD(pollset.ps, set, msec); } diff --git a/erts/emulator/sys/common/erl_check_io.h b/erts/emulator/sys/common/erl_check_io.h index 7cc1658062..edab7947ba 100644 --- a/erts/emulator/sys/common/erl_check_io.h +++ b/erts/emulator/sys/common/erl_check_io.h @@ -46,8 +46,8 @@ void erts_check_io_async_sig_interrupt_nkp(void); #endif void erts_check_io_interrupt_kp(int); void erts_check_io_interrupt_nkp(int); -void erts_check_io_interrupt_timed_kp(int, long); -void erts_check_io_interrupt_timed_nkp(int, long); +void erts_check_io_interrupt_timed_kp(int, erts_short_time_t); +void erts_check_io_interrupt_timed_nkp(int, erts_short_time_t); void erts_check_io_kp(int); void erts_check_io_nkp(int); void erts_init_check_io_kp(void); @@ -64,7 +64,7 @@ int erts_check_io_max_files(void); void erts_check_io_async_sig_interrupt(void); #endif void erts_check_io_interrupt(int); -void erts_check_io_interrupt_timed(int, long); +void erts_check_io_interrupt_timed(int, erts_short_time_t); void erts_check_io(int); void erts_init_check_io(void); diff --git a/erts/emulator/sys/common/erl_poll.c b/erts/emulator/sys/common/erl_poll.c index 80db2055a2..b6cb271f17 100644 --- a/erts/emulator/sys/common/erl_poll.c +++ b/erts/emulator/sys/common/erl_poll.c @@ -2171,7 +2171,7 @@ ERTS_POLL_EXPORT(erts_poll_async_sig_interrupt)(ErtsPollSet ps) void ERTS_POLL_EXPORT(erts_poll_interrupt_timed)(ErtsPollSet ps, int set, - long msec) + erts_short_time_t msec) { #if ERTS_POLL_ASYNC_INTERRUPT_SUPPORT || defined(ERTS_SMP) if (!set) diff --git a/erts/emulator/sys/common/erl_poll.h b/erts/emulator/sys/common/erl_poll.h index e0296c6a33..8dde619105 100644 --- a/erts/emulator/sys/common/erl_poll.h +++ b/erts/emulator/sys/common/erl_poll.h @@ -223,7 +223,7 @@ void ERTS_POLL_EXPORT(erts_poll_interrupt)(ErtsPollSet, int); void ERTS_POLL_EXPORT(erts_poll_interrupt_timed)(ErtsPollSet, int, - long); + erts_short_time_t); ErtsPollEvents ERTS_POLL_EXPORT(erts_poll_control)(ErtsPollSet, ErtsSysFdType, ErtsPollEvents, diff --git a/erts/emulator/sys/unix/erl_unix_sys.h b/erts/emulator/sys/unix/erl_unix_sys.h index 9a5ed9f5bc..c8fcec8547 100644 --- a/erts/emulator/sys/unix/erl_unix_sys.h +++ b/erts/emulator/sys/unix/erl_unix_sys.h @@ -146,6 +146,7 @@ typedef void *GETENV_STATE; /* ** For the erl_timer_sup module. */ +typedef time_t erts_time_t; typedef struct timeval SysTimeval; diff --git a/erts/emulator/sys/unix/sys.c b/erts/emulator/sys/unix/sys.c index c6b63350e5..52477467b3 100644 --- a/erts/emulator/sys/unix/sys.c +++ b/erts/emulator/sys/unix/sys.c @@ -265,7 +265,7 @@ struct { int (*event)(ErlDrvPort, ErlDrvEvent, ErlDrvEventData); void (*check_io_as_interrupt)(void); void (*check_io_interrupt)(int); - void (*check_io_interrupt_tmd)(int, long); + void (*check_io_interrupt_tmd)(int, erts_short_time_t); void (*check_io)(int); Uint (*size)(void); Eterm (*info)(void *); @@ -371,7 +371,7 @@ erts_sys_schedule_interrupt(int set) #ifdef ERTS_SMP void -erts_sys_schedule_interrupt_timed(int set, long msec) +erts_sys_schedule_interrupt_timed(int set, erts_short_time_t msec) { ERTS_CHK_IO_INTR_TMD(set, msec); } diff --git a/erts/emulator/sys/vxworks/erl_vxworks_sys.h b/erts/emulator/sys/vxworks/erl_vxworks_sys.h index ae46403600..69d9ca3478 100644 --- a/erts/emulator/sys/vxworks/erl_vxworks_sys.h +++ b/erts/emulator/sys/vxworks/erl_vxworks_sys.h @@ -158,6 +158,7 @@ typedef struct _vxworks_tms { typedef long long SysHrTime; +typedef time_t erts_time_t; typedef struct timeval SysTimeval; extern int sys_init_hrtime(void); diff --git a/erts/emulator/sys/win32/erl_poll.c b/erts/emulator/sys/win32/erl_poll.c index ab4ef05118..7a1d129cd5 100644 --- a/erts/emulator/sys/win32/erl_poll.c +++ b/erts/emulator/sys/win32/erl_poll.c @@ -442,8 +442,8 @@ poll_wait_timeout(ErtsPollSet ps, SysTimeval *tvp) if (erts_atomic32_read_nob(&ps->wakeup_state) != ERTS_POLL_NOT_WOKEN) return (DWORD) 0; - if (timeout > ERTS_AINT32_T_MAX) /* Also prevents DWORD overflow */ - timeout = ERTS_AINT32_T_MAX; + if (timeout > ((time_t) ERTS_AINT32_T_MAX)) + timeout = ERTS_AINT32_T_MAX; /* Also prevents DWORD overflow */ erts_smp_atomic32_set_relb(&ps->timeout, (erts_aint32_t) timeout); return (DWORD) timeout; @@ -1012,7 +1012,7 @@ void erts_poll_interrupt(ErtsPollSet ps, int set /* bool */) void erts_poll_interrupt_timed(ErtsPollSet ps, int set /* bool */, - long msec) + erts_short_time_t msec) { HARDTRACEF(("In erts_poll_interrupt_timed(%d,%ld)",set,msec)); if (!set) diff --git a/erts/emulator/sys/win32/erl_win32_sys_ddll.c b/erts/emulator/sys/win32/erl_win32_sys_ddll.c index a19f49af10..ec51cfea51 100644 --- a/erts/emulator/sys/win32/erl_win32_sys_ddll.c +++ b/erts/emulator/sys/win32/erl_win32_sys_ddll.c @@ -25,6 +25,9 @@ #include <windows.h> #define GET_ERTS_ALC_TEST +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif #include "sys.h" #include "global.h" #include "erl_alloc.h" diff --git a/erts/emulator/sys/win32/erl_win_dyn_driver.h b/erts/emulator/sys/win32/erl_win_dyn_driver.h index ecb06868d5..afc72bb898 100644 --- a/erts/emulator/sys/win32/erl_win_dyn_driver.h +++ b/erts/emulator/sys/win32/erl_win_dyn_driver.h @@ -83,10 +83,10 @@ WDD_TYPEDEF(void *, driver_dl_open, (char *)); WDD_TYPEDEF(void *, driver_dl_sym, (void *, char *)); WDD_TYPEDEF(int, driver_dl_close, (void *)); WDD_TYPEDEF(char *, driver_dl_error, (void)); -WDD_TYPEDEF(unsigned long, erts_alc_test, (unsigned long, - unsigned long, - unsigned long, - unsigned long)); +WDD_TYPEDEF(ErlDrvUInt, erts_alc_test, (ErlDrvUInt, + ErlDrvUInt, + ErlDrvUInt, + ErlDrvUInt)); WDD_TYPEDEF(ErlDrvSInt, driver_binary_get_refc, (ErlDrvBinary *dbp)); WDD_TYPEDEF(ErlDrvSInt, driver_binary_inc_refc, (ErlDrvBinary *dbp)); WDD_TYPEDEF(ErlDrvSInt, driver_binary_dec_refc, (ErlDrvBinary *dbp)); diff --git a/erts/emulator/sys/win32/erl_win_sys.h b/erts/emulator/sys/win32/erl_win_sys.h index 92d8577537..cf3fb4446f 100644 --- a/erts/emulator/sys/win32/erl_win_sys.h +++ b/erts/emulator/sys/win32/erl_win_sys.h @@ -117,9 +117,20 @@ int erts_check_io_debug(void); #define SYS_CLK_TCK 1000 #define SYS_CLOCK_RESOLUTION 1 +#if SIZEOF_TIME_T != 8 +# error "Unexpected sizeof(time_t)" +#endif + +/* + * gcc uses a 4 byte time_t and vc++ uses an 8 byte time_t. + * Types seen in beam_emu.c *need* to have the same size + * as in the rest of the system... + */ +typedef __int64 erts_time_t; + typedef struct { - long tv_sec; - long tv_usec; + erts_time_t tv_sec; + erts_time_t tv_usec; } SysTimeval; typedef struct { @@ -169,10 +180,12 @@ void erts_sys_env_init(void); extern volatile int erl_fp_exception; #include <float.h> -#if defined (__GNUC__) +/* I suspect this test isn't right, it might depend on the version of GCC + rather than if it's a MINGW gcc, but I havent been able to pinpoint the + exact point where _finite was added to the headers in cygwin... */ +#if defined (__GNUC__) && !defined(__MINGW32__) int _finite(double x); #endif -#endif /*#define NO_FPE_SIGNALS*/ #define erts_get_current_fp_exception() NULL @@ -191,13 +204,6 @@ int _finite(double x); #define erts_sys_block_fpe() 0 #define erts_sys_unblock_fpe(x) do{}while(0) -#define SIZEOF_SHORT 2 -#define SIZEOF_INT 4 -#define SIZEOF_LONG 4 -#define SIZEOF_VOID_P 4 -#define SIZEOF_SIZE_T 4 -#define SIZEOF_OFF_T 4 - /* * Seems to be missing. */ @@ -210,3 +216,4 @@ typedef long ssize_t; int init_async(int); int exit_async(void); #endif +#endif diff --git a/erts/emulator/sys/win32/sys.c b/erts/emulator/sys/win32/sys.c index 6f33ef7ad6..a701747b78 100644..100755 --- a/erts/emulator/sys/win32/sys.c +++ b/erts/emulator/sys/win32/sys.c @@ -1634,17 +1634,6 @@ create_child_process WaitForSingleObject(hProcess, 50); } - /* - * When an application spawns a process repeatedly, a new thread - * instance will be created for each process but the previous - * instances may not be cleaned up. This results in a significant - * virtual memory loss each time the process is spawned. If there - * is a WaitForInputIdle() call between CreateProcess() and - * CloseHandle(), the problem does not occur. PSS ID Number: Q124121 - */ - - WaitForInputIdle(piProcInfo.hProcess, 5000); - return ok; } @@ -3301,7 +3290,7 @@ erts_sys_schedule_interrupt(int set) #ifdef ERTS_SMP void -erts_sys_schedule_interrupt_timed(int set, long msec) +erts_sys_schedule_interrupt_timed(int set, erts_short_time_t msec) { erts_check_io_interrupt_timed(set, msec); } diff --git a/erts/emulator/sys/win32/sys_float.c b/erts/emulator/sys/win32/sys_float.c index 9e67ca7f48..6c03821f3b 100644 --- a/erts/emulator/sys/win32/sys_float.c +++ b/erts/emulator/sys/win32/sys_float.c @@ -18,6 +18,9 @@ */ /* Float conversions */ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif #include "sys.h" #include "signal.h" diff --git a/erts/emulator/sys/win32/sys_interrupt.c b/erts/emulator/sys/win32/sys_interrupt.c index 93aaa23f97..347c31053b 100644 --- a/erts/emulator/sys/win32/sys_interrupt.c +++ b/erts/emulator/sys/win32/sys_interrupt.c @@ -19,6 +19,9 @@ /* * Purpose: Interrupt handling in windows. */ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif #include "sys.h" #include "erl_alloc.h" #include "erl_thr_progress.h" diff --git a/erts/emulator/sys/win32/sys_time.c b/erts/emulator/sys/win32/sys_time.c index 50e43065b5..e5b9513edc 100644 --- a/erts/emulator/sys/win32/sys_time.c +++ b/erts/emulator/sys/win32/sys_time.c @@ -20,6 +20,9 @@ * Purpose: System-dependent time functions. */ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif #include "sys.h" #include "assert.h" @@ -52,8 +55,8 @@ sys_gettimeofday(SysTimeval *tv) GetSystemTime(&t); SystemTimeToFileTime(&t, &ft); memcpy(&lft, &ft, sizeof(lft)); - tv->tv_usec = (long) ((lft / LL_LITERAL(10)) % LL_LITERAL(1000000)); - tv->tv_sec = (long) ((lft / LL_LITERAL(10000000)) - EPOCH_JULIAN_DIFF); + tv->tv_usec = (erts_time_t) ((lft / LL_LITERAL(10)) % LL_LITERAL(1000000)); + tv->tv_sec = (erts_time_t) ((lft / LL_LITERAL(10000000)) - EPOCH_JULIAN_DIFF); } SysHrTime diff --git a/erts/emulator/test/alloc_SUITE_data/allocator_test.h b/erts/emulator/test/alloc_SUITE_data/allocator_test.h index 8b34375980..cd4a91d34a 100644 --- a/erts/emulator/test/alloc_SUITE_data/allocator_test.h +++ b/erts/emulator/test/alloc_SUITE_data/allocator_test.h @@ -19,7 +19,7 @@ #ifndef ALLOCATOR_TEST_H__ #define ALLOCATOR_TEST_H__ -typedef unsigned long Ulong; +typedef ErlDrvUInt Ulong; #ifndef __WIN32__ Ulong erts_alc_test(Ulong, Ulong, Ulong, Ulong); diff --git a/erts/emulator/test/big_SUITE.erl b/erts/emulator/test/big_SUITE.erl index 3487917677..413bd3bcae 100644 --- a/erts/emulator/test/big_SUITE.erl +++ b/erts/emulator/test/big_SUITE.erl @@ -26,7 +26,7 @@ shift_limit_1/1, powmod/1, system_limit/1, otp_6692/1]). %% Internal exports. --export([eval/1, funcall/2]). +-export([eval/1]). -export([init/3]). -export([fac/1, fib/1, pow/2, gcd/2, lcm/2]). @@ -162,12 +162,15 @@ multi_match([Node|Ns], Expr, Rs) -> multi_match([], _, Rs) -> Rs. eval(Expr) -> - Fun = {?MODULE,funcall}, - {value,V,_} = erl_eval:expr(Expr, [], Fun), %Applied arithmetic BIFs. - V = eval(Expr, Fun), %Real arithmetic instructions. - V. + LFH = fun(Name, As) -> apply(?MODULE, Name, As) end, + + %% Applied arithmetic BIFs. + {value,V,_} = erl_eval:expr(Expr, [], {value,LFH}), -funcall(F, As) -> apply(?MODULE, F, As). + %% Real arithmetic instructions. + V = eval(Expr, LFH), + + V. %% Like a subset of erl_eval:expr/3, but uses real arithmetic instructions instead of %% applying them (it does make a difference). diff --git a/erts/emulator/test/nif_SUITE_data/nif_SUITE.c b/erts/emulator/test/nif_SUITE_data/nif_SUITE.c index 7d7903af25..03092fef5e 100644 --- a/erts/emulator/test/nif_SUITE_data/nif_SUITE.c +++ b/erts/emulator/test/nif_SUITE_data/nif_SUITE.c @@ -345,8 +345,13 @@ static int test_double(ErlNifEnv* env, double d1) #define TAG_BITS 4 #define SMALL_BITS (sizeof(void*)*8 - TAG_BITS) +#ifdef _WIN64 +#define MAX_SMALL ((1LL << (SMALL_BITS-1))-1) +#define MIN_SMALL (-(1LL << (SMALL_BITS-1))) +#else #define MAX_SMALL ((1L << (SMALL_BITS-1))-1) #define MIN_SMALL (-(1L << (SMALL_BITS-1))) +#endif static ERL_NIF_TERM type_test(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { diff --git a/erts/emulator/test/sensitive_SUITE.erl b/erts/emulator/test/sensitive_SUITE.erl index 634df367ca..e073eab596 100644 --- a/erts/emulator/test/sensitive_SUITE.erl +++ b/erts/emulator/test/sensitive_SUITE.erl @@ -160,8 +160,7 @@ recv_trace(Config) when is_list(Config) -> ?line {messages,Messages} = process_info(Tracer, messages), [{trace,Parent,'receive',a}, {trace,Parent,'receive',{trace_delivered,_,_}}, - {trace,Parent,'receive',c}, - {trace,Parent,'receive',{trace_delivered,_,_}}] = Messages, + {trace,Parent,'receive',c}|_] = Messages, ?line unlink(Tracer), exit(Tracer, kill), ?line unlink(Sender), exit(Sender, kill), diff --git a/erts/emulator/utils/make_preload b/erts/emulator/utils/make_preload index d22f08f993..62aaef51d9 100755 --- a/erts/emulator/utils/make_preload +++ b/erts/emulator/utils/make_preload @@ -39,6 +39,7 @@ use File::Basename; my $gen_rc = 0; my $gen_old = 0; my $windres = 0; +my $msys = 0; my $file; my $progname = basename($0); @@ -49,6 +50,8 @@ while (@ARGV && $ARGV[0] =~ /^-(\w+)/) { $gen_rc = 1; } elsif ($opt eq '-windres') { $windres = 1; + } elsif ($opt eq '-msys') { + $msys = 1; } elsif ($opt eq '-old') { $gen_old = 1; } else { @@ -68,7 +71,12 @@ foreach $file (@ARGV) { unless $file =~ /\.beam$/; my $module = basename($file, ".beam"); if ($gen_rc) { - my ($win_file) = split("\n", `(cygpath -d $file 2>/dev/null || cygpath -w $file)`); + my $win_file; + if ($msys) { + ($win_file) = split("\n", `(msys2win_path.sh $file)`); + } else { + ($win_file) = split("\n", `(cygpath -d $file 2>/dev/null || cygpath -w $file)`); + } $win_file =~ s&\\&\\\\&g; print "$num ERLANG_CODE \"$win_file\"\n"; push(@modules, " ", -s $file, "L, $num, ", diff --git a/erts/emulator/valgrind/suppress.patched.3.6.0 b/erts/emulator/valgrind/suppress.patched.3.6.0 index 2647949672..8cf4cba2c8 100644 --- a/erts/emulator/valgrind/suppress.patched.3.6.0 +++ b/erts/emulator/valgrind/suppress.patched.3.6.0 @@ -305,3 +305,46 @@ fun:erl_init fun:erl_start fun:main } + +{ +Permanent cache aligned malloc for array of mseg allocators +Memcheck:Leak +PossiblyLost +fun:malloc +fun:erts_mseg_init +fun:erts_alloc_init +fun:early_init +fun:erl_start +fun:main +} + +{ +Early permanent cache aligned erl_process:aux_work_tmo +Memcheck:Leak +PossiblyLost +fun:malloc +fun:aux_work_timeout_early_init +fun:erts_early_init_scheduling +fun:early_init +fun:erl_start +fun:main +} + +{ +Early permanent cache aligned ts_event_pool +Memcheck:Leak +PossiblyLost +fun:malloc +fun:erts_sys_alloc +fun:erts_alloc_fnf +fun:ethr_std_alloc +fun:ts_event_pool +fun:init_ts_event_alloc +fun:ethr_late_init_common__ +fun:ethr_late_init +fun:erts_thr_late_init +fun:early_init +fun:erl_start +fun:main +} + diff --git a/erts/emulator/valgrind/suppress.standard b/erts/emulator/valgrind/suppress.standard index d759038c97..26e34e3757 100644 --- a/erts/emulator/valgrind/suppress.standard +++ b/erts/emulator/valgrind/suppress.standard @@ -266,3 +266,43 @@ fun:erl_init fun:erl_start fun:main } + +{ +Permanent cache aligned malloc for array of mseg allocators +Memcheck:Leak +fun:malloc +fun:erts_mseg_init +fun:erts_alloc_init +fun:early_init +fun:erl_start +fun:main +} + +{ +Early permanent cache aligned erl_process:aux_work_tmo +Memcheck:Leak +fun:malloc +fun:aux_work_timeout_early_init +fun:erts_early_init_scheduling +fun:early_init +fun:erl_start +fun:main +} + +{ +Early permanent cache aligned ts_event_pool +Memcheck:Leak +fun:malloc +fun:erts_sys_alloc +fun:erts_alloc_fnf +fun:ethr_std_alloc +fun:ts_event_pool +fun:init_ts_event_alloc +fun:ethr_late_init_common__ +fun:ethr_late_init +fun:erts_thr_late_init +fun:early_init +fun:erl_start +fun:main +} + |