diff options
Diffstat (limited to 'erts/emulator')
140 files changed, 3438 insertions, 1662 deletions
diff --git a/erts/emulator/Makefile.in b/erts/emulator/Makefile.in index 708d4ca0a3..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) @@ -971,7 +972,8 @@ HIPE_SRC= endif BEAM_SRC=$(wildcard beam/*.c) -DRV_SRC=$(wildcard drivers/common/*.c) $(wildcard drivers/$(ERLANG_OSTYPE)/*.c) +DRV_COMMON_SRC=$(wildcard drivers/common/*.c) +DRV_OSTYPE_SRC=$(wildcard drivers/$(ERLANG_OSTYPE)/*.c) ALL_SYS_SRC=$(wildcard sys/$(ERLANG_OSTYPE)/*.c) $(wildcard sys/common/*.c) TARGET_SRC=$(wildcard $(TARGET)/*.c) $(wildcard $(TTF_DIR)/*.c) @@ -982,7 +984,7 @@ ifeq ($(TARGET),win32) #DEP_CC=$(EMU_CC) DEP_CC=$(CC) -DEP_FLAGS=-MM $(subst -O2,,$(CFLAGS)) $(INCLUDES) -I../etc/win32 -Idrivers/common +DEP_FLAGS=-MM $(subst -O2,,$(CFLAGS)) $(INCLUDES) -I../etc/win32 -Idrivers/common -Idrivers/$(ERLANG_OSTYPE) # ifeq (@MIXED_CYGWIN_VC@,yes) # VC++ used for compiling. If __GNUC__ is defined we will include # other headers then when compiling which will result in faulty @@ -1002,23 +1004,21 @@ MG_FLAG=-MG endif DEP_CC=$(CC) -DEP_FLAGS=-MM $(MG_FLAG) $(CFLAGS) $(INCLUDES) -Idrivers/common +DEP_FLAGS=-MM $(MG_FLAG) $(CFLAGS) $(INCLUDES) -Idrivers/common -Idrivers/$(ERLANG_OSTYPE) SYS_SRC=$(ALL_SYS_SRC) endif depend: $(DEP_CC) $(DEP_FLAGS) $(BEAM_SRC) \ | $(SED_DEPEND) > $(TARGET)/depend.mk - $(DEP_CC) $(DEP_FLAGS) $(DRV_SRC) \ + $(DEP_CC) $(DEP_FLAGS) -DLIBSCTP=$(LIBSCTP) $(DRV_COMMON_SRC) \ + | $(SED_DEPEND) >> $(TARGET)/depend.mk + $(DEP_CC) $(DEP_FLAGS) -I../etc/$(ERLANG_OSTYPE) $(DRV_OSTYPE_SRC) \ | $(SED_DEPEND) >> $(TARGET)/depend.mk $(DEP_CC) $(DEP_FLAGS) $(SYS_SRC) \ | $(SED_DEPEND) >> $(TARGET)/depend.mk $(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 4427defe0c..dd788df6e4 100644 --- a/erts/emulator/beam/beam_load.c +++ b/erts/emulator/beam/beam_load.c @@ -254,6 +254,7 @@ typedef struct LoaderState { char* file_name; /* Name of file we are reading (usually chunk name). */ byte* file_p; /* Current pointer within file. */ unsigned file_left; /* Number of bytes left in file. */ + ErlDrvBinary* bin; /* Binary holding BEAM file (or NULL) */ /* * The following are used mainly for diagnostics. @@ -499,8 +500,10 @@ static void free_state(LoaderState* stp); static Eterm insert_new_code(Process *c_p, ErtsProcLocks c_p_locks, Eterm group_leader, Eterm module, BeamInstr* code, Uint size); +static int init_iff_file(LoaderState* stp, byte* code, Uint size); static int scan_iff_file(LoaderState* stp, Uint* chunk_types, Uint num_types, Uint num_mandatory); +static int verify_chunks(LoaderState* stp); static int load_atom_table(LoaderState* stp); static int load_import_table(LoaderState* stp); static int read_export_table(LoaderState* stp); @@ -630,40 +633,23 @@ erts_prepare_loading(LoaderState* stp, Process *c_p, Eterm group_leader, Eterm* modp, byte* code, Uint unloaded_size) { Eterm retval = am_badfile; - ErlDrvBinary* bin = NULL; stp->module = *modp; stp->group_leader = group_leader; - /* - * Check if the module is compressed (or possibly invalid/corrupted). - */ - if ( !(unloaded_size >= 4 && - code[0] == 'F' && code[1] == 'O' && - code[2] == 'R' && code[3] == '1') ) { - bin = (ErlDrvBinary *) - erts_gzinflate_buffer((char*)code, unloaded_size); - if (bin == NULL) { - goto load_error; - } - code = (byte*)bin->orig_bytes; - unloaded_size = bin->orig_size; - } +#if defined(LOAD_MEMORY_HARD_DEBUG) && defined(DEBUG) + erts_fprintf(stderr,"Loading a module\n"); +#endif /* * Scan the IFF file. */ -#if defined(LOAD_MEMORY_HARD_DEBUG) && defined(DEBUG) - erts_fprintf(stderr,"Loading a module\n"); -#endif - CHKALLOC(); CHKBLK(ERTS_ALC_T_CODE,stp->code); - stp->file_name = "IFF header for Beam file"; - stp->file_p = code; - stp->file_left = unloaded_size; - if (!scan_iff_file(stp, chunk_types, NUM_CHUNK_TYPES, NUM_MANDATORY)) { + if (!init_iff_file(stp, code, unloaded_size) || + !scan_iff_file(stp, chunk_types, NUM_CHUNK_TYPES, NUM_MANDATORY) || + !verify_chunks(stp)) { goto load_error; } @@ -787,9 +773,6 @@ erts_prepare_loading(LoaderState* stp, Process *c_p, Eterm group_leader, retval = NIL; load_error: - if (bin) { - driver_free_binary(bin); - } if (retval != NIL) { free_state(stp); } @@ -864,6 +847,7 @@ erts_alloc_loader_state(void) LoaderState* stp; stp = erts_alloc(ERTS_ALC_T_LOADER_TMP, sizeof(LoaderState)); + stp->bin = NULL; stp->function = THE_NON_VALUE; /* Function not known yet */ stp->arity = 0; stp->specific_op = -1; @@ -897,6 +881,9 @@ erts_alloc_loader_state(void) static void free_state(LoaderState* stp) { + if (stp->bin != 0) { + driver_free_binary(stp->bin); + } if (stp->code != 0) { erts_free(ERTS_ALC_T_CODE, stp->code); } @@ -956,6 +943,7 @@ free_state(LoaderState* stp) if (stp->fname != 0) { erts_free(ERTS_ALC_T_LOADER_TMP, stp->fname); } + erts_free(ERTS_ALC_T_LOADER_TMP, stp); } @@ -968,7 +956,7 @@ insert_new_code(Process *c_p, ErtsProcLocks c_p_locks, Eterm retval; int i; - if ((retval = beam_make_current_old(c_p, c_p_locks, module)) < 0) { + if ((retval = beam_make_current_old(c_p, c_p_locks, module)) != NIL) { erts_dsprintf_buf_t *dsbufp = erts_create_logger_dsbuf(); erts_dsprintf(dsbufp, "Module %T must be purged before loading\n", @@ -1011,23 +999,47 @@ insert_new_code(Process *c_p, ErtsProcLocks c_p_locks, } static int -scan_iff_file(LoaderState* stp, Uint* chunk_types, Uint num_types, Uint num_mandatory) +init_iff_file(LoaderState* stp, byte* code, Uint size) { - MD5_CTX context; + Uint form_id = MakeIffId('F', 'O', 'R', '1'); Uint id; Uint count; - int i; + + if (size < 4) { + goto load_error; + } /* - * The binary must start with an IFF 'FOR1' chunk. + * Check if the module is compressed (or possibly invalid/corrupted). */ + if (MakeIffId(code[0], code[1], code[2], code[3]) != form_id) { + stp->bin = (ErlDrvBinary *) erts_gzinflate_buffer((char*)code, size); + if (stp->bin == NULL) { + goto load_error; + } + code = (byte*)stp->bin->orig_bytes; + size = stp->bin->orig_size; + if (size < 4) { + goto load_error; + } + } - GetInt(stp, 4, id); - if (id != MakeIffId('F', 'O', 'R', '1')) { + /* + * The binary must start with an IFF 'FOR1' chunk. + */ + if (MakeIffId(code[0], code[1], code[2], code[3]) != form_id) { LoadError0(stp, "not a BEAM file: no IFF 'FOR1' chunk"); } /* + * Initialize our "virtual file system". + */ + + stp->file_name = "IFF header for Beam file"; + stp->file_p = code + 4; + stp->file_left = size - 4; + + /* * Retrieve the chunk size and verify it. If the size is equal to * or less than the size of the binary, it is ok and we will use it * as the limit for the logical file size. @@ -1048,6 +1060,21 @@ scan_iff_file(LoaderState* stp, Uint* chunk_types, Uint num_types, Uint num_mand if (id != MakeIffId('B', 'E', 'A', 'M')) { LoadError0(stp, "not a BEAM file: IFF form type is not 'BEAM'"); } + return 1; + + load_error: + return 0; +} + +/* + * Scan the IFF file. The header should have been verified by init_iff_file(). + */ +static int +scan_iff_file(LoaderState* stp, Uint* chunk_types, Uint num_types, Uint num_mandatory) +{ + Uint count; + Uint id; + int i; /* * Initialize the chunks[] array in the state. @@ -1104,17 +1131,25 @@ scan_iff_file(LoaderState* stp, Uint* chunk_types, Uint num_types, Uint num_mand stp->file_p += count; stp->file_left -= count; } + return 1; - /* - * At this point, we have read the entire IFF file, and we - * know that it is syntactically correct. - * - * Now check that it contains all mandatory chunks. At the - * same time calculate the MD5 for the module. - */ + load_error: + return 0; +} + +/* + * Verify that all mandatory chunks are present and calculate + * MD5 for the module. + */ + +static int +verify_chunks(LoaderState* stp) +{ + int i; + MD5_CTX context; MD5Init(&context); - for (i = 0; i < num_mandatory; i++) { + for (i = 0; i < NUM_MANDATORY; i++) { if (stp->chunks[i].start != NULL) { MD5Update(&context, stp->chunks[i].start, stp->chunks[i].size); } else { @@ -1124,41 +1159,49 @@ scan_iff_file(LoaderState* stp, Uint* chunk_types, Uint num_types, Uint num_mand LoadError1(stp, "mandatory chunk of type '%s' not found\n", sbuf); } } - if (LITERAL_CHUNK < num_types) { - if (stp->chunks[LAMBDA_CHUNK].start != 0) { - byte* start = stp->chunks[LAMBDA_CHUNK].start; - Uint left = stp->chunks[LAMBDA_CHUNK].size; - /* - * The idea here is to ignore the OldUniq field for the fun; it is - * based on the old broken hash function, which can be different - * on little endian and big endian machines. - */ - if (left >= 4) { - static byte zero[4]; - MD5Update(&context, start, 4); - start += 4; - left -= 4; + /* + * If there is a lambda chunk, include parts of it in the MD5. + */ + if (stp->chunks[LAMBDA_CHUNK].start != 0) { + byte* start = stp->chunks[LAMBDA_CHUNK].start; + Uint left = stp->chunks[LAMBDA_CHUNK].size; + + /* + * The idea here is to ignore the OldUniq field for the fun; it is + * based on the old broken hash function, which can be different + * on little endian and big endian machines. + */ + if (left >= 4) { + static byte zero[4]; + MD5Update(&context, start, 4); + start += 4; + left -= 4; - while (left >= 24) { - /* Include: Function Arity Index NumFree */ - MD5Update(&context, start, 20); - /* Set to zero: OldUniq */ - MD5Update(&context, zero, 4); - start += 24; - left -= 24; - } - } - /* Can't happen for a correct 'FunT' chunk */ - if (left > 0) { - MD5Update(&context, start, left); + while (left >= 24) { + /* Include: Function Arity Index NumFree */ + MD5Update(&context, start, 20); + /* Set to zero: OldUniq */ + MD5Update(&context, zero, 4); + start += 24; + left -= 24; } } - if (stp->chunks[LITERAL_CHUNK].start != 0) { - MD5Update(&context, stp->chunks[LITERAL_CHUNK].start, - stp->chunks[LITERAL_CHUNK].size); + /* Can't happen for a correct 'FunT' chunk */ + if (left > 0) { + MD5Update(&context, start, left); } } + + + /* + * If there is a literal chunk, include it in the MD5. + */ + if (stp->chunks[LITERAL_CHUNK].start != 0) { + MD5Update(&context, stp->chunks[LITERAL_CHUNK].start, + stp->chunks[LITERAL_CHUNK].size); + } + MD5Final(stp->mod_md5, &context); return 1; @@ -1391,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); @@ -1401,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)); @@ -3457,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. */ @@ -3489,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]; @@ -5407,7 +5449,7 @@ code_get_chunk_2(BIF_ALIST_2) Process* p = BIF_P; Eterm Bin = BIF_ARG_1; Eterm Chunk = BIF_ARG_2; - LoaderState state; + LoaderState* stp; Uint chunk = 0; ErlSubBin* sb; Uint offset; @@ -5419,15 +5461,16 @@ code_get_chunk_2(BIF_ALIST_2) Eterm real_bin; byte* temp_alloc = NULL; + stp = erts_alloc_loader_state(); if ((start = erts_get_aligned_binary_bytes(Bin, &temp_alloc)) == NULL) { error: erts_free_aligned_binary_bytes(temp_alloc); + if (stp) { + free_state(stp); + } BIF_ERROR(p, BADARG); } - state.module = THE_NON_VALUE; /* Suppress diagnostiscs */ - state.file_name = "IFF header for Beam file"; - state.file_p = start; - state.file_left = binary_size(Bin); + stp->module = THE_NON_VALUE; /* Suppress diagnostics */ for (i = 0; i < 4; i++) { Eterm* chunkp; Eterm num; @@ -5445,25 +5488,30 @@ code_get_chunk_2(BIF_ALIST_2) if (is_not_nil(Chunk)) { goto error; } - if (!scan_iff_file(&state, &chunk, 1, 1)) { - erts_free_aligned_binary_bytes(temp_alloc); - return am_undefined; + if (!init_iff_file(stp, start, binary_size(Bin)) || + !scan_iff_file(stp, &chunk, 1, 1) || + stp->chunks[0].start == NULL) { + res = am_undefined; + goto done; } ERTS_GET_REAL_BIN(Bin, real_bin, offset, bitoffs, bitsize); if (bitoffs) { - res = new_binary(p, state.chunks[0].start, state.chunks[0].size); + res = new_binary(p, stp->chunks[0].start, stp->chunks[0].size); } else { sb = (ErlSubBin *) HAlloc(p, ERL_SUB_BIN_SIZE); sb->thing_word = HEADER_SUB_BIN; sb->orig = real_bin; - sb->size = state.chunks[0].size; + sb->size = stp->chunks[0].size; sb->bitsize = 0; sb->bitoffs = 0; - sb->offs = offset + (state.chunks[0].start - start); + sb->offs = offset + (stp->chunks[0].start - start); sb->is_writable = 0; res = make_binary(sb); } + + done: erts_free_aligned_binary_bytes(temp_alloc); + free_state(stp); return res; } @@ -5476,21 +5524,29 @@ code_module_md5_1(BIF_ALIST_1) { Process* p = BIF_P; Eterm Bin = BIF_ARG_1; - LoaderState state; + LoaderState* stp; + byte* bytes; byte* temp_alloc = NULL; + Eterm res; - if ((state.file_p = erts_get_aligned_binary_bytes(Bin, &temp_alloc)) == NULL) { + stp = erts_alloc_loader_state(); + if ((bytes = erts_get_aligned_binary_bytes(Bin, &temp_alloc)) == NULL) { + free_state(stp); BIF_ERROR(p, BADARG); } - state.module = THE_NON_VALUE; /* Suppress diagnostiscs */ - state.file_name = "IFF header for Beam file"; - state.file_left = binary_size(Bin); - - if (!scan_iff_file(&state, chunk_types, NUM_CHUNK_TYPES, NUM_MANDATORY)) { - return am_undefined; + stp->module = THE_NON_VALUE; /* Suppress diagnostiscs */ + if (!init_iff_file(stp, bytes, binary_size(Bin)) || + !scan_iff_file(stp, chunk_types, NUM_CHUNK_TYPES, NUM_MANDATORY) || + !verify_chunks(stp)) { + res = am_undefined; + goto done; } + res = new_binary(p, stp->mod_md5, sizeof(stp->mod_md5)); + + done: erts_free_aligned_binary_bytes(temp_alloc); - return new_binary(p, state.mod_md5, sizeof(state.mod_md5)); + free_state(stp); + return res; } #define WORDS_PER_FUNCTION 6 @@ -5776,7 +5832,6 @@ erts_make_stub_module(Process* p, Eterm Mod, Eterm Beam, Eterm Info) int code_size; int rval; int i; - ErlDrvBinary* bin = NULL; byte* temp_alloc = NULL; byte* bytes; Uint size; @@ -5809,29 +5864,17 @@ erts_make_stub_module(Process* p, Eterm Mod, Eterm Beam, Eterm Info) size = binary_size(Beam); /* - * Uncompressed if needed. - */ - if (!(size >= 4 && bytes[0] == 'F' && bytes[1] == 'O' && - bytes[2] == 'R' && bytes[3] == '1')) { - bin = (ErlDrvBinary *) erts_gzinflate_buffer((char*)bytes, size); - if (bin == NULL) { - goto error; - } - bytes = (byte*)bin->orig_bytes; - size = bin->orig_size; - } - - /* * Scan the Beam binary and read the interesting sections. */ - stp->file_name = "IFF header for Beam file"; - stp->file_p = bytes; - stp->file_left = size; stp->module = Mod; stp->group_leader = p->group_leader; stp->num_functions = n; - if (!scan_iff_file(stp, chunk_types, NUM_CHUNK_TYPES, NUM_MANDATORY)) { + if (!init_iff_file(stp, bytes, size)) { + goto error; + } + if (!scan_iff_file(stp, chunk_types, NUM_CHUNK_TYPES, NUM_MANDATORY) || + !verify_chunks(stp)) { goto error; } define_file(stp, "code chunk header", CODE_CHUNK); @@ -5986,13 +6029,11 @@ erts_make_stub_module(Process* p, Eterm Mod, Eterm Beam, Eterm Info) if (patch_funentries(Patchlist)) { erts_free_aligned_binary_bytes(temp_alloc); free_state(stp); - if (bin != NULL) { - driver_free_binary(bin); - } return Mod; } error: + erts_free_aligned_binary_bytes(temp_alloc); free_state(stp); BIF_ERROR(p, BADARG); } diff --git a/erts/emulator/beam/bif.c b/erts/emulator/beam/bif.c index 8ab363a1ec..55f4798892 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); @@ -3389,6 +3385,61 @@ BIF_RETTYPE universaltime_to_localtime_1(BIF_ALIST_1) BIF_RET(TUPLE2(hp, res1, res2)); } +/* convert calendar:universaltime_to_seconds/1 */ + +BIF_RETTYPE universaltime_to_posixtime_1(BIF_ALIST_1) +{ + Sint year, month, day; + Sint hour, minute, second; + + Sint64 seconds = 0; + Eterm *hp; + Uint hsz = 0; + + if (!time_to_parts(BIF_ARG_1, &year, &month, &day, + &hour, &minute, &second)) + BIF_ERROR(BIF_P, BADARG); + + if (!univ_to_seconds(year, month, day, hour, minute, second, &seconds)) { + BIF_ERROR(BIF_P, BADARG); + } + + erts_bld_sint64(NULL, &hsz, seconds); + hp = HAlloc(BIF_P, hsz); + BIF_RET(erts_bld_sint64(&hp, NULL, seconds)); +} + +/* convert calendar:seconds_to_universaltime/1 */ + +BIF_RETTYPE posixtime_to_universaltime_1(BIF_ALIST_1) +{ + Sint year, month, day; + Sint hour, minute, second; + Eterm res1, res2; + Eterm* hp; + + Sint64 time = 0; + + if (!term_to_Sint64(BIF_ARG_1, &time)) { + BIF_ERROR(BIF_P, BADARG); + } + + if (!seconds_to_univ(time, &year, &month, &day, + &hour, &minute, &second)) { + BIF_ERROR(BIF_P, BADARG); + } + + hp = HAlloc(BIF_P, 4+4+3); + res1 = TUPLE3(hp,make_small(year),make_small(month), + make_small(day)); + hp += 4; + res2 = TUPLE3(hp,make_small(hour),make_small(minute), + make_small(second)); + hp += 4; + BIF_RET(TUPLE2(hp, res1, res2)); +} + + /**********************************************************************/ @@ -4128,8 +4179,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/bif.tab b/erts/emulator/beam/bif.tab index 987008c937..8cc568b16c 100644 --- a/erts/emulator/beam/bif.tab +++ b/erts/emulator/beam/bif.tab @@ -806,6 +806,12 @@ bif file:native_name_encoding/0 # bif erlang:check_old_code/1 + +# +# New in R15B +# +bif erlang:universaltime_to_posixtime/1 +bif erlang:posixtime_to_universaltime/1 # # Obsolete # 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..bee61e7273 100644 --- a/erts/emulator/beam/dist.c +++ b/erts/emulator/beam/dist.c @@ -54,9 +54,9 @@ #endif #if defined(ERTS_DIST_MSG_DBG) || defined(ERTS_RAW_DIST_MSG_DBG) -static void bw(byte *buf, int sz) +static void bw(byte *buf, ErlDrvSizeT sz) { - bin_write(ERTS_PRINT_STDERR,NULL,buf,sz); + bin_write(ERTS_PRINT_STDERR, NULL, buf, sz); } #endif @@ -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; @@ -897,9 +897,9 @@ erts_dsig_send_group_leader(ErtsDSigData *dsdp, Eterm leader, Eterm remote) int erts_net_message(Port *prt, DistEntry *dep, byte *hbuf, - int hlen, + ErlDrvSizeT hlen, byte *buf, - int len) + ErlDrvSizeT len) { #define DIST_CTL_DEFAULT_SIZE 64 ErtsDistExternal ede; @@ -924,7 +924,7 @@ int erts_net_message(Port *prt, Uint tuple_arity; int res; #ifdef ERTS_DIST_MSG_DBG - int orig_len = len; + ErlDrvSizeT orig_len = len; #endif UseTmpHeapNoproc(DIST_CTL_DEFAULT_SIZE); @@ -940,7 +940,7 @@ int erts_net_message(Port *prt, UnUseTmpHeapNoproc(DIST_CTL_DEFAULT_SIZE); return 0; } - if (hlen > 0) + if (hlen != 0) goto data_error; if (len == 0) { /* HANDLE TICK !!! */ UnUseTmpHeapNoproc(DIST_CTL_DEFAULT_SIZE); diff --git a/erts/emulator/beam/erl_alloc.c b/erts/emulator/beam/erl_alloc.c index 140a84d5fc..1e75afe6f6 100644 --- a/erts/emulator/beam/erl_alloc.c +++ b/erts/emulator/beam/erl_alloc.c @@ -2877,8 +2877,9 @@ reply_alloc_info(void *vair) ainfo); ainfo = erts_bld_tuple(hpp, szp, 2, erts_bld_atom(hpp, szp, - "otps"), + "options"), ainfo); + ainfo = erts_bld_cons(hpp, szp,ainfo,NIL); } ainfo = erts_bld_tuple(hpp, szp, 3, alloc_atom, @@ -3117,10 +3118,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 +3135,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 +3182,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 +3223,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 +3260,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 +3286,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 +3303,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 +3545,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 +3562,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 +3590,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.c b/erts/emulator/beam/erl_alloc_util.c index af386c9197..c32938bdff 100644 --- a/erts/emulator/beam/erl_alloc_util.c +++ b/erts/emulator/beam/erl_alloc_util.c @@ -3014,9 +3014,7 @@ info_options(Allctr_t *allctr, add_2tup(hpp, szp, &res, am.low, allctr->mseg_opt.low_mem ? am_true : am_false); #endif add_2tup(hpp, szp, &res, am.ramv, allctr->ramv ? am_true : am_false); - add_2tup(hpp, szp, &res, am.t, (allctr->t - ? bld_uint(hpp, szp, (Uint) allctr->t) - : am_false)); + add_2tup(hpp, szp, &res, am.t, (allctr->t ? am_true : am_false)); add_2tup(hpp, szp, &res, am.e, am_true); } 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_async.c b/erts/emulator/beam/erl_async.c index 2dc7237f7c..8bca9ae582 100644 --- a/erts/emulator/beam/erl_async.c +++ b/erts/emulator/beam/erl_async.c @@ -304,8 +304,9 @@ static ERTS_INLINE ErtsAsync *async_get(ErtsThrQ_t *q, switch (erts_thr_q_inspect(q, 1)) { case ERTS_THR_Q_DIRTY: break; + case ERTS_THR_Q_NEED_THR_PRGR: #ifdef ERTS_SMP - case ERTS_THR_Q_NEED_THR_PRGR: { + { ErtsThrPrgrVal prgr = erts_thr_q_need_thr_progress(q); erts_thr_progress_wakeup(NULL, prgr); /* @@ -522,8 +523,8 @@ int erts_async_ready_clean(void *varq, void *val) switch (cstate) { case ERTS_THR_Q_DIRTY: return ERTS_ASYNC_READY_DIRTY; -#ifdef ERTS_SMP case ERTS_THR_Q_NEED_THR_PRGR: +#ifdef ERTS_SMP *((ErtsThrPrgrVal *) val) = erts_thr_q_need_thr_progress(&arq->thr_q); return ERTS_ASYNC_READY_NEED_THR_PRGR; diff --git a/erts/emulator/beam/erl_bif_ddll.c b/erts/emulator/beam/erl_bif_ddll.c index b2d5722e9b..37d540b41b 100644 --- a/erts/emulator/beam/erl_bif_ddll.c +++ b/erts/emulator/beam/erl_bif_ddll.c @@ -1580,24 +1580,6 @@ static int do_load_driver_entry(DE_Handle *dh, char *path, char *name) } switch (dp->extended_marker) { - case 0: - /* - * This may be an old driver that has been recompiled. If so, - * at least the fields that existed in extended driver version - * 1.0 should be zero. If not, a it is a bad driver. We cannot - * be completely certain that this is a valid driver but this is - * the best we can do with old drivers... - */ - if (dp->major_version != 0 - || dp->minor_version != 0 - || dp->driver_flags != 0 - || dp->handle2 != NULL - || dp->process_exit != NULL) { - /* Old driver; needs to be recompiled... */ - res = ERL_DE_LOAD_ERROR_INCORRECT_VERSION; - goto error; - } - break; case ERL_DRV_EXTENDED_MARKER: if (ERL_DRV_EXTENDED_MAJOR_VERSION != dp->major_version || ERL_DRV_EXTENDED_MINOR_VERSION < dp->minor_version) { 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..cd423eb200 100644 --- a/erts/emulator/beam/erl_bif_port.c +++ b/erts/emulator/beam/erl_bif_port.c @@ -254,13 +254,13 @@ port_call(Process* c_p, Eterm arg1, Eterm arg2, Eterm arg3) Uint size; byte *bytes; byte *endp; - size_t real_size; + ErlDrvSizeT real_size; erts_driver_t *drv; byte port_input[256]; /* Default input buffer to encode in */ byte port_result[256]; /* Buffer for result from port. */ byte* port_resp; /* Pointer to result buffer. */ char *prc; - int ret; + ErlDrvSSizeT ret; Eterm res; Sint result_size; Eterm *hp; @@ -366,9 +366,9 @@ port_call(Process* c_p, Eterm arg1, Eterm arg2, Eterm arg3) erts_smp_proc_lock(c_p, ERTS_PROC_LOCK_MAIN); #ifdef HARDDEBUG { - int z; - printf("real_size = %ld,%d, ret = %d\r\n",real_size, - (int) real_size, ret); + ErlDrvSizeT z; + printf("real_size = %ld,%d, ret = %ld,%d\r\n", (unsigned long) real_size, + (int) real_size, (unsigned long)ret, (int) ret); printf("["); for(z = 0; z < real_size; ++z) { printf("%d, ",(int) bytes[z]); @@ -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_debug.h b/erts/emulator/beam/erl_debug.h index bdfbaddbbf..c49354a2b3 100644 --- a/erts/emulator/beam/erl_debug.h +++ b/erts/emulator/beam/erl_debug.h @@ -1,7 +1,7 @@ /* * %CopyrightBegin% * - * Copyright Ericsson AB 2004-2010. All Rights Reserved. + * Copyright Ericsson AB 2004-2011. All Rights Reserved. * * The contents of this file are subject to the Erlang Public License, * Version 1.1, (the "License"); you may not use this file except in @@ -51,7 +51,7 @@ extern Uint32 verbose; -void upp(byte*, int); +void upp(byte*, size_t); void pat(Eterm); void pinfo(void); void pp(Process*); diff --git a/erts/emulator/beam/erl_driver.h b/erts/emulator/beam/erl_driver.h index ae0c9def90..e80eae0b86 100644 --- a/erts/emulator/beam/erl_driver.h +++ b/erts/emulator/beam/erl_driver.h @@ -85,6 +85,7 @@ #include "erl_drv_nif.h" #include <stdlib.h> +#include <string.h> /* ssize_t on Mac OS X */ #if defined(VXWORKS) # include <ioLib.h> @@ -134,8 +135,8 @@ typedef struct { #define DO_WRITE ERL_DRV_WRITE #define ERL_DRV_EXTENDED_MARKER (0xfeeeeeed) -#define ERL_DRV_EXTENDED_MAJOR_VERSION 1 -#define ERL_DRV_EXTENDED_MINOR_VERSION 5 +#define ERL_DRV_EXTENDED_MAJOR_VERSION 2 +#define ERL_DRV_EXTENDED_MINOR_VERSION 0 /* * The emulator will refuse to load a driver with different major @@ -160,10 +161,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; @@ -178,13 +184,21 @@ typedef long long ErlDrvSInt64; #error No 64-bit integer type #endif +#if defined(__WIN32__) +typedef ErlDrvUInt ErlDrvSizeT; +typedef ErlDrvSInt ErlDrvSSizeT; +#else +typedef size_t ErlDrvSizeT; +typedef ssize_t ErlDrvSSizeT; +#endif + /* * A binary as seen in a driver. Note that a binary should never be * altered by the driver when it has been sent to Erlang. */ 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; @@ -244,7 +258,7 @@ typedef struct { typedef struct erl_io_vec { int vsize; /* length of vectors */ - int size; /* total size in bytes */ + ErlDrvSizeT size; /* total size in bytes */ SysIOVec* iov; ErlDrvBinary** binv; } ErlIOVec; @@ -285,8 +299,8 @@ typedef struct erl_drv_entry { void (*stop)(ErlDrvData drv_data); /* called when port is closed, and when the emulator is halted. */ - void (*output)(ErlDrvData drv_data, char *buf, int len); - /* called when we have output from erlang to + void (*output)(ErlDrvData drv_data, char *buf, ErlDrvSizeT len); + /* called when we have output from erlang to the port */ void (*ready_input)(ErlDrvData drv_data, ErlDrvEvent event); /* called when we have input from one of @@ -299,10 +313,10 @@ typedef struct erl_drv_entry { void (*finish)(void); /* called before unloading the driver - DYNAMIC DRIVERS ONLY */ void *handle; /* Reserved -- Used by emulator internally */ - int (*control)(ErlDrvData drv_data, unsigned int command, char *buf, - int len, char **rbuf, int rlen); - /* "ioctl" for drivers - invoked by - port_control/3 */ + ErlDrvSSizeT (*control)(ErlDrvData drv_data, unsigned int command, + char *buf, ErlDrvSizeT len, char **rbuf, + ErlDrvSizeT rlen); /* "ioctl" for drivers - invoked by + port_control/3 */ void (*timeout)(ErlDrvData drv_data); /* Handling of timeout in driver */ void (*outputv)(ErlDrvData drv_data, ErlIOVec *ev); /* called when we have output from erlang @@ -313,10 +327,12 @@ typedef struct erl_drv_entry { closed, and there is data in the driver queue that needs to be flushed before 'stop' can be called */ - int (*call)(ErlDrvData drv_data, unsigned int command, char *buf, - int len, char **rbuf, int rlen, unsigned int *flags); - /* Works mostly like 'control', a synchronous - call into the driver. */ + ErlDrvSSizeT (*call)(ErlDrvData drv_data, + unsigned int command, char *buf, ErlDrvSizeT len, + char **rbuf, ErlDrvSizeT rlen, + unsigned int *flags); /* Works mostly like 'control', + a synchronous + call into the driver. */ void (*event)(ErlDrvData drv_data, ErlDrvEvent event, ErlDrvEventData event_data); /* Called when an event selected by @@ -368,14 +384,16 @@ typedef struct erl_drv_entry { EXTERN int driver_select(ErlDrvPort port, ErlDrvEvent event, int mode, int on); EXTERN int driver_event(ErlDrvPort port, ErlDrvEvent event, ErlDrvEventData event_data); -EXTERN int driver_output(ErlDrvPort port, char *buf, int len); -EXTERN int driver_output2(ErlDrvPort port, char *hbuf, int hlen, - char *buf, int len); -EXTERN int driver_output_binary(ErlDrvPort port, char *hbuf, int hlen, - ErlDrvBinary* bin, int offset, int len); -EXTERN int driver_outputv(ErlDrvPort port, char* hbuf, int hlen, ErlIOVec *ev, - int skip); -EXTERN int driver_vec_to_buf(ErlIOVec *ev, char *buf, int len); + +EXTERN int driver_output(ErlDrvPort port, char *buf, ErlDrvSizeT len); +EXTERN int driver_output2(ErlDrvPort port, char *hbuf, ErlDrvSizeT hlen, + char *buf, ErlDrvSizeT len); +EXTERN int driver_output_binary(ErlDrvPort port, char *hbuf, ErlDrvSizeT hlen, + ErlDrvBinary* bin, + ErlDrvSizeT offset, ErlDrvSizeT len); +EXTERN int driver_outputv(ErlDrvPort port, char* hbuf, ErlDrvSizeT hlen, + ErlIOVec *ev, ErlDrvSizeT skip); +EXTERN ErlDrvSizeT driver_vec_to_buf(ErlIOVec *ev, char *buf, ErlDrvSizeT len); EXTERN int driver_set_timer(ErlDrvPort port, unsigned long time); EXTERN int driver_cancel_timer(ErlDrvPort port); EXTERN int driver_read_timer(ErlDrvPort port, unsigned long *time_left); @@ -436,8 +454,8 @@ EXTERN int get_port_flags(ErlDrvPort port); * since the binary is a shared object it MUST be written once. */ -EXTERN ErlDrvBinary* driver_alloc_binary(int size); -EXTERN ErlDrvBinary* driver_realloc_binary(ErlDrvBinary *bin, int size); +EXTERN ErlDrvBinary* driver_alloc_binary(ErlDrvSizeT size); +EXTERN ErlDrvBinary* driver_realloc_binary(ErlDrvBinary *bin, ErlDrvSizeT size); EXTERN void driver_free_binary(ErlDrvBinary *bin); /* Referenc count on driver binaries */ @@ -446,24 +464,24 @@ EXTERN ErlDrvSInt driver_binary_inc_refc(ErlDrvBinary *dbp); EXTERN ErlDrvSInt driver_binary_dec_refc(ErlDrvBinary *dbp); /* Allocation interface */ -EXTERN void *driver_alloc(size_t size); -EXTERN void *driver_realloc(void *ptr, size_t size); +EXTERN void *driver_alloc(ErlDrvSizeT size); +EXTERN void *driver_realloc(void *ptr, ErlDrvSizeT size); EXTERN void driver_free(void *ptr); /* Queue interface */ -EXTERN int driver_enq(ErlDrvPort port, char* buf, int len); -EXTERN int driver_pushq(ErlDrvPort port, char* buf, int len); -EXTERN int driver_deq(ErlDrvPort port, int size); -EXTERN int driver_sizeq(ErlDrvPort port); -EXTERN int driver_enq_bin(ErlDrvPort port, ErlDrvBinary *bin, int offset, - int len); -EXTERN int driver_pushq_bin(ErlDrvPort port, ErlDrvBinary *bin, int offset, - int len); - -EXTERN int driver_peekqv(ErlDrvPort port, ErlIOVec *ev); +EXTERN int driver_enq(ErlDrvPort port, char* buf, ErlDrvSizeT len); +EXTERN int driver_pushq(ErlDrvPort port, char* buf, ErlDrvSizeT len); +EXTERN ErlDrvSizeT driver_deq(ErlDrvPort port, ErlDrvSizeT size); +EXTERN ErlDrvSizeT driver_sizeq(ErlDrvPort port); +EXTERN int driver_enq_bin(ErlDrvPort port, ErlDrvBinary *bin, ErlDrvSizeT offset, + ErlDrvSizeT len); +EXTERN int driver_pushq_bin(ErlDrvPort port, ErlDrvBinary *bin, ErlDrvSizeT offset, + ErlDrvSizeT len); + +EXTERN ErlDrvSizeT driver_peekqv(ErlDrvPort port, ErlIOVec *ev); EXTERN SysIOVec* driver_peekq(ErlDrvPort port, int *vlen); -EXTERN int driver_enqv(ErlDrvPort port, ErlIOVec *ev, int skip); -EXTERN int driver_pushqv(ErlDrvPort port, ErlIOVec *ev, int skip); +EXTERN int driver_enqv(ErlDrvPort port, ErlIOVec *ev, ErlDrvSizeT skip); +EXTERN int driver_pushqv(ErlDrvPort port, ErlIOVec *ev, ErlDrvSizeT skip); /* * Add and remove driver entries. 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..b8c6b64fc0 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; @@ -778,8 +769,8 @@ misc_aux_work_clean(ErtsThrQ_t *q, case ERTS_THR_Q_DIRTY: set_aux_work_flags(awdp->ssi, ERTS_SSI_AUX_WORK_MISC); return aux_work | ERTS_SSI_AUX_WORK_MISC; -#ifdef ERTS_SMP case ERTS_THR_Q_NEED_THR_PRGR: +#ifdef ERTS_SMP set_aux_work_flags(awdp->ssi, ERTS_SSI_AUX_WORK_MISC_THR_PRGR); erts_thr_progress_wakeup(awdp->esdp, erts_thr_q_need_thr_progress(q)); @@ -918,7 +909,7 @@ handle_async_ready_clean(ErtsAuxWorkData *awdp, #ifdef ERTS_SMP if (awdp->async_ready.need_thr_prgr - && !erts_thr_progress_has_reached(awdp->misc.thr_prgr)) { + && !erts_thr_progress_has_reached(awdp->async_ready.thr_prgr)) { return aux_work & ~ERTS_SSI_AUX_WORK_ASYNC_READY_CLEAN; } @@ -937,6 +928,7 @@ handle_async_ready_clean(ErtsAuxWorkData *awdp, erts_thr_progress_wakeup(awdp->esdp, awdp->async_ready.thr_prgr); awdp->async_ready.need_thr_prgr = 1; + return aux_work & ~ERTS_SSI_AUX_WORK_ASYNC_READY_CLEAN; #endif default: return aux_work; @@ -1724,21 +1716,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 +1980,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 +1995,13 @@ wake_scheduler(ErtsRunQueue *rq, int incq, int one) */ ERTS_SMP_LC_ASSERT(!erts_smp_lc_runq_is_locked(rq)); - sl = &rq->sleepers; - - 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); + ssi = rq->scheduler->ssi; - 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 +2094,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 +2142,7 @@ smp_notify_inc_runq(ErtsRunQueue *runq) { #ifdef ERTS_SMP if (runq) - wake_scheduler(runq, 1, 1); + wake_scheduler(runq, 1); #endif } @@ -2217,19 +2157,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 +2431,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 +2589,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 +3265,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 +3277,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 +3302,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 +3350,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 +3426,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 +3451,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 +3464,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 +3511,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 +3801,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 +3997,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 +4044,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 +4070,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 +4163,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 +4294,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 +4972,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 +5542,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 +5692,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 +6013,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 +6024,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 +6074,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 +6143,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 +6742,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 +8267,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_thr_progress.c b/erts/emulator/beam/erl_thr_progress.c index 9324bcde51..02f36fc75e 100644 --- a/erts/emulator/beam/erl_thr_progress.c +++ b/erts/emulator/beam/erl_thr_progress.c @@ -80,12 +80,12 @@ #ifdef ERTS_SMP -/* - * We use a 64-bit value for thread progress. By this wrapping of - * the thread progress will more or less never occur. - * - * On 32-bit systems we therefore need a double word atomic. - */ +#define ERTS_THR_PRGR_DBG_CHK_WAKEUP_REQUEST_VALUE 0 + +#ifdef DEBUG +#undef ERTS_THR_PRGR_DBG_CHK_WAKEUP_REQUEST_VALUE +#define ERTS_THR_PRGR_DBG_CHK_WAKEUP_REQUEST_VALUE 1 +#endif #define ERTS_THR_PRGR_PRINT_LEADER 0 #define ERTS_THR_PRGR_PRINT_VAL 0 @@ -106,6 +106,13 @@ |ERTS_THR_PRGR_LFLG_ACTIVE_MASK)) \ == ERTS_THR_PRGR_LFLG_NO_LEADER) +/* + * We use a 64-bit value for thread progress. By this wrapping of + * the thread progress will more or less never occur. + * + * On 32-bit systems we therefore need a double word atomic. + */ + #define read_acqb erts_thr_prgr_read_acqb__ #ifdef ARCH_64 @@ -937,8 +944,10 @@ request_wakeup_managed(ErtsThrPrgrData *tpd, ErtsThrPrgrVal value) ASSERT(tpd->is_managed); ASSERT(tpd->previous.local != ERTS_THR_PRGR_VAL_WAITING); - if (has_reached_wakeup(value)) + if (has_reached_wakeup(value)) { wakeup_managed(tpd->id); + return; + } wix = ERTS_THR_PRGR_WAKEUP_IX(value); if (tpd->wakeup_request[wix] == value) @@ -976,6 +985,10 @@ request_wakeup_managed(ErtsThrPrgrData *tpd, ErtsThrPrgrVal value) mwd = intrnl->managed.data[wix]; ix = erts_atomic32_inc_read_nob(&mwd->len) - 1; +#if ERTS_THR_PRGR_DBG_CHK_WAKEUP_REQUEST_VALUE + if (ix >= intrnl->managed.no) + erl_exit(ERTS_ABORT_EXIT, "Internal error: Too many wakeup requests\n"); +#endif mwd->id[ix] = tpd->id; ASSERT(!erts_thr_progress_has_reached(value)); @@ -1001,8 +1014,10 @@ request_wakeup_unmanaged(ErtsThrPrgrData *tpd, ErtsThrPrgrVal value) * we are writing the request. */ - if (has_reached_wakeup(value)) + if (has_reached_wakeup(value)) { wakeup_unmanaged(tpd->id); + return; + } wix = ERTS_THR_PRGR_WAKEUP_IX(value); diff --git a/erts/emulator/beam/erl_thr_queue.c b/erts/emulator/beam/erl_thr_queue.c index 9ac4cd4b8e..efb8c635d7 100644 --- a/erts/emulator/beam/erl_thr_queue.c +++ b/erts/emulator/beam/erl_thr_queue.c @@ -449,32 +449,44 @@ clean(ErtsThrQ_t *q, int max_ops, int do_notify) if (inext == (erts_aint_t) &q->tail.data.marker) { q->head.head.ptr->next.ptr = &q->tail.data.marker; q->head.head.ptr = &q->tail.data.marker; -#ifdef ERTS_SMP - if (!q->head.next.thr_progress_reached) - return ERTS_THR_Q_NEED_THR_PRGR; -#else - if (do_notify) - q->head.notify(q->head.arg); -#endif - return ERTS_THR_Q_DIRTY; + goto check_thr_progress; } } } + + if (q->q.finalizing) { + ilast = erts_atomic_read_nob(&q->tail.data.last); + if (q->head.first == ((ErtsThrQElement_t *) ilast) + && ((ErtsThrQElement_t *) ilast) == &q->tail.data.marker + && q->head.first == &q->tail.data.marker) { + destroy(q); + } + else { + goto dirty; + } + } return ERTS_THR_Q_CLEAN; } - if (q->head.first != q->head.unref_end) { - if (do_notify) - q->head.notify(q->head.arg); - return ERTS_THR_Q_DIRTY; - } + if (q->head.first != q->head.unref_end) + goto dirty; + +check_thr_progress: #ifdef ERTS_SMP - if (!q->head.next.thr_progress_reached) - return ERTS_THR_Q_NEED_THR_PRGR; + if (q->head.next.thr_progress_reached) #endif + { + int um_refc_ix = q->head.next.um_refc_ix; + if (erts_atomic_read_acqb(&q->tail.data.um_refc[um_refc_ix]) == 0) { + dirty: + if (do_notify) + q->head.notify(q->head.arg); + return ERTS_THR_Q_DIRTY; + } + } - return ERTS_THR_Q_CLEAN; /* Waiting for unmanaged threads to complete... */ + return ERTS_THR_Q_NEED_THR_PRGR; } #endif @@ -492,7 +504,9 @@ erts_thr_q_clean(ErtsThrQ_t *q) ErtsThrQCleanState_t erts_thr_q_inspect(ErtsThrQ_t *q, int ensure_empty) { -#ifdef USE_THREADS +#ifndef USE_THREADS + return ERTS_THR_Q_CLEAN; +#else if (ensure_empty) { erts_aint_t inext; inext = erts_atomic_read_acqb(&q->head.head.ptr->next.atmc); @@ -523,11 +537,15 @@ erts_thr_q_inspect(ErtsThrQ_t *q, int ensure_empty) return ERTS_THR_Q_DIRTY; #ifdef ERTS_SMP - if (!q->head.next.thr_progress_reached) - return ERTS_THR_Q_NEED_THR_PRGR; + if (q->head.next.thr_progress_reached) #endif + { + int um_refc_ix = q->head.next.um_refc_ix; + if (erts_atomic_read_acqb(&q->tail.data.um_refc[um_refc_ix]) == 0) + return ERTS_THR_Q_DIRTY; + } + return ERTS_THR_Q_NEED_THR_PRGR; #endif - return ERTS_THR_Q_CLEAN; } static void diff --git a/erts/emulator/beam/erl_thr_queue.h b/erts/emulator/beam/erl_thr_queue.h index 407c23f5eb..edcf2c3823 100644 --- a/erts/emulator/beam/erl_thr_queue.h +++ b/erts/emulator/beam/erl_thr_queue.h @@ -96,9 +96,7 @@ typedef struct { typedef enum { ERTS_THR_Q_CLEAN, -#ifdef ERTS_SMP ERTS_THR_Q_NEED_THR_PRGR, -#endif ERTS_THR_Q_DIRTY, } ErtsThrQCleanState_t; 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..f782e2f0b1 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); @@ -491,7 +494,7 @@ get_time(int *hour, int *minute, int *second) the_clock = time((time_t *)0); #ifdef HAVE_LOCALTIME_R - localtime_r(&the_clock, (tm = &tmbuf)); + tm = localtime_r(&the_clock, &tmbuf); #else tm = localtime(&the_clock); #endif @@ -513,7 +516,7 @@ get_date(int *year, int *month, int *day) the_clock = time((time_t *)0); #ifdef HAVE_LOCALTIME_R - localtime_r(&the_clock, (tm = &tmbuf)); + tm = localtime_r(&the_clock, &tmbuf); #else tm = localtime(&the_clock); #endif @@ -583,7 +586,44 @@ static const int mdays[14] = {0, 31, 28, 31, 30, 31, 30, (((y) % 100) != 0)) || \ (((y) % 400) == 0)) -#define BASEYEAR 1970 +/* This is the earliest year we are sure to be able to handle + on all platforms w/o problems */ +#define BASEYEAR 1902 + +/* A more "clever" mktime + * return 1, if successful + * return -1, if not successful + */ + +static int erl_mktime(time_t *c, struct tm *tm) { + time_t clock; + + clock = mktime(tm); + + if (clock != -1) { + *c = clock; + return 1; + } + + /* in rare occasions mktime returns -1 + * when a correct value has been entered + * + * decrease seconds with one second + * if the result is -2, epochs should be -1 + */ + + tm->tm_sec = tm->tm_sec - 1; + clock = mktime(tm); + tm->tm_sec = tm->tm_sec + 1; + + *c = -1; + + if (clock == -2) { + return 1; + } + + return -1; +} /* * gregday @@ -592,10 +632,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; + Sint ndays = 0; + Sint gyear, pyear, m; /* number of days in previous years */ gyear = year - 1600; @@ -610,10 +650,72 @@ static int long gregday(int year, int month, int day) if (is_leap_year(year) && (month > 2)) ndays++; ndays += day - 1; - return ndays - 135140; /* 135140 = Jan 1, 1970 */ + return (time_t) (ndays - 135140); /* 135140 = Jan 1, 1970 */ +} + +#define SECONDS_PER_MINUTE (60) +#define SECONDS_PER_HOUR (60 * SECONDS_PER_MINUTE) +#define SECONDS_PER_DAY (24 * SECONDS_PER_HOUR) + +int seconds_to_univ(Sint64 time, Sint *year, Sint *month, Sint *day, + Sint *hour, Sint *minute, Sint *second) { + + Sint y,mi; + Sint days = time / SECONDS_PER_DAY; + Sint secs = time % SECONDS_PER_DAY; + Sint tmp; + + if (secs < 0) { + days--; + secs += SECONDS_PER_DAY; + } + + tmp = secs % SECONDS_PER_HOUR; + + *hour = secs / SECONDS_PER_HOUR; + *minute = tmp / SECONDS_PER_MINUTE; + *second = tmp % SECONDS_PER_MINUTE; + + days += 719468; + y = (10000*((Sint64)days) + 14780) / 3652425; + tmp = days - (365 * y + y/4 - y/100 + y/400); + + if (tmp < 0) { + y--; + tmp = days - (365*y + y/4 - y/100 + y/400); + } + mi = (100 * tmp + 52)/3060; + *month = (mi + 2) % 12 + 1; + *year = y + (mi + 2) / 12; + *day = tmp - (mi * 306 + 5)/10 + 1; + + return 1; } +int univ_to_seconds(Sint year, Sint month, Sint day, Sint hour, Sint minute, Sint second, Sint64 *time) { + Sint days; + + if (!(IN_RANGE(1600, year, INT_MAX - 1) && + IN_RANGE(1, month, 12) && + IN_RANGE(1, day, (mdays[month] + + (month == 2 + && (year % 4 == 0) + && (year % 100 != 0 || year % 400 == 0)))) && + IN_RANGE(0, hour, 23) && + IN_RANGE(0, minute, 59) && + IN_RANGE(0, second, 59))) { + return 0; + } + + days = gregday(year, month, day); + *time = SECONDS_PER_DAY; + *time *= days; /* don't try overflow it, it hurts */ + *time += SECONDS_PER_HOUR * hour; + *time += SECONDS_PER_MINUTE * minute; + *time += second; + return 1; +} int local_to_univ(Sint *year, Sint *month, Sint *day, @@ -644,15 +746,18 @@ local_to_univ(Sint *year, Sint *month, Sint *day, t.tm_min = *minute; t.tm_sec = *second; t.tm_isdst = isdst; - the_clock = mktime(&t); - if (the_clock == -1) { + + /* the nature of mktime makes this a bit interesting, + * up to four mktime calls could happen here + */ + + if (erl_mktime(&the_clock, &t) < 0) { if (isdst) { /* If this is a timezone without DST and the OS (correctly) refuses to give us a DST time, we simulate the Linux/Solaris behaviour of giving the same data as if is_dst was not set. */ t.tm_isdst = 0; - the_clock = mktime(&t); - if (the_clock == -1) { + if (erl_mktime(&the_clock, &t)) { /* Failed anyway, something else is bad - will be a badarg */ return 0; } @@ -662,10 +767,13 @@ local_to_univ(Sint *year, Sint *month, Sint *day, } } #ifdef HAVE_GMTIME_R - gmtime_r(&the_clock, (tm = &tmbuf)); + tm = gmtime_r(&the_clock, &tmbuf); #else tm = gmtime(&the_clock); #endif + if (!tm) { + return 0; + } *year = tm->tm_year + 1900; *month = tm->tm_mon +1; *day = tm->tm_mday; @@ -719,17 +827,20 @@ univ_to_local(Sint *year, Sint *month, Sint *day, #endif #ifdef HAVE_LOCALTIME_R - localtime_r(&the_clock, (tm = &tmbuf)); + tm = localtime_r(&the_clock, &tmbuf); #else tm = localtime(&the_clock); #endif - *year = tm->tm_year + 1900; - *month = tm->tm_mon +1; - *day = tm->tm_mday; - *hour = tm->tm_hour; - *minute = tm->tm_min; - *second = tm->tm_sec; - return 1; + if (tm) { + *year = tm->tm_year + 1900; + *month = tm->tm_mon +1; + *day = tm->tm_mday; + *hour = tm->tm_hour; + *minute = tm->tm_min; + *second = tm->tm_sec; + return 1; + } + return 0; } @@ -798,13 +909,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 +951,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..f1335f600d 100644 --- a/erts/emulator/beam/global.h +++ b/erts/emulator/beam/global.h @@ -47,7 +47,7 @@ typedef struct erts_driver_t_ erts_driver_t; #define SMALL_IO_QUEUE 5 /* Number of fixed elements */ typedef struct { - int size; /* total size in bytes */ + ErlDrvSizeT size; /* total size in bytes */ SysIOVec* v_start; SysIOVec* v_end; @@ -63,9 +63,9 @@ typedef struct { } ErlIOQueue; typedef struct line_buf { /* Buffer used in line oriented I/O */ - int bufsiz; /* Size of character buffer */ - int ovlen; /* Length of overflow data */ - int ovsiz; /* Actual size of overflow buffer */ + ErlDrvSizeT bufsiz; /* Size of character buffer */ + ErlDrvSizeT ovlen; /* Length of overflow data */ + ErlDrvSizeT ovsiz; /* Actual size of overflow buffer */ char data[1]; /* Starting point of buffer data, data[0] is a flag indicating an unprocess CR, The rest is the overflow buffer. */ @@ -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 } @@ -323,12 +323,15 @@ struct erts_driver_t_ { void (*stop)(ErlDrvData drv_data); void (*finish)(void); void (*flush)(ErlDrvData drv_data); - void (*output)(ErlDrvData drv_data, char *buf, int len); + void (*output)(ErlDrvData drv_data, char *buf, ErlDrvSizeT len); void (*outputv)(ErlDrvData drv_data, ErlIOVec *ev); /* Might be NULL */ - int (*control)(ErlDrvData drv_data, unsigned int command, char *buf, - int len, char **rbuf, int rlen); /* Might be NULL */ - int (*call)(ErlDrvData drv_data, unsigned int command, char *buf, - int len, char **rbuf, int rlen, unsigned int *flags); /* Might be NULL */ + ErlDrvSSizeT (*control)(ErlDrvData drv_data, unsigned int command, + char *buf, ErlDrvSizeT len, + char **rbuf, ErlDrvSizeT rlen); /* Might be NULL */ + ErlDrvSSizeT (*call)(ErlDrvData drv_data, unsigned int command, + char *buf, ErlDrvSizeT len, + char **rbuf, ErlDrvSizeT rlen, /* Might be NULL */ + unsigned int *flags); void (*event)(ErlDrvData drv_data, ErlDrvEvent event, ErlDrvEventData event_data); void (*ready_input)(ErlDrvData drv_data, ErlDrvEvent event); @@ -398,7 +401,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 +410,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; @@ -1053,7 +1056,8 @@ extern int erts_do_net_exits(DistEntry*, Eterm); extern int distribution_info(int, void *); extern int is_node_name_atom(Eterm a); -extern int erts_net_message(Port *, DistEntry *, byte *, int, byte *, int); +extern int erts_net_message(Port *, DistEntry *, + byte *, ErlDrvSizeT, byte *, ErlDrvSizeT); extern void init_dist(void); extern int stop_dist(void); @@ -1661,7 +1665,7 @@ do { \ #define ERTS_SMP_CHK_PEND_TRACE_MSGS(ESDP) #endif -void bin_write(int, void*, byte*, int); +void bin_write(int, void*, byte*, size_t); int intlist_to_buf(Eterm, char*, int); /* most callers pass plain char*'s */ struct Sint_buf { @@ -1677,7 +1681,7 @@ char* Sint_to_buf(Sint, struct Sint_buf*); #define ERTS_IOLIST_OVERFLOW 1 #define ERTS_IOLIST_TYPE 2 -Eterm buf_to_intlist(Eterm**, char*, int, Eterm); /* most callers pass plain char*'s */ +Eterm buf_to_intlist(Eterm**, char*, size_t, Eterm); /* most callers pass plain char*'s */ int io_list_to_buf(Eterm, char*, int); int io_list_to_buf2(Eterm, char*, int); int erts_iolist_size(Eterm, Uint *); diff --git a/erts/emulator/beam/io.c b/erts/emulator/beam/io.c index 132dc78515..49cd0e5f53 100644 --- a/erts/emulator/beam/io.c +++ b/erts/emulator/beam/io.c @@ -164,8 +164,8 @@ erts_port_ioq_size(Port *pp) typedef struct line_buf_context { LineBuf **b; char *buf; - int left; - int retlen; + ErlDrvSizeT left; + ErlDrvSizeT retlen; } LineBufContext; #define LINEBUF_EMPTY 0 @@ -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; } @@ -829,13 +828,13 @@ io_list_to_vec(Eterm obj, /* io-list */ SysIOVec* iov, /* io vector */ ErlDrvBinary** binv, /* binary reference vector */ ErlDrvBinary* cbin, /* binary to store characters */ - int bin_limit) /* small binaries limit */ + ErlDrvSizeT bin_limit) /* small binaries limit */ { DECLARE_ESTACK(s); Eterm* objp; char *buf = cbin->orig_bytes; - int len = cbin->orig_size; - int csize = 0; + ErlDrvSizeT len = cbin->orig_size; + ErlDrvSizeT csize = 0; int vlen = 0; char* cptr = buf; @@ -875,7 +874,7 @@ io_list_to_vec(Eterm obj, /* io-list */ Eterm real_bin; Uint offset; Eterm* bptr; - int size; + ErlDrvSizeT size; int bitoffs; int bitsize; @@ -950,7 +949,7 @@ io_list_to_vec(Eterm obj, /* io-list */ #define IO_LIST_VEC_COUNT(obj) \ do { \ - int _size = binary_size(obj); \ + ErlDrvSizeT _size = binary_size(obj); \ Eterm _real; \ ERTS_DECLARE_DUMMY(Uint _offset); \ int _bitoffs; \ @@ -1105,7 +1104,7 @@ int erts_write_to_port(Eterm caller_id, Port *p, Eterm list) Uint csize; Uint pvsize; Uint pcsize; - int blimit; + ErlDrvSizeT blimit; SysIOVec iv[SMALL_WRITE_VEC]; ErlDrvBinary* bv[SMALL_WRITE_VEC]; SysIOVec* ivp; @@ -1361,7 +1360,8 @@ int bufsiz; * buf - A buffer containing the data to be read and split to lines. * len - The number of bytes in buf. */ -static int init_linebuf_context(LineBufContext *lc, LineBuf **lb, char *buf, int len) +static int init_linebuf_context(LineBufContext *lc, LineBuf **lb, + char *buf, ErlDrvSizeT len) { if(lc == NULL || lb == NULL) return -1; @@ -1530,10 +1530,10 @@ deliver_result(Eterm sender, Eterm pid, Eterm res) */ static void deliver_read_message(Port* prt, Eterm to, - char *hbuf, int hlen, - char *buf, int len, int eol) + char *hbuf, ErlDrvSizeT hlen, + char *buf, ErlDrvSizeT len, int eol) { - int need; + ErlDrvSizeT need; Eterm listp; Eterm tuple; Process* rp; @@ -1613,8 +1613,8 @@ static void deliver_read_message(Port* prt, Eterm to, * deliver_read_message, and takes the same parameters. */ static void deliver_linebuf_message(Port* prt, Eterm to, - char* hbuf, int hlen, - char *buf, int len) + char* hbuf, ErlDrvSizeT hlen, + char *buf, ErlDrvSizeT len) { LineBufContext lc; int ret; @@ -1657,14 +1657,14 @@ static void deliver_vec_message(Port* prt, /* Port */ Eterm to, /* Receiving pid */ char* hbuf, /* "Header" buffer... */ - int hlen, /* ... and its length */ + ErlDrvSizeT hlen, /* ... and its length */ ErlDrvBinary** binv, /* Vector of binaries */ SysIOVec* iov, /* I/O vector */ int vsize, /* Size of binv & iov */ - int csize) /* Size of characters in + ErlDrvSizeT csize) /* Size of characters in iov (not hlen) */ { - int need; + ErlDrvSizeT need; Eterm listp; Eterm tuple; Process* rp; @@ -1745,7 +1745,7 @@ deliver_vec_message(Port* prt, /* Port */ } } - if (hlen > 0) { /* Prepend the header */ + if (hlen != 0) { /* Prepend the header */ Eterm* thp = hp; listp = buf_to_intlist(&thp, hbuf, hlen, listp); hp = thp; @@ -1765,10 +1765,10 @@ deliver_vec_message(Port* prt, /* Port */ static void deliver_bin_message(Port* prt, /* port */ Eterm to, /* receiving pid */ char* hbuf, /* "header" buffer */ - int hlen, /* and it's length */ + ErlDrvSizeT hlen, /* and it's length */ ErlDrvBinary* bin, /* binary data */ - int offs, /* offset into binary */ - int len) /* length of binary */ + ErlDrvSizeT offs, /* offset into binary */ + ErlDrvSizeT len) /* length of binary */ { SysIOVec vec; @@ -2156,8 +2156,9 @@ erts_port_control(Process* p, Port* prt, Uint command, Eterm iolist) int must_free = 0; /* True if the buffer should be freed. */ char port_result[ERL_ONHEAP_BIN_LIMIT]; /* Default buffer for result from port. */ char* port_resp; /* Pointer to result buffer. */ - int n; - int (*control)(ErlDrvData, unsigned, char*, int, char**, int); + ErlDrvSSizeT n; + ErlDrvSSizeT (*control) + (ErlDrvData, unsigned, char*, ErlDrvSizeT, char**, ErlDrvSizeT); int fpe_was_unmasked; ERTS_SMP_LC_ASSERT(erts_lc_is_port_locked(prt)); @@ -3083,7 +3084,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; @@ -3240,8 +3241,8 @@ driver_send_term(ErlDrvPort ix, ErlDrvTermData to, ErlDrvTermData* data, int len * and data is len length of bin starting from offset offs. */ -int driver_output_binary(ErlDrvPort ix, char* hbuf, int hlen, - ErlDrvBinary* bin, int offs, int len) +int driver_output_binary(ErlDrvPort ix, char* hbuf, ErlDrvSizeT hlen, + ErlDrvBinary* bin, ErlDrvSizeT offs, ErlDrvSizeT len) { Port* prt = erts_drvport2port(ix); @@ -3274,7 +3275,8 @@ int driver_output_binary(ErlDrvPort ix, char* hbuf, int hlen, ** Example: if hlen = 3 then the port owner will receive the data ** [H1,H2,H3 | T] */ -int driver_output2(ErlDrvPort ix, char* hbuf, int hlen, char* buf, int len) +int driver_output2(ErlDrvPort ix, char* hbuf, ErlDrvSizeT hlen, + char* buf, ErlDrvSizeT len) { Port* prt = erts_drvport2port(ix); @@ -3311,27 +3313,29 @@ int driver_output2(ErlDrvPort ix, char* hbuf, int hlen, char* buf, int len) /* Interface functions available to driver writers */ -int driver_output(ErlDrvPort ix, char* buf, int len) +int driver_output(ErlDrvPort ix, char* buf, ErlDrvSizeT len) { ERTS_SMP_CHK_NO_PROC_LOCKS; return driver_output2(ix, NULL, 0, buf, len); } -int driver_outputv(ErlDrvPort ix, char* hbuf, int hlen, ErlIOVec* vec, int skip) +int driver_outputv(ErlDrvPort ix, char* hbuf, ErlDrvSizeT hlen, + ErlIOVec* vec, ErlDrvSizeT skip) { int n; - int len; - int size; + ErlDrvSizeT len; + ErlDrvSizeT size; SysIOVec* iov; ErlDrvBinary** binv; Port* prt; ERTS_SMP_CHK_NO_PROC_LOCKS; - size = vec->size - skip; /* Size of remaining bytes in vector */ - ASSERT(size >= 0); - if (size <= 0) + ASSERT(vec->size >= skip); + if (vec->size <= skip) return driver_output2(ix, hbuf, hlen, NULL, 0); + size = vec->size - skip; /* Size of remaining bytes in vector */ + ASSERT(hlen >= 0); /* debug only */ if (hlen < 0) hlen = 0; @@ -3375,17 +3379,14 @@ int driver_outputv(ErlDrvPort ix, char* hbuf, int hlen, ErlIOVec* vec, int skip) ** input is a vector a buffer and a max length ** return bytes copied */ -int driver_vec_to_buf(vec, buf, len) -ErlIOVec* vec; -char* buf; -int len; +ErlDrvSizeT driver_vec_to_buf(ErlIOVec *vec, char *buf, ErlDrvSizeT len) { SysIOVec* iov = vec->iov; int n = vec->vsize; - int orig_len = len; + ErlDrvSizeT orig_len = len; while(n--) { - int ilen = iov->iov_len; + size_t ilen = iov->iov_len; if (ilen < len) { sys_memcpy(buf, iov->iov_base, ilen); len -= ilen; @@ -3437,43 +3438,34 @@ driver_binary_dec_refc(ErlDrvBinary *dbp) */ ErlDrvBinary* -driver_alloc_binary(int size) +driver_alloc_binary(ErlDrvSizeT size) { Binary* bin; - if (size < 0) - return NULL; - bin = erts_bin_drv_alloc_fnf((Uint) size); if (!bin) 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); } /* Reallocate space hold by binary */ -ErlDrvBinary* driver_realloc_binary(ErlDrvBinary* bin, int size) +ErlDrvBinary* driver_realloc_binary(ErlDrvBinary* bin, ErlDrvSizeT size) { Binary* oldbin; Binary* newbin; - if (!bin || size < 0) { + if (!bin) { erts_dsprintf_buf_t *dsbufp = erts_create_logger_dsbuf(); erts_dsprintf(dsbufp, - "Bad use of driver_realloc_binary(%p, %d): " + "Bad use of driver_realloc_binary(%p, %lu): " "called with ", - bin, size); + bin, (unsigned long)size); if (!bin) { erts_dsprintf(dsbufp, "NULL pointer as first argument"); - if (size < 0) - erts_dsprintf(dsbufp, ", and "); - } - if (size < 0) { - erts_dsprintf(dsbufp, "negative size as second argument"); - size = 0; } erts_send_warning_to_logger_nogl(dsbufp); if (!bin) @@ -3513,12 +3505,12 @@ ErlDrvBinary* dbin; * Allocation/deallocation of memory for drivers */ -void *driver_alloc(size_t size) +void *driver_alloc(ErlDrvSizeT size) { return erts_alloc_fnf(ERTS_ALC_T_DRV, (Uint) size); } -void *driver_realloc(void *ptr, size_t size) +void *driver_realloc(void *ptr, ErlDrvSizeT size) { return erts_realloc_fnf(ERTS_ALC_T_DRV, ptr, (Uint) size); } @@ -3780,11 +3772,11 @@ static int expandq(ErlIOQueue* q, int n, int tail) /* Put elements from vec at q tail */ -int driver_enqv(ErlDrvPort ix, ErlIOVec* vec, int skip) +int driver_enqv(ErlDrvPort ix, ErlIOVec* vec, ErlDrvSizeT skip) { int n; - int len; - int size; + size_t len; + ErlDrvSizeT size; SysIOVec* iov; ErlDrvBinary** binv; ErlDrvBinary* b; @@ -3793,10 +3785,10 @@ int driver_enqv(ErlDrvPort ix, ErlIOVec* vec, int skip) if (q == NULL) return -1; - size = vec->size - skip; - ASSERT(size >= 0); /* debug only */ - if (size <= 0) + ASSERT(vec->size >= skip); /* debug only */ + if (vec->size <= skip) return 0; + size = vec->size - skip; iov = vec->iov; binv = vec->binv; @@ -3846,11 +3838,11 @@ int driver_enqv(ErlDrvPort ix, ErlIOVec* vec, int skip) } /* Put elements from vec at q head */ -int driver_pushqv(ErlDrvPort ix, ErlIOVec* vec, int skip) +int driver_pushqv(ErlDrvPort ix, ErlIOVec* vec, ErlDrvSizeT skip) { int n; - int len; - int size; + size_t len; + ErlDrvSizeT size; SysIOVec* iov; ErlDrvBinary** binv; ErlDrvBinary* b; @@ -3859,8 +3851,10 @@ int driver_pushqv(ErlDrvPort ix, ErlIOVec* vec, int skip) if (q == NULL) return -1; - if ((size = vec->size - skip) <= 0) + if (vec->size <= skip) return 0; + size = vec->size - skip; + iov = vec->iov; binv = vec->binv; n = vec->vsize; @@ -3915,15 +3909,14 @@ int driver_pushqv(ErlDrvPort ix, ErlIOVec* vec, int skip) ** Remove size bytes from queue head ** Return number of bytes that remain in queue */ -int driver_deq(ErlDrvPort ix, int size) +ErlDrvSizeT driver_deq(ErlDrvPort ix, ErlDrvSizeT size) { ErlIOQueue* q = drvport2ioq(ix); int len; - int sz; - if ((q == NULL) || (sz = (q->size - size)) < 0) + if ((q == NULL) || (q->size < size)) return -1; - q->size = sz; + q->size -= size; while (size > 0) { ASSERT(q->v_head != q->v_tail); @@ -3946,16 +3939,16 @@ int driver_deq(ErlDrvPort ix, int size) q->v_head = q->v_tail = q->v_start; q->b_head = q->b_tail = q->b_start; } - return sz; + return q->size; } -int driver_peekqv(ErlDrvPort ix, ErlIOVec *ev) { +ErlDrvSizeT driver_peekqv(ErlDrvPort ix, ErlIOVec *ev) { ErlIOQueue *q = drvport2ioq(ix); ASSERT(ev); if (! q) { - return -1; + return (ErlDrvSizeT) -1; } else { if ((ev->vsize = q->v_tail - q->v_head) == 0) { ev->size = 0; @@ -3984,12 +3977,12 @@ SysIOVec* driver_peekq(ErlDrvPort ix, int* vlenp) /* length of io-vector */ } -int driver_sizeq(ErlDrvPort ix) +ErlDrvSizeT driver_sizeq(ErlDrvPort ix) { ErlIOQueue* q = drvport2ioq(ix); if (q == NULL) - return -1; + return (size_t) -1; return q->size; } @@ -3997,7 +3990,8 @@ int driver_sizeq(ErlDrvPort ix) /* Utils */ /* Enqueue a binary */ -int driver_enq_bin(ErlDrvPort ix, ErlDrvBinary* bin, int offs, int len) +int driver_enq_bin(ErlDrvPort ix, ErlDrvBinary* bin, + ErlDrvSizeT offs, ErlDrvSizeT len) { SysIOVec iov; ErlIOVec ev; @@ -4014,7 +4008,7 @@ int driver_enq_bin(ErlDrvPort ix, ErlDrvBinary* bin, int offs, int len) return driver_enqv(ix, &ev, 0); } -int driver_enq(ErlDrvPort ix, char* buffer, int len) +int driver_enq(ErlDrvPort ix, char* buffer, ErlDrvSizeT len) { int code; ErlDrvBinary* bin; @@ -4030,7 +4024,8 @@ int driver_enq(ErlDrvPort ix, char* buffer, int len) return code; } -int driver_pushq_bin(ErlDrvPort ix, ErlDrvBinary* bin, int offs, int len) +int driver_pushq_bin(ErlDrvPort ix, ErlDrvBinary* bin, + ErlDrvSizeT offs, ErlDrvSizeT len) { SysIOVec iov; ErlIOVec ev; @@ -4047,7 +4042,7 @@ int driver_pushq_bin(ErlDrvPort ix, ErlDrvBinary* bin, int offs, int len) return driver_pushqv(ix, &ev, 0); } -int driver_pushq(ErlDrvPort ix, char* buffer, int len) +int driver_pushq(ErlDrvPort ix, char* buffer, ErlDrvSizeT len) { int code; ErlDrvBinary* bin; @@ -4076,7 +4071,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); @@ -4768,7 +4763,7 @@ get_current_port(void) */ static void -no_output_callback(ErlDrvData drv_data, char *buf, int len) +no_output_callback(ErlDrvData drv_data, char *buf, ErlDrvSizeT len) { } @@ -4819,16 +4814,11 @@ static int init_driver(erts_driver_t *drv, ErlDrvEntry *de, DE_Handle *handle) { drv->name = de->driver_name; - if (de->extended_marker == ERL_DRV_EXTENDED_MARKER) { - drv->version.major = de->major_version; - drv->version.minor = de->minor_version; - drv->flags = de->driver_flags; - } - else { - drv->version.major = 0; - drv->version.minor = 0; - drv->flags = 0; - } + ASSERT(de->extended_marker == ERL_DRV_EXTENDED_MARKER); + ASSERT(de->major_version >= 2); + drv->version.major = de->major_version; + drv->version.minor = de->minor_version; + drv->flags = de->driver_flags; drv->handle = handle; #ifdef ERTS_SMP if (drv->flags & ERL_DRV_FLAG_USE_PORT_LOCKING) @@ -4861,11 +4851,8 @@ init_driver(erts_driver_t *drv, ErlDrvEntry *de, DE_Handle *handle) drv->ready_output = de->ready_output ? de->ready_output : no_ready_output_callback; drv->timeout = de->timeout ? de->timeout : no_timeout_callback; drv->ready_async = de->ready_async; - if (de->extended_marker == ERL_DRV_EXTENDED_MARKER) - drv->process_exit = de->process_exit; - else - drv->process_exit = NULL; - if (de->minor_version >= 3/*R13A*/ && de->stop_select) + drv->process_exit = de->process_exit; + if (de->stop_select) drv->stop_select = de->stop_select; else drv->stop_select = no_stop_select_callback; diff --git a/erts/emulator/beam/packet_parser.c b/erts/emulator/beam/packet_parser.c index a66d60aa22..4d4b6ea196 100644 --- a/erts/emulator/beam/packet_parser.c +++ b/erts/emulator/beam/packet_parser.c @@ -301,7 +301,11 @@ int packet_get_length(enum PacketParseType htype, /* TCP_PB_LINE_LF: [Data ... \n] */ const char* ptr2; if ((ptr2 = memchr(ptr, '\n', n)) == NULL) { - if (n >= trunc_len && trunc_len!=0) { /* buffer full */ + if (n > max_plen && max_plen != 0) { /* packet full */ + DEBUGF((" => packet full (no NL)=%d\r\n", n)); + goto error; + } + else if (n >= trunc_len && trunc_len!=0) { /* buffer full */ DEBUGF((" => line buffer full (no NL)=%d\r\n", n)); return trunc_len; } @@ -309,6 +313,10 @@ int packet_get_length(enum PacketParseType htype, } else { int len = (ptr2 - ptr) + 1; /* including newline */ + if (len > max_plen && max_plen!=0) { + DEBUGF((" => packet_size %d exceeded\r\n", max_plen)); + goto error; + } if (len > trunc_len && trunc_len!=0) { DEBUGF((" => truncated line=%d\r\n", trunc_len)); return trunc_len; @@ -397,33 +405,50 @@ int packet_get_length(enum PacketParseType htype, const char* ptr1 = ptr; int len = plen; + if (!max_plen) { + /* This is for backward compatibility with old user of decode_packet + * that might use option 'line_length' to limit accepted length of + * http lines. + */ + max_plen = trunc_len; + } + while (1) { const char* ptr2 = memchr(ptr1, '\n', len); if (ptr2 == NULL) { - if (n >= trunc_len && trunc_len!=0) { /* buffer full */ - plen = trunc_len; - goto done; + if (max_plen != 0) { + if (n >= max_plen) /* packet full */ + goto error; } goto more; } else { plen = (ptr2 - ptr) + 1; - - if (*statep == 0) + + if (*statep == 0) { + if (max_plen != 0 && plen > max_plen) + goto error; goto done; - + } + if (plen < n) { if (SP(ptr2+1) && plen>2) { /* header field value continue on next line */ ptr1 = ptr2+1; len = n - plen; } - else + else { + if (max_plen != 0 && plen > max_plen) + goto error; goto done; + } } - else + else { + if (max_plen != 0 && plen > max_plen) + goto error; goto more; + } } } } diff --git a/erts/emulator/beam/sys.h b/erts/emulator/beam/sys.h index 94c36c8c59..6b4b382caa 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,17 +657,24 @@ 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, int *hour, int *minute, int *second); void get_universaltime(int *year, int *month, int *day, int *hour, int *minute, int *second); -int univ_to_local(Sint *year, Sint *month, Sint *day, +int seconds_to_univ(Sint64 seconds, + Sint *year, Sint *month, Sint *day, + Sint *hour, Sint *minute, Sint *second); +int univ_to_seconds(Sint year, Sint month, Sint day, + Sint hour, Sint minute, Sint second, + Sint64* seconds); +int univ_to_local( + Sint *year, Sint *month, Sint *day, Sint *hour, Sint *minute, Sint *second); int local_to_univ(Sint *year, Sint *month, Sint *day, Sint *hour, Sint *minute, Sint *second, int isdst); @@ -968,6 +997,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..49b6618f73 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 @@ -2660,6 +2661,7 @@ tailrecur_ne: #endif #define MAX_LOSSLESS_FLOAT ((double)((1LL << 53) - 2)) #define MIN_LOSSLESS_FLOAT ((double)(((1LL << 53) - 2)*-1)) +#define BIG_ARITY_FLOAT_MAX (1024 / D_EXP) /* arity of max float as a bignum */ b_tag = tag_val_def(bw); switch(_NUMBER_CODE(a_tag, b_tag)) { @@ -2692,16 +2694,24 @@ tailrecur_ne: } #endif // ERTS_SIZEOF_ETERM == 8 break; + case FLOAT_BIG: + { + Wterm tmp = aw; + aw = bw; + bw = tmp; + }/* fall through */ case BIG_FLOAT: GET_DOUBLE(bw, f2); if ((f2.fd < (double) (MAX_SMALL + 1)) && (f2.fd > (double) (MIN_SMALL - 1))) { // Float is a Sint j = big_sign(aw) ? -1 : 1; - } else if ((pow(2.0,(big_arity(aw)-1.0)*D_EXP)-1.0) > fabs(f2.fd)) { + } else if (big_arity(aw) > BIG_ARITY_FLOAT_MAX + || pow(2.0,(big_arity(aw)-1)*D_EXP) > fabs(f2.fd)) { // If bignum size shows that it is bigger than the abs float j = big_sign(aw) ? -1 : 1; - } else if ((pow(2.0,(big_arity(aw))*D_EXP)-1.0) < fabs(f2.fd)) { + } else if (big_arity(aw) < BIG_ARITY_FLOAT_MAX + && (pow(2.0,(big_arity(aw))*D_EXP)-1.0) < fabs(f2.fd)) { // If bignum size shows that it is smaller than the abs float j = f2.fd < 0 ? 1 : -1; } else if (f2.fd < MAX_LOSSLESS_FLOAT && f2.fd > MIN_LOSSLESS_FLOAT) { @@ -2715,6 +2725,9 @@ tailrecur_ne: big = double_to_big(f2.fd, big_buf); j = big_comp(aw, big); } + if (_NUMBER_CODE(a_tag, b_tag) == FLOAT_BIG) { + j = -j; + } break; case FLOAT_SMALL: GET_DOUBLE(aw, f1); @@ -2739,29 +2752,6 @@ tailrecur_ne: } #endif // ERTS_SIZEOF_ETERM == 8 break; - case FLOAT_BIG: - GET_DOUBLE(aw, f1); - if ((f1.fd < (double) (MAX_SMALL + 1)) - && (f1.fd > (double) (MIN_SMALL - 1))) { // Float is a Sint - j = big_sign(bw) ? 1 : -1; - } else if ((pow(2.0, (big_arity(bw) - 1.0) * D_EXP) - 1.0) > fabs(f1.fd)) { - // If bignum size shows that it is bigger than the abs float - j = big_sign(bw) ? 1 : -1; - } else if ((pow(2.0,(big_arity(bw))*D_EXP)-1.0) < fabs(f1.fd)) { - // If bignum size shows that it is smaller than the abs float - j = f1.fd < 0 ? -1 : 1; - } else if (f1.fd < MAX_LOSSLESS_FLOAT && f1.fd > MIN_LOSSLESS_FLOAT) { - // Float is within the no loss limit - if (big_to_double(bw, &f2.fd) < 0) { - j = big_sign(bw) ? 1 : -1; - } else { - j = float_comp(f1.fd, f2.fd); - } - } else { - big = double_to_big(f1.fd, big_buf); - j = big_comp(big, bw); - } - break; default: j = b_tag - a_tag; } @@ -2875,9 +2865,9 @@ store_external_or_ref_in_proc_(Process *proc, Eterm ns) return store_external_or_ref_(&hp, &MSO(proc), ns); } -void bin_write(int to, void *to_arg, byte* buf, int sz) +void bin_write(int to, void *to_arg, byte* buf, size_t sz) { - int i; + size_t i; for (i=0;i<sz;i++) { if (IS_DIGIT(buf[i])) @@ -2952,15 +2942,15 @@ char* Sint_to_buf(Sint n, struct Sint_buf *buf) */ Eterm -buf_to_intlist(Eterm** hpp, char *buf, int len, Eterm tail) +buf_to_intlist(Eterm** hpp, char *buf, size_t len, Eterm tail) { Eterm* hp = *hpp; - int i = len - 1; + size_t i = len; - while(i >= 0) { + while(i != 0) { + --i; tail = CONS(hp, make_small((Uint)(byte)buf[i]), tail); hp += 2; - --i; } *hpp = hp; @@ -3469,11 +3459,9 @@ void erts_silence_warn_unused_result(long unused) * Handy functions when using a debugger - don't use in the code! */ -void upp(buf,sz) -byte* buf; -int sz; +void upp(byte *buf, size_t sz) { - bin_write(ERTS_PRINT_STDERR,NULL,buf,sz); + bin_write(ERTS_PRINT_STDERR, NULL, buf, sz); } void pat(Eterm atom) diff --git a/erts/emulator/drivers/common/efile_drv.c b/erts/emulator/drivers/common/efile_drv.c index 901d98c09d..b132991a3b 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,14 @@ # 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" @@ -140,6 +148,22 @@ static ErlDrvSysInfo sys_info; #define MUTEX_UNLOCK(m) #endif + +/** + * On DARWIN sendfile can deadlock with close if called in + * different threads. So until Apple fixes so that sendfile + * is not buggy we disable usage of the async pool for + * DARWIN. The testcase t_sendfile_crashduring reproduces + * this error when using +A 10. + */ +#if !defined(DARWIN) +#define USE_THRDS_FOR_SENDFILE (sys_info.async_threads > 0) +#else +#define USE_THRDS_FOR_SENDFILE 0 +#endif /* !DARWIN */ + + + #if 0 /* Experimental, for forcing all file operations to use the same thread. */ static unsigned file_fixed_key = 1; @@ -217,17 +241,25 @@ typedef unsigned char uchar; static ErlDrvData file_start(ErlDrvPort port, char* command); static int file_init(void); static void file_stop(ErlDrvData); -static void file_output(ErlDrvData, char* buf, int len); -static int file_control(ErlDrvData, unsigned int command, - char* buf, int len, char **rbuf, int rlen); +static void file_output(ErlDrvData, char* buf, ErlDrvSizeT len); +static ErlDrvSSizeT file_control(ErlDrvData, unsigned int command, + char* buf, ErlDrvSizeT len, + char **rbuf, ErlDrvSizeT rlen); static void file_timeout(ErlDrvData); 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 +274,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 +299,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 +318,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 +443,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 +538,6 @@ static void *ef_safe_realloc(void *op, Uint s) : 0) - #if 0 static void ev_clear(ErlIOVec *ev) { @@ -613,7 +665,6 @@ static struct t_data *cq_deq(file_descriptor *desc) { } - /********************************************************************* * Driver entry point -> init */ @@ -628,6 +679,7 @@ file_init(void) ? atoi(buf) : 0); driver_system_info(&sys_info, sizeof(ErlDrvSysInfo)); + return 0; } @@ -655,6 +707,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; @@ -697,6 +752,15 @@ file_stop(ErlDrvData e) TRACE_C('p'); +#ifdef HAVE_SENDFILE + if (desc->sendfile_state == sending && !USE_THRDS_FOR_SENDFILE) { + driver_select(desc->port,(ErlDrvEvent)(long)desc->d->c.sendfile.out_fd, + ERL_DRV_WRITE|ERL_DRV_USE,0); + } else if (desc->sendfile_state == sending) { + SET_NONBLOCKING(desc->d->c.sendfile.out_fd); + } +#endif /* HAVE_SENDFILE */ + if (desc->fd != FILE_FD_INVALID) { do_close(desc->flags, desc->fd); desc->fd = FILE_FD_INVALID; @@ -762,7 +826,16 @@ static void reply_Uint_posix_error(file_descriptor *desc, Uint num, driver_output2(desc->port, response, t-response, NULL, 0); } +static void reply_string_error(file_descriptor *desc, char* str) { + char response[256]; /* Response buffer. */ + char* s; + char* t; + response[0] = FILE_RESP_ERROR; + for (s = str, t = response+1; *s; s++, t++) + *t = tolower(*s); + driver_output2(desc->port, response, t-response, NULL, 0); +} static int reply_error(file_descriptor *desc, Efile_error *errInfo) /* The error codes. */ @@ -893,8 +966,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 *)) { @@ -1013,7 +1084,7 @@ static void invoke_read_line(void *data) d->c.read_line.read_offset - d->c.read_line.read_size; if (size == 0) { /* Need more place */ - size_t need = (d->c.read_line.read_size >= DEFAULT_LINEBUF_SIZE) ? + ErlDrvSizeT need = (d->c.read_line.read_size >= DEFAULT_LINEBUF_SIZE) ? d->c.read_line.read_size + DEFAULT_LINEBUF_SIZE : DEFAULT_LINEBUF_SIZE; ErlDrvBinary *newbin = driver_alloc_binary(need); if (newbin == NULL) { @@ -1694,6 +1765,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 (USE_THRDS_FOR_SENDFILE) { + 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 +1886,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)); @@ -2021,24 +2156,25 @@ file_async_ready(ErlDrvData e, ErlDrvThreadData data) if (d->result_ok) { resbuf[0] = FILE_RESP_INFO; - put_int32(d->info.size_high, &resbuf[1 + (0 * 4)]); - put_int32(d->info.size_low, &resbuf[1 + (1 * 4)]); - put_int32(d->info.type, &resbuf[1 + (2 * 4)]); - - PUT_TIME(d->info.accessTime, resbuf + 1 + 3*4); - PUT_TIME(d->info.modifyTime, resbuf + 1 + 9*4); - PUT_TIME(d->info.cTime, resbuf + 1 + 15*4); - - put_int32(d->info.mode, &resbuf[1 + (21 * 4)]); - put_int32(d->info.links, &resbuf[1 + (22 * 4)]); - put_int32(d->info.major_device, &resbuf[1 + (23 * 4)]); - put_int32(d->info.minor_device, &resbuf[1 + (24 * 4)]); - put_int32(d->info.inode, &resbuf[1 + (25 * 4)]); - put_int32(d->info.uid, &resbuf[1 + (26 * 4)]); - put_int32(d->info.gid, &resbuf[1 + (27 * 4)]); - put_int32(d->info.access, &resbuf[1 + (28 * 4)]); - -#define RESULT_SIZE (1 + (29 * 4)) + put_int32(d->info.size_high, &resbuf[1 + ( 0 * 4)]); + put_int32(d->info.size_low, &resbuf[1 + ( 1 * 4)]); + put_int32(d->info.type, &resbuf[1 + ( 2 * 4)]); + + /* Note 64 bit indexing in resbuf here */ + put_int64(d->info.accessTime, &resbuf[1 + ( 3 * 4)]); + put_int64(d->info.modifyTime, &resbuf[1 + ( 5 * 4)]); + put_int64(d->info.cTime, &resbuf[1 + ( 7 * 4)]); + + put_int32(d->info.mode, &resbuf[1 + ( 9 * 4)]); + put_int32(d->info.links, &resbuf[1 + (10 * 4)]); + put_int32(d->info.major_device, &resbuf[1 + (11 * 4)]); + put_int32(d->info.minor_device, &resbuf[1 + (12 * 4)]); + put_int32(d->info.inode, &resbuf[1 + (13 * 4)]); + put_int32(d->info.uid, &resbuf[1 + (14 * 4)]); + put_int32(d->info.gid, &resbuf[1 + (15 * 4)]); + put_int32(d->info.access, &resbuf[1 + (16 * 4)]); + +#define RESULT_SIZE (1 + (17 * 4)) TRACE_C('R'); driver_output2(desc->port, resbuf, RESULT_SIZE, NULL, 0); #undef RESULT_SIZE @@ -2105,6 +2241,42 @@ 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; + if (d->errInfo.posix_errno == ECONNRESET || + d->errInfo.posix_errno == ENOTCONN || + d->errInfo.posix_errno == EPIPE) + reply_string_error(desc,"closed"); + else + reply_error(desc, &d->errInfo); + if (USE_THRDS_FOR_SENDFILE) { + 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 (USE_THRDS_FOR_SENDFILE) { + 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(); } @@ -2120,7 +2292,7 @@ file_async_ready(ErlDrvData e, ErlDrvThreadData data) * Driver entry point -> output */ static void -file_output(ErlDrvData e, char* buf, int count) +file_output(ErlDrvData e, char* buf, ErlDrvSizeT count) { file_descriptor* desc = (file_descriptor*)e; Efile_error errInfo; /* The error codes for the last operation. */ @@ -2355,15 +2527,16 @@ file_output(ErlDrvData e, char* buf, int count) case FILE_WRITE_INFO: { d = EF_SAFE_ALLOC(sizeof(struct t_data) - 1 - + FILENAME_BYTELEN(buf+21*4) + FILENAME_CHARSIZE); + + FILENAME_BYTELEN(buf + 9*4) + FILENAME_CHARSIZE); - d->info.mode = get_int32(buf + 0 * 4); - d->info.uid = get_int32(buf + 1 * 4); - d->info.gid = get_int32(buf + 2 * 4); - GET_TIME(d->info.accessTime, buf + 3 * 4); - GET_TIME(d->info.modifyTime, buf + 9 * 4); - GET_TIME(d->info.cTime, buf + 15 * 4); - FILENAME_COPY(d->b, buf+21*4); + d->info.mode = get_int32(buf + 0 * 4); + d->info.uid = get_int32(buf + 1 * 4); + d->info.gid = get_int32(buf + 2 * 4); + d->info.accessTime = (time_t)((Sint64)get_int64(buf + 3 * 4)); + d->info.modifyTime = (time_t)((Sint64)get_int64(buf + 5 * 4)); + d->info.cTime = (time_t)((Sint64)get_int64(buf + 7 * 4)); + + FILENAME_COPY(d->b, buf + 9*4); d->command = command; d->invoke = invoke_write_info; d->free = free_data; @@ -2496,9 +2669,9 @@ file_flush(ErlDrvData e) { /********************************************************************* * Driver entry point -> control */ -static int +static ErlDrvSSizeT file_control(ErlDrvData e, unsigned int command, - char* buf, int len, char **rbuf, int rlen) { + char* buf, ErlDrvSizeT len, char **rbuf, ErlDrvSizeT rlen) { /* * warning: variable ‘desc’ set but not used * [-Wunused-but-set-variable] @@ -2799,8 +2972,8 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { cq_enq(desc, d); } goto done; case FILE_WRITE: { - int skip = 1; - int size = ev->size - skip; + ErlDrvSizeT skip = 1; + ErlDrvSizeT size = ev->size - skip; if (lseek_flush_read(desc, &err) < 0) { reply_posix_error(desc, err); goto done; @@ -2809,7 +2982,7 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { reply_posix_error(desc, EBADF); goto done; } - if (size <= 0) { + if (size == 0) { reply_Uint(desc, size); goto done; } @@ -2923,7 +3096,7 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { EF_FREE(d); reply_Uint(desc, 0); } else { - size_t skip = 1 + 4 + 8*(2*n); + ErlDrvSizeT skip = 1 + 4 + 8*(2*n); if (skip + total != ev->size) { /* Actual amount of data does not match * total of all pos/size specs @@ -3245,9 +3418,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 (USE_THRDS_FOR_SENDFILE) { + 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..be1faa13f5 100644 --- a/erts/emulator/drivers/common/erl_efile.h +++ b/erts/emulator/drivers/common/erl_efile.h @@ -67,6 +67,11 @@ #define FILENAMES_16BIT 1 #endif +// We use sendfilev if it exist on solaris +#if !defined(HAVE_SENDFILE) && defined(HAVE_SENDFILEV) +#define HAVE_SENDFILE +#endif + /* * An handle to an open directory. To be cast to the correct type * in the system-dependent directory functions. @@ -85,14 +90,15 @@ typedef struct _Efile_error { /* * This structure contains date and time. */ -typedef struct _Efile_time { - unsigned year; /* (4 digits). */ - unsigned month; /* (1..12). */ - unsigned day; /* (1..31). */ - unsigned hour; /* (0..23). */ - unsigned minute; /* (0..59). */ - unsigned second; /* (0..59). */ -} Efile_time; + +//typedef struct _Efile_time { +// unsigned year; /* (4 digits). */ +// unsigned month; /* (1..12). */ +// unsigned day; /* (1..31). */ +// unsigned hour; /* (0..23). */ +// unsigned minute; /* (0..59). */ +// unsigned second; /* (0..59). */ +//} Efile_time; /* @@ -111,13 +117,26 @@ typedef struct _Efile_info { Uint32 inode; /* Inode number. */ Uint32 uid; /* User id of owner. */ Uint32 gid; /* Group id of owner. */ - Efile_time accessTime; /* Last time the file was accessed. */ - Efile_time modifyTime; /* Last time the file was modified. */ - Efile_time cTime; /* Creation time (Windows) or last + time_t accessTime; /* Last time the file was accessed. */ + time_t modifyTime; /* Last time the file was modified. */ + time_t cTime; /* Creation time (Windows) or last * inode change (Unix). */ } Efile_info; + +#ifdef HAVE_SENDFILE +/* + * Describes the structure of headers/trailers for sendfile + */ +struct t_sendfile_hdtl { + SysIOVec *headers; + int hdr_cnt; + SysIOVec *trailers; + int trl_cnt; +}; +#endif /* HAVE_SENDFILE */ + /* * Functions. */ @@ -162,3 +181,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 1fe9e04341..eeaa4d24ea 100644 --- a/erts/emulator/drivers/common/inet_drv.c +++ b/erts/emulator/drivers/common/inet_drv.c @@ -80,6 +80,13 @@ #endif #ifdef __WIN32__ +#define LLU "%I64u" +#else +#define LLU "%llu" +#endif +typedef unsigned long long llu_t; + +#ifdef __WIN32__ #define STRNCASECMP strncasecmp #define INCL_WINSOCK_API_TYPEDEFS 1 @@ -110,6 +117,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 +523,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(!(d)->is_ignored); \ (d)->event_mask = (onoff) ? \ ((d)->event_mask | (flags)) : \ ((d)->event_mask & ~(flags)); \ @@ -467,6 +546,13 @@ static int my_strncasecmp(const char *s1, const char *s2, size_t n) (((unsigned char*) (s))[1] << 8) | \ (((unsigned char*) (s))[0])) + +#ifdef VALGRIND +# include <valgrind/memcheck.h> +#else +# define VALGRIND_MAKE_MEM_DEFINED(ptr,size) +#endif + /*---------------------------------------------------------------------------- ** Interface constants. ** @@ -538,6 +624,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 +813,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 +957,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 the inet_drv. + This flag should be set to true when + the fd is used outside of inet_drv. */ } inet_descriptor; @@ -876,13 +972,14 @@ typedef struct { static int tcp_inet_init(void); static void tcp_inet_stop(ErlDrvData); -static void tcp_inet_command(ErlDrvData, char*, int); +static void tcp_inet_command(ErlDrvData, char*, ErlDrvSizeT); static void tcp_inet_commandv(ErlDrvData, ErlIOVec*); static void tcp_inet_flush(ErlDrvData drv_data); static void tcp_inet_drv_input(ErlDrvData, ErlDrvEvent); static void tcp_inet_drv_output(ErlDrvData data, ErlDrvEvent event); static ErlDrvData tcp_inet_start(ErlDrvPort, char* command); -static int tcp_inet_ctl(ErlDrvData, unsigned int, char*, int, char**, int); +static ErlDrvSSizeT tcp_inet_ctl(ErlDrvData, unsigned int, + char*, ErlDrvSizeT, char**, ErlDrvSizeT); static void tcp_inet_timeout(ErlDrvData); static void tcp_inet_process_exit(ErlDrvData, ErlDrvMonitor *); static void inet_stop_select(ErlDrvEvent, void*); @@ -927,15 +1024,15 @@ static struct erl_drv_entry tcp_inet_driver_entry = static int packet_inet_init(void); static void packet_inet_stop(ErlDrvData); -static void packet_inet_command(ErlDrvData, char*, int); +static void packet_inet_command(ErlDrvData, char*, ErlDrvSizeT); static void packet_inet_drv_input(ErlDrvData data, ErlDrvEvent event); static void packet_inet_drv_output(ErlDrvData data, ErlDrvEvent event); static ErlDrvData udp_inet_start(ErlDrvPort, char* command); #ifdef HAVE_SCTP static ErlDrvData sctp_inet_start(ErlDrvPort, char* command); #endif -static int packet_inet_ctl(ErlDrvData, unsigned int, char*, - int, char**, int); +static ErlDrvSSizeT packet_inet_ctl(ErlDrvData, unsigned int, char*, + ErlDrvSizeT, char**, ErlDrvSizeT); static void packet_inet_timeout(ErlDrvData); #ifdef __WIN32__ static void packet_inet_event(ErlDrvData, ErlDrvEvent); @@ -1029,7 +1126,7 @@ typedef struct { } tcp_descriptor; /* send function */ -static int tcp_send(tcp_descriptor* desc, char* ptr, int len); +static int tcp_send(tcp_descriptor* desc, char* ptr, ErlDrvSizeT len); static int tcp_sendv(tcp_descriptor* desc, ErlIOVec* ev); static int tcp_recv(tcp_descriptor* desc, int request_len); static int tcp_deliver(tcp_descriptor* desc, int len); @@ -1096,7 +1193,7 @@ static ErlDrvTermData am_tos; static int inet_init(void); -static int ctl_reply(int, char*, int, char**, int); +static ErlDrvSSizeT ctl_reply(int, char*, ErlDrvSizeT, char**, ErlDrvSizeT); struct erl_drv_entry inet_driver_entry = { @@ -1106,7 +1203,23 @@ struct erl_drv_entry inet_driver_entry = NULL, /* output */ NULL, /* ready_input */ NULL, /* ready_output */ - "inet" + "inet", + NULL, + NULL, /* handle */ + NULL, /* control */ + NULL, /* timeout */ + NULL, /* outputv */ + NULL, /* ready_async */ + NULL, /* flush */ + NULL, /* call */ + NULL, /* event */ + ERL_DRV_EXTENDED_MARKER, + ERL_DRV_EXTENDED_MAJOR_VERSION, + ERL_DRV_EXTENDED_MINOR_VERSION, + 0, + NULL, + NULL, + NULL, }; /* XXX: is this a driver interface function ??? */ @@ -1120,7 +1233,7 @@ void erl_exit(int n, char*, ...); #ifdef FATAL_MALLOC -static void *alloc_wrapper(size_t size){ +static void *alloc_wrapper(ErlDrvSizeT size){ void *ret = driver_alloc(size); if(ret == NULL) erl_exit(1,"Out of virtual memory in malloc (%s)", __FILE__); @@ -1128,7 +1241,7 @@ static void *alloc_wrapper(size_t size){ } #define ALLOC(X) alloc_wrapper(X) -static void *realloc_wrapper(void *current, size_t size){ +static void *realloc_wrapper(void *current, ErlDrvSizeT size){ void *ret = driver_realloc(current,size); if(ret == NULL) erl_exit(1,"Out of virtual memory in realloc (%s)", __FILE__); @@ -1357,11 +1470,11 @@ static InetDrvBufStk *get_bufstk(void) return bs; } -static ErlDrvBinary* alloc_buffer(long minsz) +static ErlDrvBinary* alloc_buffer(ErlDrvSizeT minsz) { InetDrvBufStk *bs = get_bufstk(); - DEBUGF(("alloc_buffer: %ld\r\n", minsz)); + DEBUGF(("alloc_buffer: "LLU"\r\n", (llu_t)minsz)); if (bs && bs->buf.pos > 0) { long size; @@ -1437,7 +1550,7 @@ static void release_buffer(ErlDrvBinary* buf) } } -static ErlDrvBinary* realloc_buffer(ErlDrvBinary* buf, long newsz) +static ErlDrvBinary* realloc_buffer(ErlDrvBinary* buf, ErlDrvSizeT newsz) { return driver_realloc_binary(buf, newsz); } @@ -1466,8 +1579,9 @@ static ErlDrvData dummy_start(ErlDrvPort port, char* command) return (ErlDrvData)port; } -static int dummy_ctl(ErlDrvData data, unsigned int cmd, char* buf, int len, - char** rbuf, int rsize) +static ErlDrvSSizeT dummy_ctl(ErlDrvData data, unsigned int cmd, + char* buf, ErlDrvSizeT len, char** rbuf, + ErlDrvSizeT rsize) { static char error[] = "no_winsock2"; @@ -1475,7 +1589,7 @@ static int dummy_ctl(ErlDrvData data, unsigned int cmd, char* buf, int len, return ctl_reply(INET_REP_ERROR, error, sizeof(error), rbuf, rsize); } -static void dummy_command(ErlDrvData data, char* buf, int len) +static void dummy_command(ErlDrvData data, char* buf, ErlDrvSizeT len) { } @@ -1532,7 +1646,8 @@ static struct erl_drv_entry dummy_sctp_driver_entry = #endif /* general control reply function */ -static int ctl_reply(int rep, char* buf, int len, char** rbuf, int rsize) +static ErlDrvSSizeT ctl_reply(int rep, char* buf, ErlDrvSizeT len, + char** rbuf, ErlDrvSizeT rsize) { char* ptr; @@ -1548,7 +1663,7 @@ static int ctl_reply(int rep, char* buf, int len, char** rbuf, int rsize) } /* general control error reply function */ -static int ctl_error(int err, char** rbuf, int rsize) +static ErlDrvSSizeT ctl_error(int err, char** rbuf, ErlDrvSizeT rsize) { char response[256]; /* Response buffer. */ char* s; @@ -1559,7 +1674,7 @@ static int ctl_error(int err, char** rbuf, int rsize) return ctl_reply(INET_REP_ERROR, response, t-response, rbuf, rsize); } -static int ctl_xerror(char* xerr, char** rbuf, int rsize) +static ErlDrvSSizeT ctl_xerror(char* xerr, char** rbuf, ErlDrvSizeT rsize) { int n = strlen(xerr); return ctl_reply(INET_REP_ERROR, xerr, n, rbuf, rsize); @@ -3576,7 +3691,8 @@ static int inet_init() ** and is set to actual length of dst on return ** return NULL on error and ptr after port address on success */ -static char* inet_set_address(int family, inet_address* dst, char* src, int* len) +static char* inet_set_address(int family, inet_address* dst, + char* src, ErlDrvSizeT* len) { short port; @@ -3612,7 +3728,7 @@ static char* inet_set_address(int family, inet_address* dst, char* src, int* len ** src = [TAG,P1,P0,X1,X2,...] when TAG = INET_AF_INET | INET_AF_INET6 */ static char *inet_set_faddress(int family, inet_address* dst, - char *src, int* len) { + char *src, ErlDrvSizeT* len) { int tag; if (*len < 1) return NULL; @@ -3727,7 +3843,13 @@ static void desc_close(inet_descriptor* desc) desc->forced_events = 0; desc->send_would_block = 0; #endif - driver_select(desc->port, (ErlDrvEvent)(long)desc->event, ERL_DRV_USE, 0); + // We should close the fd here, but the other driver might still + // be selecting on it. + if (!desc->is_ignored) + driver_select(desc->port,(ErlDrvEvent)(long)desc->event, + ERL_DRV_USE, 0); + else + inet_stop_select((ErlDrvEvent)(long)desc->event,NULL); desc->event = INVALID_EVENT; /* closed by stop_select callback */ desc->s = INVALID_SOCKET; desc->event_mask = 0; @@ -3770,8 +3892,8 @@ static int erl_inet_close(inet_descriptor* desc) } -static int inet_ctl_open(inet_descriptor* desc, int domain, int type, - char** rbuf, int rsize) +static ErlDrvSSizeT inet_ctl_open(inet_descriptor* desc, int domain, int type, + char** rbuf, ErlDrvSizeT rsize) { if (desc->state != INET_STATE_CLOSED) return ctl_xerror(EXBADSEQ, rbuf, rsize); @@ -3791,8 +3913,8 @@ static int inet_ctl_open(inet_descriptor* desc, int domain, int type, /* as inet_open but pass in an open socket (MUST BE OF RIGHT TYPE) */ -static int inet_ctl_fdopen(inet_descriptor* desc, int domain, int type, - SOCKET s, char** rbuf, int rsize) +static ErlDrvSSizeT inet_ctl_fdopen(inet_descriptor* desc, int domain, int type, + SOCKET s, char** rbuf, ErlDrvSizeT rsize) { inet_address name; unsigned int sz = sizeof(name); @@ -3996,14 +4118,15 @@ static char* buf_to_sockaddr(char* ptr, char* end, struct sockaddr* addr) #if defined(__WIN32__) && defined(SIO_GET_INTERFACE_LIST) -static int inet_ctl_getiflist(inet_descriptor* desc, char** rbuf, int rsize) +static ErlDrvSSizeT inet_ctl_getiflist(inet_descriptor* desc, + char** rbuf, ErlDrvSizeT rsize) { char ifbuf[BUFSIZ]; char sbuf[BUFSIZ]; char* sptr; INTERFACE_INFO* ifp; DWORD len; - int n; + ErlDrvSizeT n; int err; ifp = (INTERFACE_INFO*) ifbuf; @@ -4033,8 +4156,8 @@ static int inet_ctl_getiflist(inet_descriptor* desc, char** rbuf, int rsize) /* input is an ip-address in string format i.e A.B.C.D ** scan the INTERFACE_LIST to get the options */ -static int inet_ctl_ifget(inet_descriptor* desc, char* buf, int len, - char** rbuf, int rsize) +static ErlDrvSSizeT inet_ctl_ifget(inet_descriptor* desc, char* buf, + ErlDrvSizeT len, char** rbuf, ErlDrvSizeT rsize) { char ifbuf[BUFSIZ]; int n; @@ -4135,8 +4258,9 @@ static int inet_ctl_ifget(inet_descriptor* desc, char* buf, int len, } /* not supported */ -static int inet_ctl_ifset(inet_descriptor* desc, char* buf, int len, - char** rbuf, int rsize) +static ErlDrvSSizeT inet_ctl_ifset(inet_descriptor* desc, + char* buf, ErlDrvSizeT len, + char** rbuf, ErlDrvSizeT rsize) { return ctl_reply(INET_REP_OK, NULL, 0, rbuf, rsize); } @@ -4179,12 +4303,13 @@ static void free_ifconf(struct ifconf *ifcp) { FREE(ifcp->ifc_buf); } -static int inet_ctl_getiflist(inet_descriptor* desc, char** rbuf, int rsize) +static ErlDrvSSizeT inet_ctl_getiflist(inet_descriptor* desc, + char** rbuf, ErlDrvSizeT rsize) { struct ifconf ifc; struct ifreq *ifrp; char *sbuf, *sp; - int i; + ErlDrvSizeT i; /* Courtesy of Per Bergqvist and W. Richard Stevens */ @@ -4196,7 +4321,7 @@ static int inet_ctl_getiflist(inet_descriptor* desc, char** rbuf, int rsize) *sp++ = INET_REP_OK; i = 0; for (;;) { - int n; + ErlDrvSizeT n; ifrp = (struct ifreq *) VOIDP(ifc.ifc_buf + i); n = sizeof(ifrp->ifr_name) + SIZEA(ifrp->ifr_addr); @@ -4222,13 +4347,39 @@ 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 #endif -static int inet_ctl_ifget(inet_descriptor* desc, char* buf, int len, - char** rbuf, int rsize) +static ErlDrvSSizeT inet_ctl_ifget(inet_descriptor* desc, + char* buf, ErlDrvSizeT len, + char** rbuf, ErlDrvSizeT rsize) { char sbuf[BUFSIZ]; char* sptr; @@ -4257,7 +4408,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 +4434,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)); @@ -4405,8 +4573,9 @@ static int inet_ctl_ifget(inet_descriptor* desc, char* buf, int len, } -static int inet_ctl_ifset(inet_descriptor* desc, char* buf, int len, - char** rbuf, int rsize) +static ErlDrvSSizeT inet_ctl_ifset(inet_descriptor* desc, + char* buf, ErlDrvSizeT len, + char** rbuf, ErlDrvSizeT rsize) { struct ifreq ifreq; int namlen; @@ -4429,19 +4598,19 @@ static int inet_ctl_ifset(inet_descriptor* desc, char* buf, int len, break; case INET_IFOPT_HWADDR: { - unsigned int len; + unsigned int hwalen; buf_check(buf, b_end, 2); - len = get_int16(buf); buf += 2; - buf_check(buf, b_end, len); + hwalen = get_int16(buf); buf += 2; + buf_check(buf, b_end, hwalen); #ifdef SIOCSIFHWADDR /* raw memcpy (fix include autoconf later) */ sys_memset((char*)(&ifreq.ifr_hwaddr.sa_data), '\0', sizeof(ifreq.ifr_hwaddr.sa_data)); - sys_memcpy((char*)(&ifreq.ifr_hwaddr.sa_data), buf, len); + sys_memcpy((char*)(&ifreq.ifr_hwaddr.sa_data), buf, hwalen); (void) ioctl(desc->s, SIOCSIFHWADDR, (char *)&ifreq); #endif - buf += len; + buf += hwalen; break; } @@ -4527,21 +4696,24 @@ static int inet_ctl_ifset(inet_descriptor* desc, char* buf, int len, #else -static int inet_ctl_getiflist(inet_descriptor* desc, char** rbuf, int rsize) +static ErlDrvSSizeT inet_ctl_getiflist(inet_descriptor* desc, + char** rbuf, ErlDrvSizeT rsize) { return ctl_reply(INET_REP_OK, NULL, 0, rbuf, rsize); } -static int inet_ctl_ifget(inet_descriptor* desc, char* buf, int len, - char** rbuf, int rsize) +static ErlDrvSSizeT inet_ctl_ifget(inet_descriptor* desc, + char* buf, ErlDrvSizeT len, + char** rbuf, ErlDrvSizeT rsize) { return ctl_reply(INET_REP_OK, NULL, 0, rbuf, rsize); } -static int inet_ctl_ifset(inet_descriptor* desc, char* buf, int len, - char** rbuf, int rsize) +static ErlDrvSSizeT inet_ctl_ifset(inet_descriptor* desc, + char* buf, ErlDrvSizeT len, + char** rbuf, ErlDrvSizeT rsize) { return ctl_reply(INET_REP_OK, NULL, 0, rbuf, rsize); } @@ -4598,8 +4770,8 @@ int eq_masked_bytes(char *a, char *b, int pref_len) { return !0; } -static int inet_ctl_getifaddrs(inet_descriptor* desc_p, - char **rbuf_pp, int rsize) +static ErlDrvSSizeT inet_ctl_getifaddrs(inet_descriptor* desc_p, + char **rbuf_pp, ErlDrvSizeT rsize) { int i; DWORD ret, n; @@ -4609,7 +4781,7 @@ static int inet_ctl_getifaddrs(inet_descriptor* desc_p, char *buf_p; char *buf_alloc_p; - int buf_size =512; + ErlDrvSizeT buf_size = 512; # define BUF_ENSURE(Size) \ do { \ int NEED_, GOT_ = buf_p - buf_alloc_p; \ @@ -4983,12 +5155,12 @@ done: #elif defined(HAVE_GETIFADDRS) -static int inet_ctl_getifaddrs(inet_descriptor* desc_p, - char **rbuf_pp, int rsize) +static ErlDrvSSizeT inet_ctl_getifaddrs(inet_descriptor* desc_p, + char **rbuf_pp, ErlDrvSizeT rsize) { struct ifaddrs *ifa_p, *ifa_free_p; - int buf_size; + ErlDrvSizeT buf_size; char *buf_p; char *buf_alloc_p; @@ -5091,8 +5263,8 @@ static int inet_ctl_getifaddrs(inet_descriptor* desc_p, #else -static int inet_ctl_getifaddrs(inet_descriptor* desc_p, - char **rbuf_pp, int rsize) +static ErlDrvSSizeT inet_ctl_getifaddrs(inet_descriptor* desc_p, + char **rbuf_pp, ErlDrvSizeT rsize) { return ctl_error(ENOTSUP, rbuf_pp, rsize); } @@ -5893,7 +6065,7 @@ static int sctp_set_opts(inet_descriptor* desc, char* ptr, int len) case SCTP_OPT_PRIMARY_ADDR: case SCTP_OPT_SET_PEER_PRIMARY_ADDR: { - int alen; + ErlDrvSizeT alen; char *after; CHKLEN(curr, ASSOC_ID_LEN); @@ -5935,7 +6107,7 @@ static int sctp_set_opts(inet_descriptor* desc, char* ptr, int len) } case SCTP_OPT_PEER_ADDR_PARAMS: { - int alen; + ErlDrvSizeT alen; char *after; # ifdef HAVE_STRUCT_SCTP_PADDRPARAMS_SPP_FLAGS int eflags, cflags, hb_enable, hb_disable, @@ -6065,7 +6237,7 @@ static int sctp_set_opts(inet_descriptor* desc, char* ptr, int len) proto = IPPROTO_SCTP; type = SCTP_DELAYED_ACK_TIME; arg_ptr = (char*) (&arg.av); - arg_sz = sizeof ( arg.es); + arg_sz = sizeof ( arg.av); break; } # endif @@ -6111,8 +6283,9 @@ static int sctp_set_opts(inet_descriptor* desc, char* ptr, int len) ** ptr should point to a buffer with 9*len +1 to be safe!! */ -static int inet_fill_opts(inet_descriptor* desc, - char* buf, int len, char** dest, int destlen) +static ErlDrvSSizeT inet_fill_opts(inet_descriptor* desc, + char* buf, ErlDrvSizeT len, + char** dest, ErlDrvSizeT destlen) { int type; int proto; @@ -6122,8 +6295,8 @@ static int inet_fill_opts(inet_descriptor* desc, char* arg_ptr; unsigned int arg_sz; char *ptr = NULL; - int dest_used = 0; - int dest_allocated = destlen; + ErlDrvSizeT dest_used = 0; + ErlDrvSizeT dest_allocated = destlen; char *orig_dest = *dest; /* Ptr is a name parameter */ @@ -6138,7 +6311,7 @@ static int inet_fill_opts(inet_descriptor* desc, #define PLACE_FOR(Size,Ptr) \ do { \ - int need = dest_used + (Size); \ + ErlDrvSizeT need = dest_used + (Size); \ if (need > INET_MAX_OPT_BUFFER) { \ RETURN_ERROR(); \ } \ @@ -6159,7 +6332,7 @@ static int inet_fill_opts(inet_descriptor* desc, /* Ptr is a name parameter */ #define TRUNCATE_TO(Size,Ptr) \ do { \ - int new_need = ((Ptr) - (*dest)) + (Size); \ + ErlDrvSizeT new_need = ((Ptr) - (*dest)) + (Size); \ if (new_need > dest_used) { \ erl_exit(1,"Internal error in inet_drv, " \ "miscalculated buffer size"); \ @@ -6449,8 +6622,9 @@ static int load_paddrinfo (ErlDrvTermData * spec, int i, /* ** "sctp_fill_opts": Returns {ok, Results}, or an error: */ -static int sctp_fill_opts(inet_descriptor* desc, char* buf, int buflen, - char** dest, int destlen) +static ErlDrvSSizeT sctp_fill_opts(inet_descriptor* desc, + char* buf, ErlDrvSizeT buflen, + char** dest, ErlDrvSizeT destlen) { /* In contrast to the generic "inet_fill_opts", the output here is represented by tuples/records, which are formed in the "spec": @@ -6840,7 +7014,7 @@ static int sctp_fill_opts(inet_descriptor* desc, char* buf, int buflen, unsigned int sz = sizeof(ap); int n; char *after; - int alen; + ErlDrvSizeT alen; if (buflen < ASSOC_ID_LEN) RETURN_ERROR(spec, -EINVAL); ap.spp_assoc_id = GET_ASSOC_ID(buf); @@ -7080,7 +7254,7 @@ static int sctp_fill_opts(inet_descriptor* desc, char* buf, int buflen, struct sctp_paddrinfo pai; unsigned int sz = sizeof(pai); char *after; - int alen; + ErlDrvSizeT alen; if (buflen < ASSOC_ID_LEN) RETURN_ERROR(spec, -EINVAL); pai.spinfo_assoc_id = GET_ASSOC_ID(buf); @@ -7137,7 +7311,8 @@ static int sctp_fill_opts(inet_descriptor* desc, char* buf, int buflen, /* fill statistics reply, op codes from src and result in dest ** dst area must be a least 5*len + 1 bytes */ -static int inet_fill_stat(inet_descriptor* desc, char* src, int len, char* dst) +static ErlDrvSSizeT inet_fill_stat(inet_descriptor* desc, + char* src, ErlDrvSizeT len, char* dst) { unsigned long val; int op; @@ -7170,7 +7345,7 @@ static int inet_fill_stat(inet_descriptor* desc, char* src, int len, char* dst) val = (unsigned long) desc->send_avg; break; case INET_STAT_SEND_PND: - val = driver_sizeq(desc->port); + val = (unsigned long) driver_sizeq(desc->port); break; case INET_STAT_RECV_OCT: put_int32(desc->recv_oct[1], dst); /* write high 32bit */ @@ -7215,7 +7390,8 @@ send_empty_out_q_msgs(inet_descriptor* desc) /* subscribe and fill subscription reply, op codes from src and ** result in dest dst area must be a least 5*len + 1 bytes */ -static int inet_subscribe(inet_descriptor* desc, char* src, int len, char* dst) +static ErlDrvSSizeT inet_subscribe(inet_descriptor* desc, + char* src, ErlDrvSizeT len, char* dst) { unsigned long val; int op; @@ -7302,6 +7478,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; } @@ -7313,14 +7491,14 @@ static ErlDrvData inet_start(ErlDrvPort port, int size, int protocol) /* ** common TCP/UDP/SCTP control command */ -static int inet_ctl(inet_descriptor* desc, int cmd, char* buf, int len, - char** rbuf, int rsize) +static ErlDrvSSizeT inet_ctl(inet_descriptor* desc, int cmd, char* buf, + ErlDrvSizeT len, char** rbuf, ErlDrvSizeT rsize) { switch (cmd) { case INET_REQ_GETSTAT: { char* dst; - int i; + ErlDrvSizeT i; int dstlen = 1; /* Reply code */ for (i = 0; i < len; i++) { @@ -7360,7 +7538,7 @@ static int inet_ctl(inet_descriptor* desc, int cmd, char* buf, int len, } case INET_REQ_GETOPTS: { /* get options */ - int replen; + ErlDrvSSizeT replen; DEBUGF(("inet_ctl(%ld): GETOPTS\r\n", (long)desc->port)); #ifdef HAVE_SCTP if (IS_SCTP(desc)) @@ -7584,6 +7762,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) { + sock_select(desc, (FD_READ|FD_WRITE|FD_CLOSE|ERL_DRV_USE_NO_CALLBACK), 0); + desc->is_ignored = INET_IGNORE_READ; + } 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 */ @@ -7644,7 +7849,7 @@ static int inet_ctl(inet_descriptor* desc, int cmd, char* buf, int len, } /* update statistics on output packets */ -static void inet_output_count(inet_descriptor* desc, int len) +static void inet_output_count(inet_descriptor* desc, ErlDrvSizeT len) { unsigned long n = desc->send_cnt + 1; unsigned long t = desc->send_oct[0] + len; @@ -7664,7 +7869,7 @@ static void inet_output_count(inet_descriptor* desc, int len) } /* update statistics on input packets */ -static void inet_input_count(inet_descriptor* desc, int len) +static void inet_input_count(inet_descriptor* desc, ErlDrvSizeT len) { unsigned long n = desc->recv_cnt + 1; unsigned long t = desc->recv_oct[0] + len; @@ -7787,7 +7992,7 @@ static void tcp_clear_input(tcp_descriptor* desc) static void tcp_clear_output(tcp_descriptor* desc) { ErlDrvPort ix = desc->inet.port; - int qsz = driver_sizeq(ix); + ErlDrvSizeT qsz = driver_sizeq(ix); driver_deq(ix, qsz); send_empty_out_q_msgs(INETP(desc)); @@ -7955,10 +8160,12 @@ static void tcp_inet_stop(ErlDrvData e) /* TCP requests from Erlang */ -static int tcp_inet_ctl(ErlDrvData e, unsigned int cmd, char* buf, int len, - char** rbuf, int rsize) +static ErlDrvSSizeT tcp_inet_ctl(ErlDrvData e, unsigned int cmd, + char* buf, ErlDrvSizeT len, + char** rbuf, ErlDrvSizeT rsize) { tcp_descriptor* desc = (tcp_descriptor*)e; + switch(cmd) { case INET_REQ_OPEN: { /* open socket and return internal index */ int domain; @@ -8224,13 +8431,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); @@ -8355,7 +8563,7 @@ static void tcp_inet_multi_timeout(ErlDrvData e, ErlDrvTermData caller) ** but distribution still uses the tcp_inet_command!! */ -static void tcp_inet_command(ErlDrvData e, char *buf, int len) +static void tcp_inet_command(ErlDrvData e, char *buf, ErlDrvSizeT len) { tcp_descriptor* desc = (tcp_descriptor*)e; desc->inet.caller = driver_caller(desc->inet.port); @@ -8574,8 +8782,15 @@ static int tcp_remain(tcp_descriptor* desc, int* len) else if (tlen == 0) { /* need unknown more */ *len = 0; if (nsz == 0) { - if (nfill == n) - goto error; + if (nfill == n) { + if (desc->inet.psize != 0 && desc->inet.psize > nfill) { + if (tcp_expand_buffer(desc, desc->inet.psize) < 0) + return -1; + return desc->inet.psize; + } + else + goto error; + } DEBUGF((" => restart more=%d\r\n", nfill - n)); return nfill - n; } @@ -8970,6 +9185,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; @@ -9176,12 +9392,12 @@ static int tcp_send_error(tcp_descriptor* desc, int err) */ static int tcp_sendv(tcp_descriptor* desc, ErlIOVec* ev) { - int sz; + ErlDrvSizeT sz; char buf[4]; - int h_len; - int n; + ErlDrvSizeT h_len; + ssize_t n; ErlDrvPort ix = desc->inet.port; - int len = ev->size; + ErlDrvSizeT len = ev->size; switch(desc->inet.htype) { case TCP_PB_1: @@ -9229,9 +9445,13 @@ static int tcp_sendv(tcp_descriptor* desc, ErlIOVec* ev) else { int vsize = (ev->vsize > MAX_VSIZE) ? MAX_VSIZE : ev->vsize; - 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) { + DEBUGF(("tcp_sendv(%ld): s=%d, about to send "LLU","LLU" bytes\r\n", + (long)desc->inet.port, desc->inet.s, (llu_t)h_len, (llu_t)len)); + + 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))) { @@ -9252,14 +9472,17 @@ static int tcp_sendv(tcp_descriptor* desc, ErlIOVec* ev) return 0; } else { - DEBUGF(("tcp_sendv(%ld): s=%d, only sent %d/%d of %d/%d bytes/items\r\n", - (long)desc->inet.port, desc->inet.s, n, vsize, ev->size, ev->vsize)); + DEBUGF(("tcp_sendv(%ld): s=%d, only sent " + LLU"/%d of "LLU"/%d bytes/items\r\n", + (long)desc->inet.port, desc->inet.s, + (llu_t)n, vsize, (llu_t)ev->size, ev->vsize)); } 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; } @@ -9267,7 +9490,7 @@ static int tcp_sendv(tcp_descriptor* desc, ErlIOVec* ev) /* ** Send non blocking data */ -static int tcp_send(tcp_descriptor* desc, char* ptr, int len) +static int tcp_send(tcp_descriptor* desc, char* ptr, ErlDrvSizeT len) { int sz; char buf[4]; @@ -9322,9 +9545,12 @@ static int tcp_send(tcp_descriptor* desc, char* ptr, int len) iov[1].iov_base = ptr; iov[1].iov_len = 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) { + DEBUGF(("tcp_send(%ld): s=%d, about to send "LLU","LLU" bytes\r\n", + (long)desc->inet.port, desc->inet.s, (llu_t)h_len, (llu_t)len)); + 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 +9581,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 +9606,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) { @@ -9430,7 +9658,7 @@ static int tcp_inet_output(tcp_descriptor* desc, HANDLE event) else if (IS_CONNECTED(INETP(desc))) { for (;;) { int vsize; - int n; + ssize_t n; SysIOVec* iov; if ((iov = driver_peekq(ix, &vsize)) == NULL) { @@ -9641,10 +9869,10 @@ static int packet_error(udp_descriptor* udesc, int err) /* ** Various functions accessible via "port_control" on the Erlang side: */ -static int packet_inet_ctl(ErlDrvData e, unsigned int cmd, char* buf, int len, - char** rbuf, int rsize) +static ErlDrvSSizeT packet_inet_ctl(ErlDrvData e, unsigned int cmd, char* buf, + ErlDrvSizeT len, char** rbuf, ErlDrvSizeT rsize) { - int replen; + ErlDrvSSizeT replen; udp_descriptor * udesc = (udp_descriptor *) e; inet_descriptor* desc = INETP(udesc); int type = SOCK_DGRAM; @@ -9754,7 +9982,6 @@ static int packet_inet_ctl(ErlDrvData e, unsigned int cmd, char* buf, int len, DEBUGF(("packet_inet_ctl(%ld): CLOSE\r\n", (long)desc->port)); erl_inet_close(desc); return ctl_reply(INET_REP_OK, NULL, 0, rbuf, rsize); - return 0; case INET_REQ_CONNECT: { @@ -9900,7 +10127,7 @@ static int packet_inet_ctl(ErlDrvData e, unsigned int cmd, char* buf, int len, /* List item format: Port(2), IP(4|16) -- compatible with "inet_set_address": */ inet_address tmp; - int alen = buf + len - curr; + ErlDrvSizeT alen = buf + len - curr; curr = inet_set_address(desc->sfamily, &tmp, curr, &alen); if (curr == NULL) return ctl_error(EINVAL, rbuf, rsize); @@ -10025,13 +10252,13 @@ static void packet_inet_timeout(ErlDrvData e) ** There is no destination address -- SCTYP send is performed over ** an existing association, using "sctp_sndrcvinfo" specified. */ -static void packet_inet_command(ErlDrvData e, char* buf, int len) +static void packet_inet_command(ErlDrvData e, char* buf, ErlDrvSizeT len) { udp_descriptor * udesc= (udp_descriptor*) e; inet_descriptor* desc = INETP(udesc); char* ptr = buf; char* qtr; - int sz; + ErlDrvSizeT sz; int code; inet_address other; @@ -10049,7 +10276,7 @@ static void packet_inet_command(ErlDrvData e, char* buf, int len) #ifdef HAVE_SCTP if (IS_SCTP(desc)) { - int data_len; + ErlDrvSizeT data_len; struct iovec iov[1]; /* For real data */ struct msghdr mhdr; /* Message wrapper */ struct sctp_sndrcvinfo *sri; /* The actual ancilary data */ @@ -10072,6 +10299,7 @@ static void packet_inet_command(ErlDrvData e, char* buf, int len) cmsg.hdr.cmsg_level = IPPROTO_SCTP; cmsg.hdr.cmsg_type = SCTP_SNDRCV; cmsg.hdr.cmsg_len = CMSG_LEN(sizeof(*sri)); + VALGRIND_MAKE_MEM_DEFINED(&cmsg, (char*)sri - (char*)&cmsg); /*suppress padding as "uninitialised bytes"*/ data_len = (buf + len) - ptr; /* The whole msg. @@ -10269,6 +10497,7 @@ static int packet_inet_input(udp_descriptor* udesc, HANDLE event) int code; void * extra = NULL; char * ptr; + int nsz; inet_input_count(desc, n); udesc->i_ptr += n; @@ -10282,17 +10511,19 @@ static int packet_inet_input(udp_descriptor* udesc, HANDLE event) ptr = udesc->i_buf->orig_bytes + sizeof(other) - len; sys_memcpy(ptr, abuf, len); + nsz = udesc->i_ptr - ptr; + /* Check if we need to reallocate binary */ - if ((desc->mode == INET_MODE_BINARY) && - (desc->hsz < (udesc->i_ptr - ptr)) && - ((udesc->i_ptr - ptr) + BIN_REALLOC_MARGIN(desc->bufsz) >= - udesc->i_bufsz)) { + if ((desc->mode == INET_MODE_BINARY) + && (desc->hsz < (nsz - len)) + && (nsz + BIN_REALLOC_MARGIN(desc->bufsz) < udesc->i_bufsz)) { ErlDrvBinary* tmp; int bufsz; bufsz = udesc->i_ptr - udesc->i_buf->orig_bytes; if ((tmp = realloc_buffer(udesc->i_buf, bufsz)) != NULL) { udesc->i_buf = tmp; udesc->i_bufsz = bufsz; + udesc->i_ptr = NULL; /* not used from here */ } } #ifdef HAVE_SCTP @@ -10300,8 +10531,8 @@ static int packet_inet_input(udp_descriptor* udesc, HANDLE event) #endif /* Actual parsing and return of the data received, occur here: */ code = packet_reply_binary_data(desc, len, udesc->i_buf, - ptr - udesc->i_buf->orig_bytes, - udesc->i_ptr - ptr, + (sizeof(other) - len), + nsz, extra); free_buffer(udesc->i_buf); udesc->i_buf = NULL; @@ -10793,7 +11024,7 @@ int erts_sock_connect(erts_sock_t socket, byte *ip_addr, int len, Uint16 port) { SOCKET s = (SOCKET) socket; char buf[2 + 4]; - int blen = 6; + ErlDrvSizeT blen = 6; inet_address addr; if (socket == ERTS_SOCK_INVALID_SOCKET || len != 4) diff --git a/erts/emulator/drivers/common/ram_file_drv.c b/erts/emulator/drivers/common/ram_file_drv.c index abedcc933a..a109e40333 100644 --- a/erts/emulator/drivers/common/ram_file_drv.c +++ b/erts/emulator/drivers/common/ram_file_drv.c @@ -1,7 +1,7 @@ /* * %CopyrightBegin% * - * Copyright Ericsson AB 1997-2010. All Rights Reserved. + * Copyright Ericsson AB 1997-2011. All Rights Reserved. * * The contents of this file are subject to the Erlang Public License, * Version 1.1, (the "License"); you may not use this file except in @@ -98,7 +98,7 @@ typedef unsigned char uchar; static ErlDrvData rfile_start(ErlDrvPort, char*); static int rfile_init(void); static void rfile_stop(ErlDrvData); -static void rfile_command(ErlDrvData, char*, int); +static void rfile_command(ErlDrvData, char*, ErlDrvSizeT); struct erl_drv_entry ram_file_driver_entry = { @@ -108,7 +108,23 @@ struct erl_drv_entry ram_file_driver_entry = { rfile_command, NULL, NULL, - "ram_file_drv" + "ram_file_drv", + NULL, + NULL, /* handle */ + NULL, /* control */ + NULL, /* timeout */ + NULL, /* outputv */ + NULL, /* ready_async */ + NULL, /* flush */ + NULL, /* call */ + NULL, /* event */ + ERL_DRV_EXTENDED_MARKER, + ERL_DRV_EXTENDED_MAJOR_VERSION, + ERL_DRV_EXTENDED_MINOR_VERSION, + 0, + NULL, + NULL, + NULL, }; /* A File is represented as a array of bytes, this array is @@ -121,9 +137,9 @@ typedef struct ram_file { int flags; /* flags read/write */ ErlDrvBinary* bin; /* binary to hold binary file */ char* buf; /* buffer start (in binary) */ - int size; /* buffer size (allocated) */ - int cur; /* current position in buffer */ - int end; /* end position in buffer */ + ErlDrvSSizeT size; /* buffer size (allocated) */ + ErlDrvSSizeT cur; /* current position in buffer */ + ErlDrvSSizeT end; /* end position in buffer */ } RamFile; #ifdef LOADABLE @@ -211,7 +227,7 @@ static int reply(RamFile *f, int ok, int err) return 0; } -static int numeric_reply(RamFile *f, int result) +static int numeric_reply(RamFile *f, ErlDrvSSizeT result) { char tmp[5]; @@ -231,7 +247,8 @@ static int numeric_reply(RamFile *f, int result) /* install bin as the new binary reset all pointer */ -static void ram_file_set(RamFile *f, ErlDrvBinary *bin, int bsize, int len) +static void ram_file_set(RamFile *f, ErlDrvBinary *bin, + ErlDrvSSizeT bsize, ErlDrvSSizeT len) { f->size = bsize; f->buf = bin->orig_bytes; @@ -240,9 +257,9 @@ static void ram_file_set(RamFile *f, ErlDrvBinary *bin, int bsize, int len) f->bin = bin; } -static int ram_file_init(RamFile *f, char *buf, int count, int *error) +static int ram_file_init(RamFile *f, char *buf, ErlDrvSSizeT count, int *error) { - int bsize; + ErlDrvSSizeT bsize; ErlDrvBinary* bin; if (count < 0) { @@ -268,9 +285,9 @@ static int ram_file_init(RamFile *f, char *buf, int count, int *error) return count; } -static int ram_file_expand(RamFile *f, int size, int *error) +static ErlDrvSSizeT ram_file_expand(RamFile *f, ErlDrvSSizeT size, int *error) { - int bsize; + ErlDrvSSizeT bsize; ErlDrvBinary* bin; if (size < 0) { @@ -298,10 +315,10 @@ static int ram_file_expand(RamFile *f, int size, int *error) } -static int ram_file_write(RamFile *f, char *buf, int len, - int *location, int *error) +static ErlDrvSSizeT ram_file_write(RamFile *f, char *buf, ErlDrvSSizeT len, + ErlDrvSSizeT *location, int *error) { - int cur = f->cur; + ErlDrvSSizeT cur = f->cur; if (!(f->flags & RAM_FILE_MODE_WRITE)) { *error = EBADF; @@ -322,11 +339,11 @@ static int ram_file_write(RamFile *f, char *buf, int len, return len; } -static int ram_file_read(RamFile *f, int len, ErlDrvBinary **bp, - int *location, int *error) +static ErlDrvSSizeT ram_file_read(RamFile *f, ErlDrvSSizeT len, ErlDrvBinary **bp, + ErlDrvSSizeT *location, int *error) { ErlDrvBinary* bin; - int cur = f->cur; + ErlDrvSSizeT cur = f->cur; if (!(f->flags & RAM_FILE_MODE_READ)) { *error = EBADF; @@ -352,9 +369,10 @@ static int ram_file_read(RamFile *f, int len, ErlDrvBinary **bp, return len; } -static int ram_file_seek(RamFile *f, int offset, int whence, int *error) +static ErlDrvSSizeT ram_file_seek(RamFile *f, ErlDrvSSizeT offset, int whence, + int *error) { - int pos; + ErlDrvSSizeT pos; if (f->flags == 0) { *error = EBADF; @@ -389,13 +407,13 @@ static int ram_file_seek(RamFile *f, int offset, int whence, int *error) static int ram_file_uuencode(RamFile *f) { - int code_len = UULINE(UNIX_LINE); - int len = f->end; - int usize = 4*((len+2)/3) + 2*((len+code_len-1)/code_len) + 2; + ErlDrvSSizeT code_len = UULINE(UNIX_LINE); + ErlDrvSSizeT len = f->end; + ErlDrvSSizeT usize = 4*((len+2)/3) + 2*((len+code_len-1)/code_len) + 2; ErlDrvBinary* bin; uchar* inp; uchar* outp; - int count = 0; + ErlDrvSSizeT count = 0; if ((bin = driver_alloc_binary(usize)) == NULL) return error_reply(f, ENOMEM); @@ -447,8 +465,8 @@ static int ram_file_uuencode(RamFile *f) static int ram_file_uudecode(RamFile *f) { - int len = f->end; - int usize = ( (len+3) / 4 ) * 3; + ErlDrvSSizeT len = f->end; + ErlDrvSSizeT usize = ( (len+3) / 4 ) * 3; ErlDrvBinary* bin; uchar* inp; uchar* outp; @@ -510,7 +528,7 @@ static int ram_file_uudecode(RamFile *f) static int ram_file_compress(RamFile *f) { - int size = f->end; + ErlDrvSSizeT size = f->end; ErlDrvBinary* bin; if ((bin = erts_gzdeflate_buffer(f->buf, size)) == NULL) { @@ -528,7 +546,7 @@ static int ram_file_compress(RamFile *f) static int ram_file_uncompress(RamFile *f) { - int size = f->end; + ErlDrvSSizeT size = f->end; ErlDrvBinary* bin; if ((bin = erts_gzinflate_buffer(f->buf, size)) == NULL) { @@ -541,15 +559,15 @@ static int ram_file_uncompress(RamFile *f) } -static void rfile_command(ErlDrvData e, char* buf, int count) +static void rfile_command(ErlDrvData e, char* buf, ErlDrvSizeT count) { RamFile* f = (RamFile*)e; int error = 0; ErlDrvBinary* bin; char header[5]; /* result code + count */ - int offset; - int origin; /* Origin of seek. */ - int n; + ErlDrvSSizeT offset; + ErlDrvSSizeT origin; /* Origin of seek. */ + ErlDrvSSizeT n; count--; switch(*(uchar*)buf++) { diff --git a/erts/emulator/drivers/common/zlib_drv.c b/erts/emulator/drivers/common/zlib_drv.c index f50899a730..da4a17db1a 100644 --- a/erts/emulator/drivers/common/zlib_drv.c +++ b/erts/emulator/drivers/common/zlib_drv.c @@ -1,7 +1,7 @@ /* * %CopyrightBegin% * - * Copyright Ericsson AB 2003-2010. All Rights Reserved. + * Copyright Ericsson AB 2003-2011. All Rights Reserved. * * The contents of this file are subject to the Erlang Public License, * Version 1.1, (the "License"); you may not use this file except in @@ -64,8 +64,8 @@ static int zlib_init(void); static ErlDrvData zlib_start(ErlDrvPort port, char* buf); static void zlib_stop(ErlDrvData e); -static int zlib_ctl(ErlDrvData drv_data, unsigned int command, char *buf, - int len, char **rbuf, int rlen); +static ErlDrvSSizeT zlib_ctl(ErlDrvData drv_data, unsigned int command, char *buf, + ErlDrvSizeT len, char **rbuf, ErlDrvSizeT rlen); static void zlib_outputv(ErlDrvData drv_data, ErlIOVec *ev); ErlDrvEntry zlib_driver_entry = { @@ -162,12 +162,12 @@ static char* zlib_reason(int code, int* err) } -static int zlib_return(int code, char** rbuf, int rlen) +static ErlDrvSSizeT zlib_return(int code, char** rbuf, ErlDrvSizeT rlen) { int msg_code = 0; /* 0=ok, 1=error */ char* dst = *rbuf; char* src; - int len = 0; + ErlDrvSizeT len = 0; src = zlib_reason(code, &msg_code); *dst++ = msg_code; @@ -182,7 +182,8 @@ static int zlib_return(int code, char** rbuf, int rlen) return len; } -static int zlib_value2(int msg_code, int value, char** rbuf, int rlen) +static ErlDrvSSizeT zlib_value2(int msg_code, int value, + char** rbuf, ErlDrvSizeT rlen) { char* dst = *rbuf; @@ -197,7 +198,7 @@ static int zlib_value2(int msg_code, int value, char** rbuf, int rlen) return 5; } -static int zlib_value(int value, char** rbuf, int rlen) +static ErlDrvSSizeT zlib_value(int value, char** rbuf, ErlDrvSizeT rlen) { return zlib_value2(2, value, rbuf, rlen); } @@ -409,8 +410,8 @@ static void zlib_stop(ErlDrvData e) driver_free(d); } -static int zlib_ctl(ErlDrvData drv_data, unsigned int command, char *buf, - int len, char **rbuf, int rlen) +static ErlDrvSSizeT zlib_ctl(ErlDrvData drv_data, unsigned int command, char *buf, + ErlDrvSizeT len, char **rbuf, ErlDrvSizeT rlen) { ZLibData* d = (ZLibData*)drv_data; int res; diff --git a/erts/emulator/drivers/unix/ttsl_drv.c b/erts/emulator/drivers/unix/ttsl_drv.c index 45d39a559f..b29f80a8ba 100644 --- a/erts/emulator/drivers/unix/ttsl_drv.c +++ b/erts/emulator/drivers/unix/ttsl_drv.c @@ -1,7 +1,7 @@ /* * %CopyrightBegin% * - * Copyright Ericsson AB 1996-2010. All Rights Reserved. + * Copyright Ericsson AB 1996-2011. All Rights Reserved. * * The contents of this file are subject to the Erlang Public License, * Version 1.1, (the "License"); you may not use this file except in @@ -106,7 +106,7 @@ static int lpos; /* The current "cursor position" in the line buf /* Main interface functions. */ static void ttysl_stop(ErlDrvData); -static void ttysl_from_erlang(ErlDrvData, char*, int); +static void ttysl_from_erlang(ErlDrvData, char*, ErlDrvSizeT); static void ttysl_from_tty(ErlDrvData, ErlDrvEvent); static void ttysl_stop_select(ErlDrvEvent, void*); static Sint16 get_sint16(char*); @@ -141,7 +141,8 @@ static void update_cols(void); static int tty_init(int,int,int,int); static int tty_set(int); static int tty_reset(int); -static int ttysl_control(ErlDrvData, unsigned int, char *, int, char **, int); +static ErlDrvSSizeT ttysl_control(ErlDrvData, unsigned int, + char *, ErlDrvSizeT, char **, ErlDrvSizeT); #ifdef ERTS_NOT_USED static RETSIGTYPE suspend(int); #endif @@ -345,13 +346,13 @@ static void ttysl_get_window_size(Uint32 *width, Uint32 *height) *height = DEF_HEIGHT; } -static int ttysl_control(ErlDrvData drv_data, - unsigned int command, - char *buf, int len, - char **rbuf, int rlen) +static ErlDrvSSizeT ttysl_control(ErlDrvData drv_data, + unsigned int command, + char *buf, ErlDrvSizeT len, + char **rbuf, ErlDrvSizeT rlen) { char resbuff[2*sizeof(Uint32)]; - int res_size; + ErlDrvSizeT res_size; switch (command) { case CTRL_OP_GET_WINSIZE: { @@ -633,14 +634,14 @@ static int check_buf_size(byte *s, int n) } -static void ttysl_from_erlang(ErlDrvData ttysl_data, char* buf, int count) +static void ttysl_from_erlang(ErlDrvData ttysl_data, char* buf, ErlDrvSizeT count) { if (lpos > MAXSIZE) put_chars((byte*)"\n", 1); switch (buf[0]) { case OP_PUTC: - DEBUGLOG(("OP: Putc(%d)",count-1)); + DEBUGLOG(("OP: Putc(%lu)",(unsigned long) count-1)); if (check_buf_size((byte*)buf+1, count-1) == 0) return; put_chars((byte*)buf+1, count-1); diff --git a/erts/emulator/drivers/unix/unix_efile.c b/erts/emulator/drivers/unix/unix_efile.c index 4b3934657c..9160e2aed2 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 @@ -813,7 +816,6 @@ efile_fileinfo(Efile_error* errInfo, Efile_info* pInfo, char* name, int info_for_link) { struct stat statbuf; /* Information about the file */ - struct tm *timep; /* Broken-apart filetime. */ int result; #ifdef VXWORKS @@ -880,40 +882,17 @@ efile_fileinfo(Efile_error* errInfo, Efile_info* pInfo, else pInfo->type = FT_OTHER; -#if defined(HAVE_LOCALTIME_R) || defined(VXWORKS) - { - /* Use the reentrant version of localtime() */ - static struct tm local_tm; -#define localtime(a) (localtime_r((a), &local_tm), &local_tm) -#endif - - -#define GET_TIME(dst, src) \ - timep = localtime(&statbuf.src); \ - (dst).year = timep->tm_year+1900; \ - (dst).month = timep->tm_mon+1; \ - (dst).day = timep->tm_mday; \ - (dst).hour = timep->tm_hour; \ - (dst).minute = timep->tm_min; \ - (dst).second = timep->tm_sec - - GET_TIME(pInfo->accessTime, st_atime); - GET_TIME(pInfo->modifyTime, st_mtime); - GET_TIME(pInfo->cTime, st_ctime); - -#undef GET_TIME - -#if defined(HAVE_LOCALTIME_R) || defined(VXWORKS) - } -#endif + pInfo->accessTime = statbuf.st_atime; + pInfo->modifyTime = statbuf.st_mtime; + pInfo->cTime = statbuf.st_ctime; - pInfo->mode = statbuf.st_mode; - pInfo->links = statbuf.st_nlink; + pInfo->mode = statbuf.st_mode; + pInfo->links = statbuf.st_nlink; pInfo->major_device = statbuf.st_dev; pInfo->minor_device = statbuf.st_rdev; - pInfo->inode = statbuf.st_ino; - pInfo->uid = statbuf.st_uid; - pInfo->gid = statbuf.st_gid; + pInfo->inode = statbuf.st_ino; + pInfo->uid = statbuf.st_uid; + pInfo->gid = statbuf.st_gid; return 1; } @@ -921,6 +900,8 @@ efile_fileinfo(Efile_error* errInfo, Efile_info* pInfo, int efile_write_info(Efile_error *errInfo, Efile_info *pInfo, char *name) { + struct utimbuf tval; + CHECK_PATHLEN(name, errInfo); #ifdef VXWORKS @@ -973,38 +954,18 @@ efile_write_info(Efile_error *errInfo, Efile_info *pInfo, char *name) #endif /* !VXWORKS */ - if (pInfo->accessTime.year != -1 && pInfo->modifyTime.year != -1) { - struct utimbuf tval; - struct tm timebuf; - -#define MKTIME(tb, ts) \ - timebuf.tm_year = ts.year-1900; \ - timebuf.tm_mon = ts.month-1; \ - timebuf.tm_mday = ts.day; \ - timebuf.tm_hour = ts.hour; \ - timebuf.tm_min = ts.minute; \ - timebuf.tm_sec = ts.second; \ - timebuf.tm_isdst = -1; \ - if ((tb = mktime(&timebuf)) == (time_t) -1) { \ - errno = EINVAL; \ - return check_error(-1, errInfo); \ - } + tval.actime = pInfo->accessTime; + tval.modtime = pInfo->modifyTime; - MKTIME(tval.actime, pInfo->accessTime); - MKTIME(tval.modtime, pInfo->modifyTime); -#undef MKTIME - #ifdef VXWORKS - /* VxWorks' utime doesn't work when the file is a nfs mounted - * one, don't report error if utime fails. - */ - utime(name, &tval); - return 1; + /* VxWorks' utime doesn't work when the file is a nfs mounted + * one, don't report error if utime fails. + */ + utime(name, &tval); + return 1; #else - return check_error(utime(name, &tval), errInfo); + return check_error(utime(name, &tval), errInfo); #endif - } - return 1; } @@ -1464,3 +1425,109 @@ efile_fadvise(Efile_error* errInfo, int fd, Sint64 offset, return check_error(0, errInfo); #endif } + +#ifdef HAVE_SENDFILE + +// For some reason the maximum size_t cannot be used as the max size +// 3GB seems to work on all platforms +#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. + * + * All of the calls will split a command which tries to send more than + * SENDFILE_CHUNK_SIZE of data at once. + * + * On platforms where *nbytes of 0 does not mean the entire file, this is + * simulated. + * + * 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__) + ssize_t retval; + do { + // check if *nbytes is 0 or greater than chunk size + 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(__sun) && defined(__SVR4) && defined(HAVE_SENDFILEV) + ssize_t retval; + size_t len; + sendfilevec_t fdrec; + fdrec.sfv_fd = in_fd; + fdrec.sfv_flag = 0; + do { + fdrec.sfv_off = *offset; + len = 0; + // check if *nbytes is 0 or greater than chunk size + if (*nbytes == 0 || *nbytes > SENDFILE_CHUNK_SIZE) + fdrec.sfv_len = SENDFILE_CHUNK_SIZE; + else + fdrec.sfv_len = *nbytes; + retval = sendfilev(out_fd, &fdrec, 1, &len); + if (retval != -1 || errno == EAGAIN || errno == EINTR) { + *offset += len; + *nbytes -= len; + written += len; + } + } while (len == 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 chunk size + 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/registry_drv.c b/erts/emulator/drivers/win32/registry_drv.c index 05fd2ea55f..1fad34e380 100644 --- a/erts/emulator/drivers/win32/registry_drv.c +++ b/erts/emulator/drivers/win32/registry_drv.c @@ -1,7 +1,7 @@ /* * %CopyrightBegin% * - * Copyright Ericsson AB 1997-2009. All Rights Reserved. + * Copyright Ericsson AB 1997-2011. All Rights Reserved. * * The contents of this file are subject to the Erlang Public License, * Version 1.1, (the "License"); you may not use this file except in @@ -84,7 +84,7 @@ static int maperror(DWORD error); static int reg_init(void); static ErlDrvData reg_start(ErlDrvPort, char*); static void reg_stop(ErlDrvData); -static void reg_from_erlang(ErlDrvData, char*, int); +static void reg_from_erlang(ErlDrvData, char*, ErlDrvSizeT); struct erl_drv_entry registry_driver_entry = { reg_init, @@ -95,10 +95,21 @@ struct erl_drv_entry registry_driver_entry = { NULL, "registry__drv__", NULL, + NULL, /* handle */ + NULL, /* control */ + NULL, /* timeout */ + NULL, /* outputv */ + NULL, /* ready_async */ + NULL, /* flush */ + NULL, /* call */ + NULL, /* event */ + ERL_DRV_EXTENDED_MARKER, + ERL_DRV_EXTENDED_MAJOR_VERSION, + ERL_DRV_EXTENDED_MINOR_VERSION, + 0, NULL, NULL, NULL, - NULL }; static int @@ -158,7 +169,7 @@ reg_stop(ErlDrvData clientData) } static void -reg_from_erlang(ErlDrvData clientData, char* buf, int count) +reg_from_erlang(ErlDrvData clientData, char* buf, ErlDrvSizeT count) { RegPort* rp = (RegPort *) clientData; int cmd; @@ -301,7 +312,7 @@ reg_from_erlang(ErlDrvData clientData, char* buf, int count) buf = (char *) &dword; ASSERT(count == 4); } - result = RegSetValueEx(rp->hkey, name, 0, type, buf, count); + result = RegSetValueEx(rp->hkey, name, 0, type, buf, (DWORD)count); reply(rp, result); } break; diff --git a/erts/emulator/drivers/win32/ttsl_drv.c b/erts/emulator/drivers/win32/ttsl_drv.c index fd88dafd34..1a74d21e99 100644 --- a/erts/emulator/drivers/win32/ttsl_drv.c +++ b/erts/emulator/drivers/win32/ttsl_drv.c @@ -1,7 +1,7 @@ /* * %CopyrightBegin% * - * Copyright Ericsson AB 1996-2009. All Rights Reserved. + * Copyright Ericsson AB 1996-2011. All Rights Reserved. * * The contents of this file are subject to the Erlang Public License, * Version 1.1, (the "License"); you may not use this file except in @@ -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> @@ -80,8 +83,9 @@ int lpos; /* The current "cursor position" in the line buf static int ttysl_init(void); static ErlDrvData ttysl_start(ErlDrvPort, char*); static void ttysl_stop(ErlDrvData); -static int ttysl_control(ErlDrvData, unsigned int, char *, int, char **, int); -static void ttysl_from_erlang(ErlDrvData, char*, int); +static ErlDrvSSizeT ttysl_control(ErlDrvData, unsigned int, + char *, ErlDrvSizeT, char **, ErlDrvSizeT); +static void ttysl_from_erlang(ErlDrvData, char*, ErlDrvSizeT); static void ttysl_from_tty(ErlDrvData, ErlDrvEvent); static Sint16 get_sint16(char *s); @@ -117,7 +121,19 @@ struct erl_drv_entry ttsl_driver_entry = { NULL, NULL, ttysl_control, - NULL + NULL, /* timeout */ + NULL, /* outputv */ + NULL, /* ready_async */ + NULL, /* flush */ + NULL, /* call */ + NULL, /* event */ + ERL_DRV_EXTENDED_MARKER, + ERL_DRV_EXTENDED_MAJOR_VERSION, + ERL_DRV_EXTENDED_MINOR_VERSION, + 0, + NULL, + NULL, + NULL, }; static int utf8_mode = 0; @@ -151,13 +167,13 @@ static void ttysl_get_window_size(Uint32 *width, Uint32 *height) } -static int ttysl_control(ErlDrvData drv_data, +static ErlDrvSSizeT ttysl_control(ErlDrvData drv_data, unsigned int command, - char *buf, int len, - char **rbuf, int rlen) + char *buf, ErlDrvSizeT len, + char **rbuf, ErlDrvSizeT rlen) { char resbuff[2*sizeof(Uint32)]; - int res_size; + ErlDrvSizeT res_size; switch (command) { case CTRL_OP_GET_WINSIZE: { @@ -173,7 +189,7 @@ static int ttysl_control(ErlDrvData drv_data, res_size = 1; break; case CTRL_OP_SET_UNICODE_STATE: - if (len > 0) { + if (len != 0) { int m = (int) *buf; *resbuff = (utf8_mode) ? 1 : 0; res_size = 1; @@ -435,14 +451,14 @@ static int check_buf_size(byte *s, int n) } -static void ttysl_from_erlang(ErlDrvData ttysl_data, char* buf, int count) +static void ttysl_from_erlang(ErlDrvData ttysl_data, char* buf, ErlDrvSizeT count) { if (lpos > MAXSIZE) put_chars((byte*)"\n", 1); switch (buf[0]) { case OP_PUTC: - DEBUGLOG(("OP: Putc(%d)",count-1)); + DEBUGLOG(("OP: Putc(%I64u)",(unsigned long long)count-1)); if (check_buf_size((byte*)buf+1, count-1) == 0) return; put_chars((byte*)buf+1, count-1); 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..0d3d334154 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> @@ -42,6 +45,26 @@ #define INVALID_FILE_ATTRIBUTES ((DWORD) 0xFFFFFFFF) #endif +#define TICKS_PER_SECOND (10000000ULL) +#define EPOCH_DIFFERENCE (11644473600LL) + +#define FILETIME_TO_EPOCH(epoch, ft) \ + do { \ + ULARGE_INTEGER ull; \ + ull.LowPart = (ft).dwLowDateTime; \ + ull.HighPart = (ft).dwHighDateTime; \ + (epoch) = ((ull.QuadPart / TICKS_PER_SECOND) - EPOCH_DIFFERENCE); \ + } while(0) + +#define EPOCH_TO_FILETIME(ft, epoch) \ + do { \ + ULARGE_INTEGER ull; \ + ull.QuadPart = (((epoch) + EPOCH_DIFFERENCE) * TICKS_PER_SECOND); \ + (ft).dwLowDateTime = ull.LowPart; \ + (ft).dwHighDateTime = ull.HighPart; \ + } while(0) + + static int check_error(int result, Efile_error* errInfo); static int set_error(Efile_error* errInfo); static int is_root_unc_name(const WCHAR *path); @@ -861,14 +884,7 @@ efile_fileinfo(Efile_error* errInfo, Efile_info* pInfo, findbuf.cFileName[0] = L'\0'; pInfo->links = 1; - pInfo->modifyTime.year = 1980; - pInfo->modifyTime.month = 1; - pInfo->modifyTime.day = 1; - pInfo->modifyTime.hour = 0; - pInfo->modifyTime.minute = 0; - pInfo->modifyTime.second = 0; - - pInfo->accessTime = pInfo->modifyTime; + pInfo->cTime = pInfo->accessTime = pInfo->modifyTime = 0; } else { SYSTEMTIME SystemTime; FILETIME LocalFTime; @@ -902,34 +918,21 @@ efile_fileinfo(Efile_error* errInfo, Efile_info* pInfo, } } -#define GET_TIME(dst, src) \ -if (!FileTimeToLocalFileTime(&findbuf.src, &LocalFTime) || \ - !FileTimeToSystemTime(&LocalFTime, &SystemTime)) { \ - return set_error(errInfo); \ -} \ -(dst).year = SystemTime.wYear; \ -(dst).month = SystemTime.wMonth; \ -(dst).day = SystemTime.wDay; \ -(dst).hour = SystemTime.wHour; \ -(dst).minute = SystemTime.wMinute; \ -(dst).second = SystemTime.wSecond; - - GET_TIME(pInfo->modifyTime, ftLastWriteTime); + FILETIME_TO_EPOCH(pInfo->modifyTime, findbuf.ftLastWriteTime); if (findbuf.ftLastAccessTime.dwLowDateTime == 0 && findbuf.ftLastAccessTime.dwHighDateTime == 0) { pInfo->accessTime = pInfo->modifyTime; } else { - GET_TIME(pInfo->accessTime, ftLastAccessTime); + FILETIME_TO_EPOCH(pInfo->accessTime, findbuf.ftLastAccessTime); } if (findbuf.ftCreationTime.dwLowDateTime == 0 && findbuf.ftCreationTime.dwHighDateTime == 0) { pInfo->cTime = pInfo->modifyTime; } else { - GET_TIME(pInfo->cTime, ftCreationTime); + FILETIME_TO_EPOCH(pInfo->cTime ,findbuf.ftCreationTime); } -#undef GET_TIME FindClose(findhandle); } @@ -965,17 +968,12 @@ efile_write_info(Efile_error* errInfo, char* name) { SYSTEMTIME timebuf; - FILETIME LocalFileTime; FILETIME ModifyFileTime; FILETIME AccessFileTime; FILETIME CreationFileTime; HANDLE fd; - FILETIME* mtime = NULL; - FILETIME* atime = NULL; - FILETIME* ctime = NULL; DWORD attr; DWORD tempAttr; - BOOL modifyTime = FALSE; WCHAR *wname = (WCHAR *) name; /* @@ -1000,57 +998,36 @@ efile_write_info(Efile_error* errInfo, * Construct all file times. */ -#define MKTIME(tb, ts, ptr) \ - timebuf.wYear = ts.year; \ - timebuf.wMonth = ts.month; \ - timebuf.wDay = ts.day; \ - timebuf.wHour = ts.hour; \ - timebuf.wMinute = ts.minute; \ - timebuf.wSecond = ts.second; \ - timebuf.wMilliseconds = 0; \ - if (ts.year != -1) { \ - modifyTime = TRUE; \ - ptr = &tb; \ - if (!SystemTimeToFileTime(&timebuf, &LocalFileTime ) || \ - !LocalFileTimeToFileTime(&LocalFileTime, &tb)) { \ - errno = EINVAL; \ - return check_error(-1, errInfo); \ - } \ - } - - MKTIME(ModifyFileTime, pInfo->modifyTime, mtime); - MKTIME(AccessFileTime, pInfo->accessTime, atime); - MKTIME(CreationFileTime, pInfo->cTime, ctime); -#undef MKTIME + EPOCH_TO_FILETIME(ModifyFileTime, pInfo->modifyTime); + EPOCH_TO_FILETIME(AccessFileTime, pInfo->accessTime); + EPOCH_TO_FILETIME(CreationFileTime, pInfo->cTime); /* * If necessary, set the file times. */ - if (modifyTime) { - /* - * If the has read only access, we must temporarily turn on - * write access (this is necessary for native filesystems, - * but not for NFS filesystems). - */ + /* + * If the has read only access, we must temporarily turn on + * write access (this is necessary for native filesystems, + * but not for NFS filesystems). + */ - if (tempAttr & FILE_ATTRIBUTE_READONLY) { - tempAttr &= ~FILE_ATTRIBUTE_READONLY; - if (!SetFileAttributesW(wname, tempAttr)) { - return set_error(errInfo); - } + if (tempAttr & FILE_ATTRIBUTE_READONLY) { + tempAttr &= ~FILE_ATTRIBUTE_READONLY; + if (!SetFileAttributesW(wname, tempAttr)) { + return set_error(errInfo); } + } - fd = CreateFileW(wname, GENERIC_READ|GENERIC_WRITE, - FILE_SHARE_READ | FILE_SHARE_WRITE, - NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); - if (fd != INVALID_HANDLE_VALUE) { - BOOL result = SetFileTime(fd, ctime, atime, mtime); - if (!result) { - return set_error(errInfo); - } - CloseHandle(fd); + fd = CreateFileW(wname, GENERIC_READ|GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if (fd != INVALID_HANDLE_VALUE) { + BOOL result = SetFileTime(fd, &CreationFileTime, &AccessFileTime, &ModifyFileTime); + if (!result) { + return set_error(errInfo); } + CloseHandle(fd); } /* 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_mode_switch.c b/erts/emulator/hipe/hipe_mode_switch.c index 4d75883fc5..6a3ce5608f 100644 --- a/erts/emulator/hipe/hipe_mode_switch.c +++ b/erts/emulator/hipe/hipe_mode_switch.c @@ -337,14 +337,22 @@ Process *hipe_mode_switch(Process *p, unsigned cmd, Eterm reg[]) * stack: to this end hipe_${ARCH}_glue.S stores the BIF's * arity in p->hipe.narity. * - * If the BIF emptied the stack (typically hibernate), p->hipe.nsp is - * NULL and there is no need to get rid of stacked parameters. + * If the BIF emptied the stack (typically hibernate), p->hipe.nstack + * is NULL and there is no need to get rid of stacked parameters. */ unsigned int i, is_recursive = 0; - if (p->hipe.nsp != NULL) { + if (p->hipe.nstack != NULL) { + ASSERT(p->hipe.nsp != NULL); is_recursive = hipe_trap_from_native_is_recursive(p); } + else { + /* Some architectures (risc) need this re-reset of nsp as the + * BIF wrapper do not detect stack change and causes an obsolete + * stack pointer to be saved in p->hipe.nsp before return to us. + */ + p->hipe.nsp = NULL; + } /* Schedule next process if current process was hibernated or is waiting for messages */ diff --git a/erts/emulator/hipe/hipe_mode_switch.h b/erts/emulator/hipe/hipe_mode_switch.h index dbc2386e14..a3e908a3b3 100644 --- a/erts/emulator/hipe/hipe_mode_switch.h +++ b/erts/emulator/hipe/hipe_mode_switch.h @@ -49,7 +49,7 @@ #include "error.h" -int hipe_modeswitch_debug; +extern int hipe_modeswitch_debug; void hipe_mode_switch_init(void); void hipe_set_call_trap(Uint *bfun, void *nfun, int is_closure); 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..f94e0f2296 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); } @@ -1033,14 +1033,15 @@ static struct driver_data { /* Driver interfaces */ static ErlDrvData spawn_start(ErlDrvPort, char*, SysDriverOpts*); static ErlDrvData fd_start(ErlDrvPort, char*, SysDriverOpts*); -static int fd_control(ErlDrvData, unsigned int, char *, int, char **, int); +static ErlDrvSSizeT fd_control(ErlDrvData, unsigned int, char *, ErlDrvSizeT, + char **, ErlDrvSizeT); static ErlDrvData vanilla_start(ErlDrvPort, char*, SysDriverOpts*); static int spawn_init(void); static void fd_stop(ErlDrvData); static void stop(ErlDrvData); static void ready_input(ErlDrvData, ErlDrvEvent); static void ready_output(ErlDrvData, ErlDrvEvent); -static void output(ErlDrvData, char*, int); +static void output(ErlDrvData, char*, ErlDrvSizeT); static void outputv(ErlDrvData, ErlIOVec*); static void stop_select(ErlDrvEvent, void*); @@ -1726,10 +1727,10 @@ static int fd_get_window_size(int fd, Uint32 *width, Uint32 *height) return -1; } -static int fd_control(ErlDrvData drv_data, - unsigned int command, - char *buf, int len, - char **rbuf, int rlen) +static ErlDrvSSizeT fd_control(ErlDrvData drv_data, + unsigned int command, + char *buf, ErlDrvSizeT len, + char **rbuf, ErlDrvSizeT rlen) { int fd = (int)(long)drv_data; char resbuff[2*sizeof(Uint32)]; @@ -2001,18 +2002,20 @@ static void outputv(ErlDrvData e, ErlIOVec* ev) int ix = driver_data[fd].port_num; int pb = driver_data[fd].packet_bytes; int ofd = driver_data[fd].ofd; - int n; - int sz; + ssize_t n; + ErlDrvSizeT sz; char lb[4]; char* lbp; - int len = ev->size; + ErlDrvSizeT len = ev->size; /* (len > ((unsigned long)-1 >> (4-pb)*8)) */ + /* if (pb >= 0 && (len & (((ErlDrvSizeT)1 << (pb*8))) - 1) != len) {*/ if (((pb == 2) && (len > 0xffff)) || (pb == 1 && len > 0xff)) { driver_failure_posix(ix, EINVAL); return; /* -1; */ } - put_int32(len, lb); + /* Handles 0 <= pb <= 4 only */ + put_int32((Uint32) len, lb); lbp = lb + (4-pb); ev->iov[0].iov_base = lbp; @@ -2043,14 +2046,14 @@ static void outputv(ErlDrvData e, ErlIOVec* ev) } -static void output(ErlDrvData e, char* buf, int len) +static void output(ErlDrvData e, char* buf, ErlDrvSizeT len) { int fd = (int)(long)e; int ix = driver_data[fd].port_num; int pb = driver_data[fd].packet_bytes; int ofd = driver_data[fd].ofd; - int n; - int sz; + ssize_t n; + ErlDrvSizeT sz; char lb[4]; char* lbp; struct iovec iv[2]; 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/vxworks/sys.c b/erts/emulator/sys/vxworks/sys.c index d6d1fe64e0..739b026fb1 100644 --- a/erts/emulator/sys/vxworks/sys.c +++ b/erts/emulator/sys/vxworks/sys.c @@ -565,7 +565,7 @@ static void fd_stop(ErlDrvData); static void stop(ErlDrvData); static void ready_input(ErlDrvData fd, ErlDrvEvent ready_fd); static void ready_output(ErlDrvData fd, ErlDrvEvent ready_fd); -static void output(ErlDrvData fd, char *buf, int len); +static void output(ErlDrvData fd, char *buf, ErlDrvSizeT len); static void stop_select(ErlDrvEvent, void*); struct erl_drv_entry spawn_driver_entry = { @@ -1187,7 +1187,7 @@ static int sched_write(int port_num,int fd, char *buf, int len, int pb) } /* Fd is the value returned as drv_data by the start func */ -static void output(ErlDrvData drv_data, char *buf, int len) +static void output(ErlDrvData drv_data, char *buf, ErlDrvSizeT len) { int buf_done, port_num, wval, pb, ofd; byte lb[4]; 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..ec5141838a 100644 --- a/erts/emulator/sys/win32/erl_win_dyn_driver.h +++ b/erts/emulator/sys/win32/erl_win_dyn_driver.h @@ -39,11 +39,11 @@ WDD_TYPEDEF(int, driver_exit, (ErlDrvPort, int)); WDD_TYPEDEF(int, driver_failure_eof, (ErlDrvPort)); WDD_TYPEDEF(int, driver_select, (ErlDrvPort, ErlDrvEvent, int, int)); WDD_TYPEDEF(int, driver_event, (ErlDrvPort, ErlDrvEvent,ErlDrvEventData)); -WDD_TYPEDEF(int, driver_output, (ErlDrvPort, char *, int)); -WDD_TYPEDEF(int, driver_output2, (ErlDrvPort, char *, int,char *, int)); -WDD_TYPEDEF(int, driver_output_binary, (ErlDrvPort, char *, int,ErlDrvBinary*, int, int)); -WDD_TYPEDEF(int, driver_outputv, (ErlDrvPort, char*, int, ErlIOVec *,int)); -WDD_TYPEDEF(int, driver_vec_to_buf, (ErlIOVec *, char *, int)); +WDD_TYPEDEF(int, driver_output, (ErlDrvPort, char *, ErlDrvSizeT)); +WDD_TYPEDEF(int, driver_output2, (ErlDrvPort, char *, ErlDrvSizeT ,char *, ErlDrvSizeT)); +WDD_TYPEDEF(int, driver_output_binary, (ErlDrvPort, char *, ErlDrvSizeT, ErlDrvBinary*, ErlDrvSizeT, ErlDrvSizeT)); +WDD_TYPEDEF(int, driver_outputv, (ErlDrvPort, char*, ErlDrvSizeT, ErlIOVec *, ErlDrvSizeT)); +WDD_TYPEDEF(ErlDrvSizeT, driver_vec_to_buf, (ErlIOVec *, char *, ErlDrvSizeT)); WDD_TYPEDEF(int, driver_set_timer, (ErlDrvPort, unsigned long)); WDD_TYPEDEF(int, driver_cancel_timer, (ErlDrvPort)); WDD_TYPEDEF(int, driver_read_timer, (ErlDrvPort, unsigned long *)); @@ -51,22 +51,22 @@ WDD_TYPEDEF(char *, erl_errno_id, (int)); WDD_TYPEDEF(void, set_busy_port, (ErlDrvPort, int)); WDD_TYPEDEF(void, set_port_control_flags, (ErlDrvPort, int)); WDD_TYPEDEF(int, get_port_flags, (ErlDrvPort)); -WDD_TYPEDEF(ErlDrvBinary *, driver_alloc_binary, (int)); -WDD_TYPEDEF(ErlDrvBinary *, driver_realloc_binary, (ErlDrvBinary *, int)); +WDD_TYPEDEF(ErlDrvBinary *, driver_alloc_binary, (ErlDrvSizeT)); +WDD_TYPEDEF(ErlDrvBinary *, driver_realloc_binary, (ErlDrvBinary *, ErlDrvSizeT)); WDD_TYPEDEF(void, driver_free_binary, (ErlDrvBinary *)); -WDD_TYPEDEF(void *, driver_alloc, (size_t)); -WDD_TYPEDEF(void *, driver_realloc, (void *, size_t)); +WDD_TYPEDEF(void *, driver_alloc, (ErlDrvSizeT)); +WDD_TYPEDEF(void *, driver_realloc, (void *, ErlDrvSizeT)); WDD_TYPEDEF(void, driver_free, (void *)); -WDD_TYPEDEF(int, driver_enq, (ErlDrvPort, char*, int)); -WDD_TYPEDEF(int, driver_pushq, (ErlDrvPort, char*, int)); -WDD_TYPEDEF(int, driver_deq, (ErlDrvPort, int)); -WDD_TYPEDEF(int, driver_sizeq, (ErlDrvPort)); -WDD_TYPEDEF(int, driver_enq_bin, (ErlDrvPort, ErlDrvBinary *, int,int)); -WDD_TYPEDEF(int, driver_pushq_bin, (ErlDrvPort, ErlDrvBinary *, int,int)); -WDD_TYPEDEF(int, driver_peekqv, (ErlDrvPort, ErlIOVec *)); +WDD_TYPEDEF(int, driver_enq, (ErlDrvPort, char*, ErlDrvSizeT)); +WDD_TYPEDEF(int, driver_pushq, (ErlDrvPort, char*, ErlDrvSizeT)); +WDD_TYPEDEF(ErlDrvSizeT, driver_deq, (ErlDrvPort, ErlDrvSizeT)); +WDD_TYPEDEF(ErlDrvSizeT, driver_sizeq, (ErlDrvPort)); +WDD_TYPEDEF(int, driver_enq_bin, (ErlDrvPort, ErlDrvBinary *, ErlDrvSizeT, ErlDrvSizeT)); +WDD_TYPEDEF(int, driver_pushq_bin, (ErlDrvPort, ErlDrvBinary *, ErlDrvSizeT, ErlDrvSizeT)); +WDD_TYPEDEF(ErlDrvSizeT, driver_peekqv, (ErlDrvPort, ErlIOVec *)); WDD_TYPEDEF(SysIOVec *, driver_peekq, (ErlDrvPort, int *)); -WDD_TYPEDEF(int, driver_enqv, (ErlDrvPort, ErlIOVec *, int)); -WDD_TYPEDEF(int, driver_pushqv, (ErlDrvPort, ErlIOVec *, int)); +WDD_TYPEDEF(int, driver_enqv, (ErlDrvPort, ErlIOVec *, ErlDrvSizeT)); +WDD_TYPEDEF(int, driver_pushqv, (ErlDrvPort, ErlIOVec *, ErlDrvSizeT)); WDD_TYPEDEF(void, add_driver_entry, (ErlDrvEntry *)); WDD_TYPEDEF(int, remove_driver_entry, (ErlDrvEntry *)); WDD_TYPEDEF(ErlDrvTermData, driver_mk_atom, (char*)); @@ -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..e8453205ea 100644 --- a/erts/emulator/sys/win32/erl_win_sys.h +++ b/erts/emulator/sys/win32/erl_win_sys.h @@ -117,9 +117,30 @@ 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; + +struct tm *sys_localtime_r(time_t *epochs, struct tm *ptm); +struct tm *sys_gmtime_r(time_t *epochs, struct tm *ptm); +time_t sys_mktime( struct tm *ptm); + +#define localtime_r sys_localtime_r +#define HAVE_LOCALTIME_R 1 +#define gmtime_r sys_gmtime_r +#define HAVE_GMTIME_R +#define mktime sys_mktime + typedef struct { - long tv_sec; - long tv_usec; + erts_time_t tv_sec; + erts_time_t tv_usec; } SysTimeval; typedef struct { @@ -169,10 +190,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 +214,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 +226,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..b106f0932d 100644..100755 --- a/erts/emulator/sys/win32/sys.c +++ b/erts/emulator/sys/win32/sys.c @@ -474,7 +474,7 @@ static int spawn_init(void); static int fd_init(void); static void fd_stop(ErlDrvData); static void stop(ErlDrvData); -static void output(ErlDrvData, char*, int); +static void output(ErlDrvData, char*, ErlDrvSizeT); static void ready_input(ErlDrvData, ErlDrvEvent); static void ready_output(ErlDrvData, ErlDrvEvent); static void stop_select(ErlDrvEvent, void*); @@ -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; } @@ -2442,13 +2431,13 @@ threaded_exiter(LPVOID param) */ static void -output(ErlDrvData drv_data, char* buf, int len) +output(ErlDrvData drv_data, char* buf, ErlDrvSizeT len) /* long drv_data; /* The slot to use in the driver data table. * For Windows NT, this is *NOT* a file handle. * The handle is found in the driver data. */ -/* char *buf; /* Pointer to data to write to the port program. */ -/* int len; /* Number of bytes to write. */ +/* char *buf; /* Pointer to data to write to the port program. */ +/* ErlDrvSizeT len; /* Number of bytes to write. */ { DriverData* dp; int pb; /* The header size for this port. */ @@ -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..6362c1a06d 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" @@ -32,28 +35,336 @@ /******************* Routines for time measurement *********************/ #define EPOCH_JULIAN_DIFF LL_LITERAL(11644473600) +#define TICKS_PER_SECOND LL_LITERAL(10000000) +#define SECONDS_PER_DAY LL_LITERAL(86400) + +#define ULI_TO_FILETIME(ft,ull) \ + do { \ + (ft).dwLowDateTime = (ull).LowPart; \ + (ft).dwHighDateTime = (ull).HighPart; \ + } while (0) + +#define FILETIME_TO_ULI(ull,ft) \ + do { \ + (ull).LowPart = (ft).dwLowDateTime; \ + (ull).HighPart = (ft).dwHighDateTime; \ + } while (0) + +#define EPOCH_TO_FILETIME(ft, epoch) \ + do { \ + ULARGE_INTEGER ull; \ + ull.QuadPart = (((epoch) + EPOCH_JULIAN_DIFF) * TICKS_PER_SECOND); \ + ULI_TO_FILETIME(ft,ull); \ + } while(0) + +#define FILETIME_TO_EPOCH(epoch, ft) \ + do { \ + ULARGE_INTEGER ull; \ + FILETIME_TO_ULI(ull,ft); \ + (epoch) = ((ull.QuadPart / TICKS_PER_SECOND) - EPOCH_JULIAN_DIFF); \ + } while(0) + static SysHrTime wrap = 0; static DWORD last_tick_count = 0; +/* Getting timezone information is a heavy operation, so we want to do this + only once */ + +static TIME_ZONE_INFORMATION static_tzi; +static int have_static_tzi = 0; + +static int days_in_month[2][13] = { + {0,31,28,31,30,31,30,31,31,30,31,30,31}, + {0,31,29,31,30,31,30,31,31,30,31,30,31}}; + int sys_init_time(void) { + if(GetTimeZoneInformation(&static_tzi) && + static_tzi.StandardDate.wMonth != 0 && + static_tzi.DaylightDate.wMonth != 0) { + have_static_tzi = 1; + } return 1; } +/* Returns a switchtimes for DST as UTC filetimes given data from a + TIME_ZONE_INFORMATION, see sys_localtime_r for usage. */ +static void +get_dst_switchtime(DWORD year, + SYSTEMTIME dstinfo, LONG bias, + FILETIME *utc_switchtime) +{ + DWORD occu; + DWORD weekday,wday_1st; + DWORD day, days_in; + FILETIME tmp,tmp2; + ULARGE_INTEGER ull; + int leap_year = 0; + if (dstinfo.wYear != 0) { + /* A year specific transition, in which case the data in the structure + is already properly set for a specific year. Compare year + with parameter and see if they correspond, in that case generate a + filetime directly, otherwise set the filetime to 0 */ + if (year != dstinfo.wYear) { + utc_switchtime->dwLowDateTime = utc_switchtime->dwHighDateTime = 0; + return; + } + } else { + occu = dstinfo.wDay; + weekday = dstinfo.wDayOfWeek; + + dstinfo.wDayOfWeek = 0; + dstinfo.wDay = 1; + dstinfo.wYear = year; + + SystemTimeToFileTime(&dstinfo,&tmp); + ull.LowPart = tmp.dwLowDateTime; + ull.HighPart = tmp.dwHighDateTime; + + ull.QuadPart /= (TICKS_PER_SECOND*SECONDS_PER_DAY); /* Julian Day */ + wday_1st = (DWORD) ((ull.QuadPart + LL_LITERAL(1)) % LL_LITERAL(7)); + day = (weekday >= wday_1st) ? + weekday - wday_1st + 1 : + weekday - wday_1st + 8; + --occu; + if (((dstinfo.wYear % 4) == 0 && (dstinfo.wYear % 100) > 0) || + ((dstinfo.wYear % 400) == 0)) { + leap_year = 1; + } + days_in = days_in_month[leap_year][dstinfo.wMonth]; + while (occu > 0 && (day + 7 <= days_in)) { + --occu; + day += 7; + } + dstinfo.wDay = day; + } + SystemTimeToFileTime(&dstinfo,&tmp); + /* correct for bias */ + ull.LowPart = tmp.dwLowDateTime; + ull.HighPart = tmp.dwHighDateTime; + ull.QuadPart += (((LONGLONG) bias) * LL_LITERAL(60) * TICKS_PER_SECOND); + utc_switchtime->dwLowDateTime = ull.LowPart; + utc_switchtime->dwHighDateTime = ull.HighPart; + return; +} + +/* This function gives approximately the correct year from a FILETIME + Around the actual new year, it may return the wrong value, but that's OK + as DST never switches around new year. */ +static DWORD +approx_year(FILETIME ft) +{ + ULARGE_INTEGER ull; + FILETIME_TO_ULI(ull,ft); + ull.QuadPart /= LL_LITERAL(1000); + ull.QuadPart /= SECONDS_PER_DAY; + ull.QuadPart /= LL_LITERAL(3652425); + ull.QuadPart += 1601; + return (DWORD) ull.QuadPart; +} + +struct tm * +sys_localtime_r(time_t *epochs, struct tm *ptm) +{ + FILETIME ft,lft; + SYSTEMTIME st; + + if ((((*epochs) + EPOCH_JULIAN_DIFF) * TICKS_PER_SECOND) < 0LL) { + fprintf(stderr,"1\r\n"); fflush(stderr); + return NULL; + } + + EPOCH_TO_FILETIME(ft,*epochs); + ptm->tm_isdst = 0; + if (have_static_tzi) { + FILETIME dst_start, dst_stop; + ULARGE_INTEGER ull; + DWORD year = approx_year(ft); + get_dst_switchtime(year,static_tzi.DaylightDate, + static_tzi.Bias+static_tzi.StandardBias,&dst_start); + get_dst_switchtime(year,static_tzi.StandardDate, + static_tzi.Bias+static_tzi.StandardBias+ + static_tzi.DaylightBias, + &dst_stop); + FILETIME_TO_ULI(ull,ft); + + if (CompareFileTime(&ft,&dst_start) >= 0 && + CompareFileTime(&ft,&dst_stop) < 0) { + ull.QuadPart -= + ((LONGLONG) static_tzi.Bias+static_tzi.StandardBias+ + static_tzi.DaylightBias) * + LL_LITERAL(60) * TICKS_PER_SECOND; + ptm->tm_isdst = 1; + } else { + ull.QuadPart -= + ((LONGLONG) static_tzi.Bias+static_tzi.StandardBias) + * LL_LITERAL(60) * TICKS_PER_SECOND; + } + ULI_TO_FILETIME(ft,ull); + } else { + if (!FileTimeToLocalFileTime(&ft,&lft)) { + return NULL; + } + ft = lft; + } + + if (!FileTimeToSystemTime(&ft,&st)) { + return NULL; + } + + ptm->tm_year = (int) st.wYear - 1900; + ptm->tm_mon = (int) st.wMonth - 1; + ptm->tm_mday = (int) st.wDay; + ptm->tm_hour = (int) st.wHour; + ptm->tm_min = (int) st.wMinute; + ptm->tm_sec = (int) st.wSecond; + ptm->tm_wday = (int) st.wDayOfWeek; + { + int yday = ptm->tm_mday - 1; + int m = ptm->tm_mon; + int leap_year = 0; + if (((st.wYear % 4) == 0 && (st.wYear % 100) > 0) || + ((st.wYear % 400) == 0)) { + leap_year = 1; + } + while (m > 0) { + yday +=days_in_month[leap_year][m]; + --m; + } + ptm->tm_yday = yday; + } + return ptm; +} + +struct tm * +sys_gmtime_r(time_t *epochs, struct tm *ptm) +{ + FILETIME ft; + SYSTEMTIME st; + + if ((((*epochs) + EPOCH_JULIAN_DIFF) * TICKS_PER_SECOND) < 0LL) { + return NULL; + } + + EPOCH_TO_FILETIME(ft,*epochs); + + if (!FileTimeToSystemTime(&ft,&st)) { + return NULL; + } + + ptm->tm_year = (int) st.wYear - 1900; + ptm->tm_mon = (int) st.wMonth - 1; + ptm->tm_mday = (int) st.wDay; + ptm->tm_hour = (int) st.wHour; + ptm->tm_min = (int) st.wMinute; + ptm->tm_sec = (int) st.wSecond; + ptm->tm_wday = (int) st.wDayOfWeek; + ptm->tm_isdst = 0; + { + int yday = ptm->tm_mday - 1; + int m = ptm->tm_mon; + int leap_year = 0; + if (((st.wYear % 4) == 0 && (st.wYear % 100) > 0) || + ((st.wYear % 400) == 0)) { + leap_year = 1; + } + while (m > 0) { + yday +=days_in_month[leap_year][m]; + --m; + } + ptm->tm_yday = yday; + } + + return ptm; +} + +time_t +sys_mktime(struct tm *ptm) +{ + FILETIME ft; + SYSTEMTIME st; + int dst = 0; + time_t epochs; + + memset(&st,0,sizeof(st)); + /* Convert relevant parts of truct tm to SYSTEMTIME */ + st.wYear = (USHORT) (ptm->tm_year + 1900); + st.wMonth = (USHORT) (ptm->tm_mon + 1); + st.wDay = (USHORT) ptm->tm_mday; + st.wHour = (USHORT) ptm->tm_hour; + st.wMinute = (USHORT) ptm->tm_min; + st.wSecond = (USHORT) ptm->tm_sec; + + SystemTimeToFileTime(&st,&ft); + + /* ft is now some kind of local file time, but it may be wrong depending + on what is in the tm_dst field. We need to manually convert it to + UTC before turning it into epochs */ + + if (have_static_tzi) { + FILETIME dst_start, dst_stop; + ULARGE_INTEGER ull_start,ull_stop,ull_ft; + + FILETIME_TO_ULI(ull_ft,ft); + + /* Correct everything except DST */ + ull_ft.QuadPart += (static_tzi.Bias+static_tzi.StandardBias) + * LL_LITERAL(60) * TICKS_PER_SECOND; + + /* Determine if DST is active */ + if (ptm->tm_isdst >= 0) { + dst = ptm->tm_isdst; + } else if (static_tzi.DaylightDate.wMonth != 0){ + /* This is how windows mktime does it, meaning it does not + take nonexisting local times into account */ + get_dst_switchtime(st.wYear,static_tzi.DaylightDate, + static_tzi.Bias+static_tzi.StandardBias, + &dst_start); + get_dst_switchtime(st.wYear,static_tzi.StandardDate, + static_tzi.Bias+static_tzi.StandardBias+ + static_tzi.DaylightBias, + &dst_stop); + FILETIME_TO_ULI(ull_start,dst_start); + FILETIME_TO_ULI(ull_stop,dst_stop); + if ((ull_ft.QuadPart >= ull_start.QuadPart) && + (ull_ft.QuadPart < ull_stop.QuadPart)) { + /* We are in DST */ + dst = 1; + } + } + /* Correct for DST */ + if (dst) { + ull_ft.QuadPart += static_tzi.DaylightBias * + LL_LITERAL(60) * TICKS_PER_SECOND; + } + epochs = ((ull_ft.QuadPart / TICKS_PER_SECOND) - EPOCH_JULIAN_DIFF); + } else { + /* No DST, life is easy... */ + FILETIME lft; + LocalFileTimeToFileTime(&ft,&lft); + FILETIME_TO_EPOCH(epochs,lft); + } + /* Normalize the struct tm */ + sys_localtime_r(&epochs,ptm); + return epochs; +} + void sys_gettimeofday(SysTimeval *tv) { SYSTEMTIME t; FILETIME ft; - LONGLONG lft; + ULARGE_INTEGER ull; 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); + FILETIME_TO_ULI(ull,ft); + tv->tv_usec = (long) ((ull.QuadPart / LL_LITERAL(10)) % + LL_LITERAL(1000000)); + tv->tv_sec = (long) ((ull.QuadPart / LL_LITERAL(10000000)) - + EPOCH_JULIAN_DIFF); } SysHrTime @@ -88,9 +399,3 @@ sys_times(SysTimes *buffer) { buffer->tms_stime = (clock_t) (system & LL_LITERAL(0x7FFFFFFF)); return kernel_ticks; } - - - - - - diff --git a/erts/emulator/test/Makefile b/erts/emulator/test/Makefile index 4d0c87bf12..08d2066da3 100644 --- a/erts/emulator/test/Makefile +++ b/erts/emulator/test/Makefile @@ -61,7 +61,7 @@ MODULES= \ exception_SUITE \ float_SUITE \ fun_SUITE \ - fun_r12_SUITE \ + fun_r13_SUITE \ gc_SUITE \ guard_SUITE \ hash_SUITE \ diff --git a/erts/emulator/test/a_SUITE_data/timer_driver.c b/erts/emulator/test/a_SUITE_data/timer_driver.c index ef4dcdf501..44be94e0f0 100644 --- a/erts/emulator/test/a_SUITE_data/timer_driver.c +++ b/erts/emulator/test/a_SUITE_data/timer_driver.c @@ -17,7 +17,9 @@ #define CANCELLED 4 static ErlDrvData timer_start(ErlDrvPort, char*); -static void timer_stop(ErlDrvData), timer_read(ErlDrvData, char*, int), timer(ErlDrvData); +static void timer_stop(ErlDrvData), + timer_read(ErlDrvData, char*, ErlDrvSizeT), + timer(ErlDrvData); static ErlDrvEntry timer_driver_entry = { @@ -33,6 +35,16 @@ static ErlDrvEntry timer_driver_entry = NULL, timer, NULL, + NULL, + NULL, + NULL, + NULL, + ERL_DRV_EXTENDED_MARKER, + ERL_DRV_EXTENDED_MAJOR_VERSION, + ERL_DRV_EXTENDED_MINOR_VERSION, + 0, + NULL, + NULL, NULL }; @@ -47,8 +59,9 @@ static ErlDrvData timer_start(ErlDrvPort port, char *buf) } /* set the timer, this is monitored from erlang measuring the time */ -static void timer_read(ErlDrvData port, char *buf, int len) +static void timer_read(ErlDrvData p, char *buf, ErlDrvSizeT len) { + ErlDrvPort port = (ErlDrvPort) p; char reply[1]; if (buf[0] == START_TIMER) { @@ -62,8 +75,9 @@ static void timer_read(ErlDrvData port, char *buf, int len) } } -static void timer_stop(ErlDrvData port) +static void timer_stop(ErlDrvData p) { + ErlDrvPort port = (ErlDrvPort) p; driver_cancel_timer(port); } 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/alloc_SUITE_data/testcase_driver.c b/erts/emulator/test/alloc_SUITE_data/testcase_driver.c index 1e98844838..66971654a2 100644 --- a/erts/emulator/test/alloc_SUITE_data/testcase_driver.c +++ b/erts/emulator/test/alloc_SUITE_data/testcase_driver.c @@ -50,13 +50,32 @@ typedef struct { ErlDrvData testcase_drv_start(ErlDrvPort port, char *command); void testcase_drv_stop(ErlDrvData drv_data); -void testcase_drv_run(ErlDrvData drv_data, char *buf, int len); +void testcase_drv_run(ErlDrvData drv_data, char *buf, ErlDrvSizeT len); static ErlDrvEntry testcase_drv_entry = { NULL, testcase_drv_start, testcase_drv_stop, - testcase_drv_run + testcase_drv_run, + NULL, + NULL, + "testcase_drv", + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + ERL_DRV_EXTENDED_MARKER, + ERL_DRV_EXTENDED_MAJOR_VERSION, + ERL_DRV_EXTENDED_MINOR_VERSION, + 0, + NULL, + NULL, + NULL }; @@ -92,7 +111,7 @@ testcase_drv_stop(ErlDrvData drv_data) } void -testcase_drv_run(ErlDrvData drv_data, char *buf, int len) +testcase_drv_run(ErlDrvData drv_data, char *buf, ErlDrvSizeT len) { InternalTestCaseState_t *itcs = (InternalTestCaseState_t *) drv_data; ErlDrvTermData result_atom; 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/busy_port_SUITE_data/busy_drv.c b/erts/emulator/test/busy_port_SUITE_data/busy_drv.c index 1273d610ba..75106d3757 100644 --- a/erts/emulator/test/busy_port_SUITE_data/busy_drv.c +++ b/erts/emulator/test/busy_port_SUITE_data/busy_drv.c @@ -11,7 +11,8 @@ #define YES 1 static ErlDrvData busy_start(ErlDrvPort, char*); -static void busy_stop(ErlDrvData), busy_from_erlang(ErlDrvData, char*, int); +static void busy_stop(ErlDrvData), + busy_from_erlang(ErlDrvData, char*, ErlDrvSizeT); ErlDrvEntry busy_driver_entry = { @@ -23,6 +24,20 @@ ErlDrvEntry busy_driver_entry = NULL, "busy_drv", NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + ERL_DRV_EXTENDED_MARKER, + ERL_DRV_EXTENDED_MAJOR_VERSION, + ERL_DRV_EXTENDED_MINOR_VERSION, + 0, + NULL, + NULL, NULL }; @@ -73,7 +88,7 @@ static void busy_stop(ErlDrvData port) } static void -busy_from_erlang(ErlDrvData port, char* buf, int count) +busy_from_erlang(ErlDrvData port, char* buf, ErlDrvSizeT count) { if ((ErlDrvPort)port == slave_port) { set_busy_port(slave_port, next_slave_state); diff --git a/erts/emulator/test/busy_port_SUITE_data/hs_busy_drv.c b/erts/emulator/test/busy_port_SUITE_data/hs_busy_drv.c index 35919da2d0..9f6bd310c6 100644 --- a/erts/emulator/test/busy_port_SUITE_data/hs_busy_drv.c +++ b/erts/emulator/test/busy_port_SUITE_data/hs_busy_drv.c @@ -1,7 +1,7 @@ /* * %CopyrightBegin% * - * Copyright Ericsson AB 2009. All Rights Reserved. + * Copyright Ericsson AB 2009-2011. All Rights Reserved. * * The contents of this file are subject to the Erlang Public License, * Version 1.1, (the "License"); you may not use this file except in @@ -21,9 +21,9 @@ #include "erl_driver.h" ErlDrvData start(ErlDrvPort port, char *command); -void output(ErlDrvData drv_data, char *buf, int len); -int control(ErlDrvData drv_data, unsigned int command, char *buf, - int len, char **rbuf, int rlen); +void output(ErlDrvData drv_data, char *buf, ErlDrvSizeT len); +ErlDrvSSizeT control(ErlDrvData drv_data, unsigned int command, char *buf, + ErlDrvSizeT len, char **rbuf, ErlDrvSizeT rlen); static ErlDrvEntry busy_drv_entry = { NULL /* init */, @@ -61,7 +61,7 @@ ErlDrvData start(ErlDrvPort port, char *command) return (ErlDrvData) port; } -void output(ErlDrvData drv_data, char *buf, int len) +void output(ErlDrvData drv_data, char *buf, ErlDrvSizeT len) { int res; ErlDrvPort port = (ErlDrvPort) drv_data; @@ -76,8 +76,8 @@ void output(ErlDrvData drv_data, char *buf, int len) driver_failure_atom(port, "driver_output_term failed"); } -int control(ErlDrvData drv_data, unsigned int command, char *buf, - int len, char **rbuf, int rlen) +ErlDrvSSizeT control(ErlDrvData drv_data, unsigned int command, char *buf, + ErlDrvSizeT len, char **rbuf, ErlDrvSizeT rlen) { switch (command) { case 'B': /* busy */ diff --git a/erts/emulator/test/code_SUITE.erl b/erts/emulator/test/code_SUITE.erl index 2f9b01cc92..25ce94096f 100644 --- a/erts/emulator/test/code_SUITE.erl +++ b/erts/emulator/test/code_SUITE.erl @@ -20,7 +20,7 @@ -module(code_SUITE). -export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, init_per_group/2,end_per_group/2, - new_binary_types/1, + versions/1,new_binary_types/1, t_check_process_code/1,t_check_old_code/1, t_check_process_code_ets/1, external_fun/1,get_chunk/1,module_md5/1,make_stub/1, @@ -33,7 +33,7 @@ suite() -> [{ct_hooks,[ts_install_cth]}]. all() -> - [new_binary_types, t_check_process_code, + [versions, new_binary_types, t_check_process_code, t_check_process_code_ets, t_check_old_code, external_fun, get_chunk, module_md5, make_stub, make_stub_many_funs, constant_pools, constant_refc_binaries, false_dependency, @@ -56,6 +56,60 @@ init_per_group(_GroupName, Config) -> end_per_group(_GroupName, Config) -> Config. +%% Make sure that only two versions of a module can be loaded. +versions(Config) when is_list(Config) -> + V1 = compile_version(1, Config), + V2 = compile_version(2, Config), + V3 = compile_version(3, Config), + + {ok,P1,1} = load_version(V1, 1), + {ok,P2,2} = load_version(V2, 2), + {error,not_purged} = load_version(V2, 2), + {error,not_purged} = load_version(V3, 3), + + 1 = check_version(P1), + 2 = check_version(P2), + 2 = versions:version(), + + %% Kill processes, unload code. + P1 ! P2 ! done, + _ = monitor(process, P1), + _ = monitor(process, P2), + receive + {'DOWN',_,process,P1,normal} -> ok + end, + receive + {'DOWN',_,process,P2,normal} -> ok + end, + true = erlang:purge_module(versions), + true = erlang:delete_module(versions), + true = erlang:purge_module(versions), + ok. + +compile_version(Version, Config) -> + Data = ?config(data_dir, Config), + File = filename:join(Data, "versions"), + {ok,versions,Bin} = compile:file(File, [{d,'VERSION',Version}, + binary,report]), + Bin. + +load_version(Code, Ver) -> + case erlang:load_module(versions, Code) of + {module,versions} -> + Pid = spawn_link(versions, loop, []), + Ver = versions:version(), + Ver = check_version(Pid), + {ok,Pid,Ver}; + Error -> + Error + end. + +check_version(Pid) -> + Pid ! {self(),version}, + receive + {Pid,version,Version} -> + Version + end. new_binary_types(Config) when is_list(Config) -> ?line Data = ?config(data_dir, Config), diff --git a/erts/emulator/test/code_SUITE_data/versions.erl b/erts/emulator/test/code_SUITE_data/versions.erl new file mode 100644 index 0000000000..7a6fd8847d --- /dev/null +++ b/erts/emulator/test/code_SUITE_data/versions.erl @@ -0,0 +1,33 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2011. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +-module(versions). +-export([loop/0,version/0]). + +loop() -> + receive + {Pid,version} -> + Pid ! {self(),version,version()}, + loop(); + done -> + ok + end. + +version() -> + ?VERSION. diff --git a/erts/emulator/test/ddll_SUITE_data/dummy_drv.c b/erts/emulator/test/ddll_SUITE_data/dummy_drv.c index e0d5067743..86f2abf1b1 100644 --- a/erts/emulator/test/ddll_SUITE_data/dummy_drv.c +++ b/erts/emulator/test/ddll_SUITE_data/dummy_drv.c @@ -7,7 +7,7 @@ static ErlDrvPort erlang_port; static ErlDrvData dummy_start(ErlDrvPort, char*); -static void dummy_read(ErlDrvData port, char *buf, int count); +static void dummy_read(ErlDrvData port, char *buf, ErlDrvSizeT count); static void dummy_stop(ErlDrvData), easy_read(ErlDrvData, char*, int); static ErlDrvEntry dummy_driver_entry = { @@ -18,6 +18,21 @@ static ErlDrvEntry dummy_driver_entry = { NULL, NULL, "dummy_drv", + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + ERL_DRV_EXTENDED_MARKER, + ERL_DRV_EXTENDED_MAJOR_VERSION, + ERL_DRV_EXTENDED_MINOR_VERSION, + 0, + NULL, + NULL, NULL }; @@ -37,7 +52,7 @@ static ErlDrvData dummy_start(ErlDrvPort port,char *buf) return (ErlDrvData)port; } -static void dummy_read(ErlDrvData port, char *buf, int count) +static void dummy_read(ErlDrvData port, char *buf, ErlDrvSizeT count) { driver_output(erlang_port, buf, count); } diff --git a/erts/emulator/test/ddll_SUITE_data/echo_drv.c b/erts/emulator/test/ddll_SUITE_data/echo_drv.c index edf78a979d..2b3510c641 100644 --- a/erts/emulator/test/ddll_SUITE_data/echo_drv.c +++ b/erts/emulator/test/ddll_SUITE_data/echo_drv.c @@ -3,9 +3,10 @@ static ErlDrvPort erlang_port; static ErlDrvData echo_start(ErlDrvPort, char *); -static void from_erlang(ErlDrvData, char*, int); -static int echo_call(ErlDrvData drv_data, unsigned int command, char *buf, - int len, char **rbuf, int rlen, unsigned *ret_flags); +static void from_erlang(ErlDrvData, char*, ErlDrvSizeT); +static ErlDrvSSizeT echo_call(ErlDrvData drv_data, unsigned int command, + char *buf, ErlDrvSizeT len, + char **rbuf, ErlDrvSizeT rlen, unsigned *ret_flags); static ErlDrvEntry echo_driver_entry = { NULL, /* Init */ echo_start, @@ -21,7 +22,15 @@ static ErlDrvEntry echo_driver_entry = { NULL, NULL, NULL, - echo_call + echo_call, + NULL, + ERL_DRV_EXTENDED_MARKER, + ERL_DRV_EXTENDED_MAJOR_VERSION, + ERL_DRV_EXTENDED_MINOR_VERSION, + 0, + NULL, + NULL, + NULL }; DRIVER_INIT(echo_drv) @@ -36,14 +45,15 @@ echo_start(ErlDrvPort port, char *buf) } static void -from_erlang(ErlDrvData data, char *buf, int count) +from_erlang(ErlDrvData data, char *buf, ErlDrvSizeT count) { driver_output((ErlDrvPort) data, buf, count); } -static int -echo_call(ErlDrvData drv_data, unsigned int command, char *buf, - int len, char **rbuf, int rlen, unsigned *ret_flags) +static ErlDrvSSizeT +echo_call(ErlDrvData drv_data, unsigned int command, + char *buf, ErlDrvSizeT len, char **rbuf, ErlDrvSizeT rlen, + unsigned *ret_flags) { *rbuf = buf; *ret_flags |= DRIVER_CALL_KEEP_BUFFER; diff --git a/erts/emulator/test/ddll_SUITE_data/echo_drv_fail_init.c b/erts/emulator/test/ddll_SUITE_data/echo_drv_fail_init.c index 3b2a44d907..26aa03a012 100644 --- a/erts/emulator/test/ddll_SUITE_data/echo_drv_fail_init.c +++ b/erts/emulator/test/ddll_SUITE_data/echo_drv_fail_init.c @@ -3,9 +3,10 @@ static ErlDrvPort erlang_port; static ErlDrvData echo_start(ErlDrvPort, char *); -static void from_erlang(ErlDrvData, char*, int); -static int echo_call(ErlDrvData drv_data, unsigned int command, char *buf, - int len, char **rbuf, int rlen, unsigned *ret_flags); +static void from_erlang(ErlDrvData, char*, ErlDrvSizeT); +static ErlDrvSSizeT echo_call(ErlDrvData drv_data, unsigned int command, + char *buf, ErlDrvSizeT len, + char **rbuf, ErlDrvSizeT rlen, unsigned *ret_flags); static int echo_failing_init(void); static ErlDrvEntry echo_driver_entry = { @@ -23,7 +24,15 @@ static ErlDrvEntry echo_driver_entry = { NULL, NULL, NULL, - echo_call + echo_call, + NULL, + ERL_DRV_EXTENDED_MARKER, + ERL_DRV_EXTENDED_MAJOR_VERSION, + ERL_DRV_EXTENDED_MINOR_VERSION, + 0, + NULL, + NULL, + NULL }; DRIVER_INIT(echo_drv) @@ -43,14 +52,15 @@ echo_start(ErlDrvPort port, char *buf) } static void -from_erlang(ErlDrvData data, char *buf, int count) +from_erlang(ErlDrvData data, char *buf, ErlDrvSizeT count) { driver_output((ErlDrvPort) data, buf, count); } -static int -echo_call(ErlDrvData drv_data, unsigned int command, char *buf, - int len, char **rbuf, int rlen, unsigned *ret_flags) +static ErlDrvSSizeT +echo_call(ErlDrvData drv_data, unsigned int command, + char *buf, ErlDrvSizeT len, char **rbuf, ErlDrvSizeT rlen, + unsigned *ret_flags) { *rbuf = buf; *ret_flags |= DRIVER_CALL_KEEP_BUFFER; diff --git a/erts/emulator/test/ddll_SUITE_data/initfail_drv.c b/erts/emulator/test/ddll_SUITE_data/initfail_drv.c index b676ff5121..ad241b9c4f 100644 --- a/erts/emulator/test/ddll_SUITE_data/initfail_drv.c +++ b/erts/emulator/test/ddll_SUITE_data/initfail_drv.c @@ -3,7 +3,7 @@ static ErlDrvPort erlang_port; static ErlDrvData easy_start(ErlDrvPort, char*); -static void easy_stop(ErlDrvData), easy_read(ErlDrvData, char*, int); +static void easy_stop(ErlDrvData), easy_read(ErlDrvData, char*, ErlDrvSizeT); static ErlDrvEntry easy_driver_entry = { @@ -14,6 +14,21 @@ static ErlDrvEntry easy_driver_entry = NULL, NULL, "easy", + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + ERL_DRV_EXTENDED_MARKER, + ERL_DRV_EXTENDED_MAJOR_VERSION, + ERL_DRV_EXTENDED_MINOR_VERSION, + 0, + NULL, + NULL, NULL }; @@ -34,7 +49,7 @@ static ErlDrvData easy_start(ErlDrvPort port, char *buf) return (ErlDrvData)port; } -static void easy_read(ErlDrvData port, char *buf, int count) +static void easy_read(ErlDrvData port, char *buf, ErlDrvSizeT count) { driver_output(erlang_port, buf, count); } diff --git a/erts/emulator/test/ddll_SUITE_data/lock_drv.c b/erts/emulator/test/ddll_SUITE_data/lock_drv.c index 2ec8fa3a29..d2605c5bfc 100644 --- a/erts/emulator/test/ddll_SUITE_data/lock_drv.c +++ b/erts/emulator/test/ddll_SUITE_data/lock_drv.c @@ -3,9 +3,10 @@ static ErlDrvPort erlang_port; static ErlDrvData echo_start(ErlDrvPort, char *); -static void from_erlang(ErlDrvData, char*, int); -static int echo_call(ErlDrvData drv_data, unsigned int command, char *buf, - int len, char **rbuf, int rlen, unsigned *ret_flags); +static void from_erlang(ErlDrvData, char*, ErlDrvSizeT); +static ErlDrvSSizeT echo_call(ErlDrvData drv_data, unsigned int command, + char *buf, ErlDrvSizeT len, + char **rbuf, ErlDrvSizeT rlen, unsigned *ret_flags); static ErlDrvEntry echo_driver_entry = { NULL, /* Init */ echo_start, @@ -21,7 +22,15 @@ static ErlDrvEntry echo_driver_entry = { NULL, NULL, NULL, - echo_call + echo_call, + NULL, + ERL_DRV_EXTENDED_MARKER, + ERL_DRV_EXTENDED_MAJOR_VERSION, + ERL_DRV_EXTENDED_MINOR_VERSION, + 0, + NULL, + NULL, + NULL }; DRIVER_INIT(echo_drv) @@ -37,14 +46,15 @@ echo_start(ErlDrvPort port, char *buf) } static void -from_erlang(ErlDrvData data, char *buf, int count) +from_erlang(ErlDrvData data, char *buf, ErlDrvSizeT count) { driver_output((ErlDrvPort) data, buf, count); } -static int -echo_call(ErlDrvData drv_data, unsigned int command, char *buf, - int len, char **rbuf, int rlen, unsigned *ret_flags) +static ErlDrvSSizeT +echo_call(ErlDrvData drv_data, unsigned int command, + char *buf, ErlDrvSizeT len, char **rbuf, ErlDrvSizeT rlen, + unsigned *ret_flags) { ErlDrvPort port = (ErlDrvPort) drv_data; driver_lock_driver(port); diff --git a/erts/emulator/test/ddll_SUITE_data/noinit_drv.c b/erts/emulator/test/ddll_SUITE_data/noinit_drv.c index 931386a305..5abf5c4dc6 100644 --- a/erts/emulator/test/ddll_SUITE_data/noinit_drv.c +++ b/erts/emulator/test/ddll_SUITE_data/noinit_drv.c @@ -3,7 +3,7 @@ static ErlDrvPort erlang_port; static ErlDrvData easy_start(ErlDrvPort, char*); -static void easy_stop(ErlDrvData), easy_read(ErlDrvData, char*, int); +static void easy_stop(ErlDrvData), easy_read(ErlDrvData, char*, ErlDrvSizeT); static ErlDrvEntry easy_driver_entry = { @@ -14,6 +14,21 @@ static ErlDrvEntry easy_driver_entry = NULL, NULL, "easy", + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + ERL_DRV_EXTENDED_MARKER, + ERL_DRV_EXTENDED_MAJOR_VERSION, + ERL_DRV_EXTENDED_MINOR_VERSION, + 0, + NULL, + NULL, NULL }; @@ -28,7 +43,7 @@ DRIVER_INIT(noinit_drv) /* * Provoke an error when loading the module. */ -int no_driver_init(void *handle) +ErlDrvEntry* no_driver_init(void *handle) #endif { erlang_port = (ErlDrvPort)-1; @@ -46,7 +61,7 @@ static ErlDrvData easy_start(ErlDrvPort port,char *buf) return (ErlDrvData)port; } -static void easy_read(ErlDrvData port, char *buf, int count) +static void easy_read(ErlDrvData port, char *buf, ErlDrvSizeT count) { driver_output(erlang_port, buf, count); } diff --git a/erts/emulator/test/ddll_SUITE_data/wrongname_drv.c b/erts/emulator/test/ddll_SUITE_data/wrongname_drv.c index 3a35820ee7..ac7efa30de 100644 --- a/erts/emulator/test/ddll_SUITE_data/wrongname_drv.c +++ b/erts/emulator/test/ddll_SUITE_data/wrongname_drv.c @@ -7,7 +7,7 @@ static ErlDrvPort erlang_port; static ErlDrvData easy_start(ErlDrvPort, char*); -static void easy_stop(ErlDrvData), easy_read(ErlDrvData, char*, int); +static void easy_stop(ErlDrvData), easy_read(ErlDrvData, char*, ErlDrvSizeT); static ErlDrvEntry easy_driver_entry = { @@ -18,6 +18,21 @@ static ErlDrvEntry easy_driver_entry = NULL, NULL, "easy", + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + ERL_DRV_EXTENDED_MARKER, + ERL_DRV_EXTENDED_MAJOR_VERSION, + ERL_DRV_EXTENDED_MINOR_VERSION, + 0, + NULL, + NULL, NULL }; @@ -38,7 +53,7 @@ static ErlDrvData easy_start(ErlDrvPort port,char *buf) return (ErlDrvData)port; } -static void easy_read(ErlDrvData port, char *buf, int count) +static void easy_read(ErlDrvData port, char *buf, ErlDrvSizeT count) { driver_output(erlang_port, buf, count); } diff --git a/erts/emulator/test/decode_packet_SUITE.erl b/erts/emulator/test/decode_packet_SUITE.erl index c0499554eb..4acbe8c6e0 100644 --- a/erts/emulator/test/decode_packet_SUITE.erl +++ b/erts/emulator/test/decode_packet_SUITE.erl @@ -26,12 +26,14 @@ -export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, init_per_group/2,end_per_group/2, init_per_testcase/2,end_per_testcase/2, - basic/1, packet_size/1, neg/1, http/1, line/1, ssl/1, otp_8536/1]). + basic/1, packet_size/1, neg/1, http/1, line/1, ssl/1, otp_8536/1, + otp_9389/1, otp_9389_line/1]). suite() -> [{ct_hooks,[ts_install_cth]}]. all() -> - [basic, packet_size, neg, http, line, ssl, otp_8536]. + [basic, packet_size, neg, http, line, ssl, otp_8536, + otp_9389, otp_9389_line]. groups() -> []. @@ -251,6 +253,28 @@ packet_size(Config) when is_list(Config) -> ?line {error,_} = decode_pkt(4,<<Size:32,Packet/binary>>) end, lists:seq(-10,-1)), + + %% Test OTP-9389, long HTTP header lines. + Opts = [{packet_size, 128}], + Pkt = list_to_binary(["GET / HTTP/1.1\r\nHost: localhost\r\nLink: /", + string:chars($Y, 64), "\r\n\r\n"]), + <<Pkt1:50/binary, Pkt2/binary>> = Pkt, + ?line {ok, {http_request,'GET',{abs_path,"/"},{1,1}}, Rest1} = + erlang:decode_packet(http, Pkt1, Opts), + ?line {ok, {http_header,_,'Host',_,"localhost"}, Rest2} = + erlang:decode_packet(httph, Rest1, Opts), + ?line {more, undefined} = erlang:decode_packet(httph, Rest2, Opts), + ?line {ok, {http_header,_,"Link",_,_}, _} = + erlang:decode_packet(httph, list_to_binary([Rest2, Pkt2]), Opts), + + Pkt3 = list_to_binary(["GET / HTTP/1.1\r\nHost: localhost\r\nLink: /", + string:chars($Y, 129), "\r\n\r\n"]), + ?line {ok, {http_request,'GET',{abs_path,"/"},{1,1}}, Rest3} = + erlang:decode_packet(http, Pkt3, Opts), + ?line {ok, {http_header,_,'Host',_,"localhost"}, Rest4} = + erlang:decode_packet(httph, Rest3, Opts), + ?line {error, invalid} = erlang:decode_packet(httph, Rest4, Opts), + ok. @@ -557,3 +581,35 @@ decode_pkt(Type,Bin,Opts) -> %%io:format(" -> ~p\n",[Res]), Res. +otp_9389(doc) -> ["Verify line_length works correctly for HTTP headers"]; +otp_9389(suite) -> []; +otp_9389(Config) when is_list(Config) -> + Opts = [{packet_size, 16384}, {line_length, 3000}], + Pkt = list_to_binary(["GET / HTTP/1.1\r\nHost: localhost\r\nLink: /", + string:chars($X, 8192), + "\r\nContent-Length: 0\r\n\r\n"]), + <<Pkt1:5000/binary, Pkt2/binary>> = Pkt, + {ok, {http_request,'GET',{abs_path,"/"},{1,1}}, Rest1} = + erlang:decode_packet(http, Pkt1, Opts), + {ok, {http_header,_,'Host',_,"localhost"}, Rest2} = + erlang:decode_packet(httph, Rest1, Opts), + {more, undefined} = erlang:decode_packet(httph, Rest2, Opts), + {ok, {http_header,_,"Link",_,Link}, Rest3} = + erlang:decode_packet(httph, list_to_binary([Rest2, Pkt2]), Opts), + true = (length(Link) > 8000), + {ok, {http_header,_,'Content-Length',_,"0"}, <<"\r\n">>} = + erlang:decode_packet(httph, Rest3, Opts), + ok. + +otp_9389_line(doc) -> ["Verify packet_size works correctly for line mode"]; +otp_9389_line(suite) -> []; +otp_9389_line(Config) when is_list(Config) -> + Opts = [{packet_size, 20}], + Line1 = <<"0123456789012345678\n">>, + Line2 = <<"0123456789\n">>, + Line3 = <<"01234567890123456789\n">>, + Pkt = list_to_binary([Line1, Line2, Line3]), + ?line {ok, Line1, Rest1} = erlang:decode_packet(line, Pkt, Opts), + ?line {ok, Line2, Rest2} = erlang:decode_packet(line, Rest1, Opts), + ?line {error, invalid} = erlang:decode_packet(line, Rest2, Opts), + ok. diff --git a/erts/emulator/test/distribution_SUITE.erl b/erts/emulator/test/distribution_SUITE.erl index 19281f6d58..08308629fe 100644 --- a/erts/emulator/test/distribution_SUITE.erl +++ b/erts/emulator/test/distribution_SUITE.erl @@ -18,7 +18,7 @@ %% -module(distribution_SUITE). --compile(r12). +-compile(r13). %% Tests distribution and the tcp driver. @@ -37,7 +37,7 @@ dist_auto_connect_never/1, dist_auto_connect_once/1, dist_parallel_send/1, atom_roundtrip/1, - atom_roundtrip_r12b/1, + atom_roundtrip_r13b/1, contended_atom_cache_entry/1, bad_dist_structure/1, bad_dist_ext_receive/1, @@ -62,7 +62,7 @@ all() -> link_to_dead_new_node, applied_monitor_node, ref_port_roundtrip, nil_roundtrip, stop_dist, {group, trap_bif}, {group, dist_auto_connect}, - dist_parallel_send, atom_roundtrip, atom_roundtrip_r12b, + dist_parallel_send, atom_roundtrip, atom_roundtrip_r13b, contended_atom_cache_entry, bad_dist_structure, {group, bad_dist_ext}]. groups() -> @@ -1100,17 +1100,17 @@ atom_roundtrip(Config) when is_list(Config) -> ?line stop_node(Node), ?line ok. -atom_roundtrip_r12b(Config) when is_list(Config) -> - case ?t:is_release_available("r12b") of +atom_roundtrip_r13b(Config) when is_list(Config) -> + case ?t:is_release_available("r13b") of true -> ?line AtomData = atom_data(), ?line verify_atom_data(AtomData), - ?line {ok, Node} = start_node(Config, [], "r12b"), + ?line {ok, Node} = start_node(Config, [], "r13b"), ?line do_atom_roundtrip(Node, AtomData), ?line stop_node(Node), ?line ok; false -> - ?line {skip,"No OTP R12B available"} + ?line {skip,"No OTP R13B available"} end. do_atom_roundtrip(Node, AtomData) -> diff --git a/erts/emulator/test/driver_SUITE.erl b/erts/emulator/test/driver_SUITE.erl index c07dbc5871..643357263c 100644 --- a/erts/emulator/test/driver_SUITE.erl +++ b/erts/emulator/test/driver_SUITE.erl @@ -47,8 +47,8 @@ fd_change/1, steal_control/1, otp_6602/1, - 'driver_system_info_ver1.0'/1, - 'driver_system_info_ver1.1'/1, + driver_system_info_base_ver/1, + driver_system_info_prev_ver/1, driver_system_info_current_ver/1, driver_monitor/1, @@ -135,8 +135,8 @@ all() -> [outputv_errors, outputv_echo, queue_echo, {group, timer}, driver_unloaded, io_ready_exit, use_fallback_pollset, bad_fd_in_pollset, driver_event, fd_change, - steal_control, otp_6602, 'driver_system_info_ver1.0', - 'driver_system_info_ver1.1', + steal_control, otp_6602, driver_system_info_base_ver, + driver_system_info_prev_ver, driver_system_info_current_ver, driver_monitor, {group, ioq_exit}, zero_extended_marker_garb_drv, invalid_extended_marker_drv, larger_major_vsn_drv, @@ -1083,19 +1083,19 @@ otp_6602(Config) when is_list(Config) -> -define(EXPECTED_SYSTEM_INFO_NAMES, ?EXPECTED_SYSTEM_INFO_NAMES2). -'driver_system_info_ver1.0'(doc) -> +'driver_system_info_base_ver'(doc) -> []; -'driver_system_info_ver1.0'(suite) -> +'driver_system_info_base_ver'(suite) -> []; -'driver_system_info_ver1.0'(Config) when is_list(Config) -> - ?line driver_system_info_test(Config, sys_info_1_0_drv). +'driver_system_info_base_ver'(Config) when is_list(Config) -> + ?line driver_system_info_test(Config, sys_info_base_drv). -'driver_system_info_ver1.1'(doc) -> +'driver_system_info_prev_ver'(doc) -> []; -'driver_system_info_ver1.1'(suite) -> +'driver_system_info_prev_ver'(suite) -> []; -'driver_system_info_ver1.1'(Config) when is_list(Config) -> - ?line driver_system_info_test(Config, sys_info_1_1_drv). +'driver_system_info_prev_ver'(Config) when is_list(Config) -> + ?line driver_system_info_test(Config, sys_info_prev_drv). driver_system_info_current_ver(doc) -> []; @@ -1796,7 +1796,7 @@ driver_select_use0(Config) -> thread_mseg_alloc_cache_clean(Config) when is_list(Config) -> case {erlang:system_info(threads), - mseg_inst_info(0), + erlang:system_info({allocator,mseg_alloc}), driver_alloc_sbct()} of {_, false, _} -> ?line {skipped, "No mseg_alloc"}; @@ -2185,6 +2185,14 @@ wait_deallocations() -> end. driver_alloc_size() -> + case erlang:system_info(smp_support) of + true -> + ok; + false -> + %% driver_alloc also used by elements in lock-free queues, + %% give these some time to be deallocated... + receive after 100 -> ok end + end, wait_deallocations(), case erlang:system_info({allocator_sizes, driver_alloc}) of false -> diff --git a/erts/emulator/test/driver_SUITE_data/Makefile.src b/erts/emulator/test/driver_SUITE_data/Makefile.src index dd48f6a0f7..9cc107cc66 100644 --- a/erts/emulator/test/driver_SUITE_data/Makefile.src +++ b/erts/emulator/test/driver_SUITE_data/Makefile.src @@ -16,8 +16,8 @@ MISC_DRVS = outputv_drv@dll@ \ thr_free_drv@dll@ \ async_blast_drv@dll@ -SYS_INFO_DRVS = sys_info_1_0_drv@dll@ \ - sys_info_1_1_drv@dll@ \ +SYS_INFO_DRVS = sys_info_base_drv@dll@ \ + sys_info_prev_drv@dll@ \ sys_info_curr_drv@dll@ VSN_MISMATCH_DRVS = zero_extended_marker_garb_drv@dll@ \ diff --git a/erts/emulator/test/driver_SUITE_data/async_blast_drv.c b/erts/emulator/test/driver_SUITE_data/async_blast_drv.c index 3821f7e3dc..c2086c5860 100644 --- a/erts/emulator/test/driver_SUITE_data/async_blast_drv.c +++ b/erts/emulator/test/driver_SUITE_data/async_blast_drv.c @@ -25,7 +25,7 @@ static void stop(ErlDrvData drv_data); static ErlDrvData start(ErlDrvPort port, char *command); static void output(ErlDrvData drv_data, - char *buf, int len); + char *buf, ErlDrvSizeT len); static void ready_async(ErlDrvData drv_data, ErlDrvThreadData thread_data); @@ -107,7 +107,7 @@ static void ready_async(ErlDrvData drv_data, } static void output(ErlDrvData drv_data, - char *buf, int len) + char *buf, ErlDrvSizeT len) { async_blast_data_t *abd = (async_blast_data_t *) drv_data; if (abd->counter == 0) { diff --git a/erts/emulator/test/driver_SUITE_data/caller_drv.c b/erts/emulator/test/driver_SUITE_data/caller_drv.c index a78d51966f..1ed20b0638 100644 --- a/erts/emulator/test/driver_SUITE_data/caller_drv.c +++ b/erts/emulator/test/driver_SUITE_data/caller_drv.c @@ -23,17 +23,17 @@ static ErlDrvData start(ErlDrvPort port, char *command); static void output(ErlDrvData drv_data, - char *buf, int len); + char *buf, ErlDrvSizeT len); static void outputv(ErlDrvData drv_data, ErlIOVec *ev); -static int control(ErlDrvData drv_data, - unsigned int command, char *buf, - int len, char **rbuf, int rlen); -static int call(ErlDrvData drv_data, - unsigned int command, - char *buf, int len, - char **rbuf, int rlen, - unsigned int *flags); +static ErlDrvSSizeT control(ErlDrvData drv_data, + unsigned int command, char *buf, + ErlDrvSizeT len, char **rbuf, ErlDrvSizeT rlen); +static ErlDrvSSizeT call(ErlDrvData drv_data, + unsigned int command, + char *buf, ErlDrvSizeT len, + char **rbuf, ErlDrvSizeT rlen, + unsigned int *flags); static ErlDrvEntry caller_drv_entry = { NULL /* init */, @@ -98,7 +98,7 @@ start(ErlDrvPort port, char *command) } static void -output(ErlDrvData drv_data, char *buf, int len) +output(ErlDrvData drv_data, char *buf, ErlDrvSizeT len) { send_caller(drv_data, "output"); } @@ -109,20 +109,20 @@ outputv(ErlDrvData drv_data, ErlIOVec *ev) send_caller(drv_data, "outputv"); } -static int +static ErlDrvSSizeT control(ErlDrvData drv_data, unsigned int command, char *buf, - int len, char **rbuf, int rlen) + ErlDrvSizeT len, char **rbuf, ErlDrvSizeT rlen) { send_caller(drv_data, "control"); return 0; } -static int +static ErlDrvSSizeT call(ErlDrvData drv_data, unsigned int command, - char *buf, int len, - char **rbuf, int rlen, + char *buf, ErlDrvSizeT len, + char **rbuf, ErlDrvSizeT rlen, unsigned int *flags) { /* echo call */ diff --git a/erts/emulator/test/driver_SUITE_data/chkio_drv.c b/erts/emulator/test/driver_SUITE_data/chkio_drv.c index bbdb09cfcb..40f1ad4fea 100644 --- a/erts/emulator/test/driver_SUITE_data/chkio_drv.c +++ b/erts/emulator/test/driver_SUITE_data/chkio_drv.c @@ -141,8 +141,8 @@ static void chkio_drv_stop(ErlDrvData); static void chkio_drv_ready_input(ErlDrvData, ErlDrvEvent); static void chkio_drv_ready_output(ErlDrvData, ErlDrvEvent); static void chkio_drv_ready_event(ErlDrvData, ErlDrvEvent, ErlDrvEventData); -static int chkio_drv_control(ErlDrvData, unsigned int, - char *, int, char **, int); +static ErlDrvSSizeT chkio_drv_control(ErlDrvData, unsigned int, + char *, ErlDrvSizeT, char **, ErlDrvSizeT); static void chkio_drv_timeout(ErlDrvData); static void chkio_drv_stop_select(ErlDrvEvent, void*); @@ -188,7 +188,7 @@ stop_use_fallback_pollset(ChkioDrvData *cddp) for (i = 0; i < CHKIO_FALLBACK_FDS; i++) { if (cbdp->dev_null[i].fd >= 0) { if (driver_select(cddp->port, - (ErlDrvEvent) cbdp->dev_null[i].fd, + (ErlDrvEvent) (ErlDrvSInt) cbdp->dev_null[i].fd, DO_WRITE, 0) != 0) { fprintf(stderr, @@ -200,7 +200,7 @@ stop_use_fallback_pollset(ChkioDrvData *cddp) } if (cbdp->dev_zero[i].fd >= 0) { if (driver_select(cddp->port, - (ErlDrvEvent) cbdp->dev_zero[i].fd, + (ErlDrvEvent) (ErlDrvSInt) cbdp->dev_zero[i].fd, DO_READ, 0) != 0) { fprintf(stderr, @@ -212,7 +212,7 @@ stop_use_fallback_pollset(ChkioDrvData *cddp) } if (cbdp->pipe_in[i].fd >= 0) { if (driver_select(cddp->port, - (ErlDrvEvent) cbdp->pipe_in[i].fd, + (ErlDrvEvent) (ErlDrvSInt) cbdp->pipe_in[i].fd, DO_READ, 0) != 0) { fprintf(stderr, @@ -224,7 +224,7 @@ stop_use_fallback_pollset(ChkioDrvData *cddp) } if (cbdp->pipe_out[i].fd >= 0) { if (driver_select(cddp->port, - (ErlDrvEvent) cbdp->pipe_out[i].fd, + (ErlDrvEvent) (ErlDrvSInt) cbdp->pipe_out[i].fd, DO_WRITE, 0) != 0) { fprintf(stderr, @@ -249,11 +249,11 @@ stop_driver_event(ChkioDrvData *cddp) cddp->test_data = NULL; if (cdep->in_fd >= 0) { - driver_event(cddp->port, (ErlDrvEvent) cdep->in_fd, NULL); + driver_event(cddp->port, (ErlDrvEvent) (ErlDrvSInt) cdep->in_fd, NULL); close(cdep->in_fd); } if (cdep->out_fd >= 0) { - driver_event(cddp->port, (ErlDrvEvent) cdep->out_fd, NULL); + driver_event(cddp->port, (ErlDrvEvent) (ErlDrvSInt) cdep->out_fd, NULL); close(cdep->out_fd); } driver_free(cdep); @@ -268,7 +268,7 @@ stop_fd_change(ChkioDrvData *cddp) cddp->test_data = NULL; driver_cancel_timer(cddp->port); if (cfcp->fds[0] >= 0) { - driver_select(cddp->port, (ErlDrvEvent) cfcp->fds[0], DO_READ, 0); + driver_select(cddp->port, (ErlDrvEvent) (ErlDrvSInt) cfcp->fds[0], DO_READ, 0); close(cfcp->fds[0]); close(cfcp->fds[1]); } @@ -282,8 +282,8 @@ stop_bad_fd_in_pollset(ChkioDrvData *cddp) if (cddp->test_data) { ChkioBadFdInPollset *bfipp = (ChkioBadFdInPollset *) cddp->test_data; cddp->test_data = NULL; - driver_select(cddp->port, (ErlDrvEvent) bfipp->fds[0], DO_WRITE, 0); - driver_select(cddp->port, (ErlDrvEvent) bfipp->fds[1], DO_READ, 0); + driver_select(cddp->port, (ErlDrvEvent) (ErlDrvSInt) bfipp->fds[0], DO_WRITE, 0); + driver_select(cddp->port, (ErlDrvEvent) (ErlDrvSInt) bfipp->fds[1], DO_READ, 0); driver_free((void *) bfipp); } } @@ -296,21 +296,21 @@ stop_steal(ChkioDrvData *cddp) cddp->test_data = NULL; if (csp->driver_select_fds[0] >= 0) driver_select(cddp->port, - (ErlDrvEvent) csp->driver_select_fds[0], + (ErlDrvEvent) (ErlDrvSInt) csp->driver_select_fds[0], DO_READ, 0); if (csp->driver_select_fds[1] >= 0) driver_select(cddp->port, - (ErlDrvEvent) csp->driver_select_fds[1], + (ErlDrvEvent) (ErlDrvSInt) csp->driver_select_fds[1], DO_WRITE, 0); if (csp->driver_event_fds[0] >= 0) driver_event(cddp->port, - (ErlDrvEvent) csp->driver_event_fds[0], + (ErlDrvEvent) (ErlDrvSInt) csp->driver_event_fds[0], NULL); if (csp->driver_event_fds[1] >= 0) driver_event(cddp->port, - (ErlDrvEvent) csp->driver_event_fds[1], + (ErlDrvEvent) (ErlDrvSInt) csp->driver_event_fds[1], NULL); driver_free(csp); } @@ -353,7 +353,7 @@ static void free_smp_select(ChkioSmpSelect* pip, ErlDrvPort port) abort(); } case Selected: - driver_select(port, (ErlDrvEvent)pip->read_fd, DO_READ, 0); + driver_select(port, (ErlDrvEvent)(ErlDrvSInt)pip->read_fd, DO_READ, 0); /*fall through*/ case Opened: close(pip->read_fd); @@ -475,8 +475,8 @@ chkio_drv_stop(ErlDrvData drv_data) { fprintf(stderr, "%s:%d: Failed to open /dev/null\n", __FILE__, __LINE__); } - driver_select(cddp->port, (ErlDrvEvent) fd, DO_WRITE, 1); - driver_select(cddp->port, (ErlDrvEvent) fd, DO_WRITE, 0); + driver_select(cddp->port, (ErlDrvEvent) (ErlDrvSInt) fd, DO_WRITE, 1); + driver_select(cddp->port, (ErlDrvEvent) (ErlDrvSInt) fd, DO_WRITE, 0); close(fd); @@ -491,7 +491,7 @@ chkio_drv_ready_output(ErlDrvData drv_data, ErlDrvEvent event) { #ifdef UNIX ChkioDrvData *cddp = (ChkioDrvData *) drv_data; - int fd = (int) event; + int fd = (int) (ErlDrvSInt) event; switch (cddp->test) { case CHKIO_USE_FALLBACK_POLLSET: { @@ -533,7 +533,7 @@ chkio_drv_ready_input(ErlDrvData drv_data, ErlDrvEvent event) { #ifdef UNIX ChkioDrvData *cddp = (ChkioDrvData *) drv_data; - int fd = (int) event; + int fd = (int) (ErlDrvSInt) event; switch (cddp->test) { case CHKIO_USE_FALLBACK_POLLSET: { @@ -630,7 +630,7 @@ chkio_drv_ready_event(ErlDrvData drv_data, case CHKIO_DRIVER_EVENT: { #ifdef HAVE_POLL_H ChkioDriverEvent *cdep = cddp->test_data; - int fd = (int) event; + int fd = (int) (ErlDrvSInt) event; if (fd == cdep->in_fd) { if (event_data->events == POLLIN && event_data->revents == POLLIN) { @@ -679,7 +679,7 @@ chkio_drv_timeout(ErlDrvData drv_data) int in_fd = cfcp->fds[0]; int out_fd = cfcp->fds[1]; if (in_fd >= 0) { - if (driver_select(cddp->port, (ErlDrvEvent) in_fd, DO_READ, 0) < 0) + if (driver_select(cddp->port, (ErlDrvEvent) (ErlDrvSInt) in_fd, DO_READ, 0) < 0) driver_failure_atom(cddp->port, "deselect_failed"); (void) write(out_fd, (void *) "!", 1); close(out_fd); @@ -689,7 +689,7 @@ chkio_drv_timeout(ErlDrvData drv_data) driver_failure_posix(cddp->port, errno); } else { - if (driver_select(cddp->port, (ErlDrvEvent) cfcp->fds[0], + if (driver_select(cddp->port, (ErlDrvEvent) (ErlDrvSInt) cfcp->fds[0], DO_READ, 1) < 0) driver_failure_atom(cddp->port, "select_failed"); if (cfcp->fds[0] == in_fd) @@ -709,14 +709,14 @@ chkio_drv_timeout(ErlDrvData drv_data) #endif /* UNIX */ } -static int +static ErlDrvSSizeT chkio_drv_control(ErlDrvData drv_data, unsigned int command, - char *buf, int len, - char **rbuf, int rlen) + char *buf, ErlDrvSizeT len, + char **rbuf, ErlDrvSizeT rlen) { char *res_str; - int res_len = -1; + ErlDrvSSizeT res_len = -1; #ifndef UNIX #ifdef __WIN32__ res_str = "skip: windows_different"; @@ -854,7 +854,7 @@ chkio_drv_control(ErlDrvData drv_data, int fds[2]; cbdp->dev_null[i].fd = open("/dev/null", O_WRONLY); if (driver_select(cddp->port, - (ErlDrvEvent) cbdp->dev_null[i].fd, + (ErlDrvEvent) (ErlDrvSInt) cbdp->dev_null[i].fd, DO_WRITE, 1) != 0) { driver_failure_posix(cddp->port, errno); @@ -862,7 +862,7 @@ chkio_drv_control(ErlDrvData drv_data, } cbdp->dev_zero[i].fd = open("/dev/zero", O_RDONLY); if (driver_select(cddp->port, - (ErlDrvEvent) cbdp->dev_zero[i].fd, + (ErlDrvEvent) (ErlDrvSInt) cbdp->dev_zero[i].fd, DO_READ, 1) != 0) { driver_failure_posix(cddp->port, errno); @@ -873,7 +873,7 @@ chkio_drv_control(ErlDrvData drv_data, cbdp->pipe_in[i].fd = fds[0]; cbdp->pipe_out[i].fd = fds[1]; if (driver_select(cddp->port, - (ErlDrvEvent) cbdp->pipe_in[i].fd, + (ErlDrvEvent) (ErlDrvSInt) cbdp->pipe_in[i].fd, DO_READ, 1) != 0) { driver_failure_posix(cddp->port, EIO); @@ -882,7 +882,7 @@ chkio_drv_control(ErlDrvData drv_data, if (i % 2 == 0) (void) write(cbdp->pipe_out[i].fd, "!", 1); if (driver_select(cddp->port, - (ErlDrvEvent) cbdp->pipe_out[i].fd, + (ErlDrvEvent) (ErlDrvSInt) cbdp->pipe_out[i].fd, DO_WRITE, 1) != 0) { driver_failure_posix(cddp->port, EIO); @@ -928,8 +928,8 @@ chkio_drv_control(ErlDrvData drv_data, bfipp->fds[0] = fds[9]; bfipp->fds[1] = fds[10]; cddp->test_data = (void *) bfipp; - driver_select(cddp->port, (ErlDrvEvent) fds[9], DO_WRITE, 1); - driver_select(cddp->port, (ErlDrvEvent) fds[10], DO_READ, 1); + driver_select(cddp->port, (ErlDrvEvent) (ErlDrvSInt) fds[9], DO_WRITE, 1); + driver_select(cddp->port, (ErlDrvEvent) (ErlDrvSInt) fds[10], DO_READ, 1); } } res_str = "ok"; @@ -965,7 +965,7 @@ chkio_drv_control(ErlDrvData drv_data, cdep->in_ok = 0; res = driver_event(cddp->port, - (ErlDrvEvent) in_fd, + (ErlDrvEvent) (ErlDrvSInt) in_fd, &cdep->in_data); if (res < 0) { res_str = "skip: driver_event() not supported"; @@ -985,7 +985,7 @@ chkio_drv_control(ErlDrvData drv_data, cdep->out_ok = 0; res = driver_event(cddp->port, - (ErlDrvEvent) out_fd, + (ErlDrvEvent) (ErlDrvSInt) out_fd, &cdep->out_data); if (res < 0) { close(out_fd); @@ -1062,7 +1062,7 @@ chkio_drv_control(ErlDrvData drv_data, csp->event_data[0].events = POLLIN; csp->event_data[0].revents = 0; res = driver_event(cddp->port, - (ErlDrvEvent) csp->driver_event_fds[0], + (ErlDrvEvent) (ErlDrvSInt) csp->driver_event_fds[0], &csp->event_data[0]); if (res < 0) driver_failure_atom(cddp->port, @@ -1071,7 +1071,7 @@ chkio_drv_control(ErlDrvData drv_data, csp->event_data[1].events = POLLOUT; csp->event_data[1].revents = 0; res = driver_event(cddp->port, - (ErlDrvEvent) csp->driver_event_fds[1], + (ErlDrvEvent) (ErlDrvSInt) csp->driver_event_fds[1], &csp->event_data[1]); if (res < 0) driver_failure_atom(cddp->port, @@ -1083,7 +1083,7 @@ chkio_drv_control(ErlDrvData drv_data, /* Steal with driver_select() */ if (res >= 0) { res = driver_select(cddp->port, - (ErlDrvEvent) csp->driver_select_fds[0], + (ErlDrvEvent) (ErlDrvSInt) csp->driver_select_fds[0], DO_READ, 1); if (res < 0) @@ -1092,7 +1092,7 @@ chkio_drv_control(ErlDrvData drv_data, } if (res >= 0) { res = driver_select(cddp->port, - (ErlDrvEvent) csp->driver_select_fds[1], + (ErlDrvEvent) (ErlDrvSInt) csp->driver_select_fds[1], DO_WRITE, 1); if (res < 0) @@ -1159,14 +1159,14 @@ chkio_drv_control(ErlDrvData drv_data, csap->driver_event_fds[1] = write_fds[1]; res = driver_select(cddp->port, - (ErlDrvEvent) csap->driver_select_fds[0], + (ErlDrvEvent) (ErlDrvSInt) csap->driver_select_fds[0], DO_READ, 1); if (res < 0) driver_failure_atom(cddp->port, "driver_select_failed"); if (res >= 0) { res = driver_select(cddp->port, - (ErlDrvEvent) csap->driver_select_fds[1], + (ErlDrvEvent) (ErlDrvSInt) csap->driver_select_fds[1], DO_WRITE, 1); if (res < 0) @@ -1177,7 +1177,7 @@ chkio_drv_control(ErlDrvData drv_data, csap->event_data[0].events = POLLIN; csap->event_data[0].revents = 0; res = driver_event(cddp->port, - (ErlDrvEvent) csap->driver_event_fds[0], + (ErlDrvEvent) (ErlDrvSInt) csap->driver_event_fds[0], &csap->event_data[0]); if (res < 0) { close(csap->driver_event_fds[0]); @@ -1190,7 +1190,7 @@ chkio_drv_control(ErlDrvData drv_data, csap->event_data[1].events = POLLOUT; csap->event_data[1].revents = 0; res = driver_event(cddp->port, - (ErlDrvEvent) csap->driver_event_fds[1], + (ErlDrvEvent) (ErlDrvSInt) csap->driver_event_fds[1], &csap->event_data[1]); if (res < 0) driver_failure_atom(cddp->port, @@ -1285,7 +1285,7 @@ chkio_drv_control(ErlDrvData drv_data, } else { TRACEF(("%T: Select on pipe [%d->%d]\n", cddp->id, pip->write_fd, pip->read_fd)); - if (driver_select(cddp->port, (ErlDrvEvent)pip->read_fd, DO_READ, 1)) { + if (driver_select(cddp->port, (ErlDrvEvent)(ErlDrvSInt)pip->read_fd, DO_READ, 1)) { fprintf(stderr, "driver_select failed for fd=%d\n", pip->read_fd); abort(); } @@ -1314,7 +1314,7 @@ chkio_drv_control(ErlDrvData drv_data, op >>= 1; if (op & 1) { TRACEF(("%T: Deselect on pipe [%d->%d]\n", cddp->id, pip->write_fd, pip->read_fd)); - if (driver_select(cddp->port, (ErlDrvEvent)pip->read_fd, DO_READ, 0)) { + if (driver_select(cddp->port, (ErlDrvEvent)(ErlDrvSInt)pip->read_fd, DO_READ, 0)) { fprintf(stderr, "driver_(de)select failed for fd=%d\n", pip->read_fd); abort(); } diff --git a/erts/emulator/test/driver_SUITE_data/io_ready_exit_drv.c b/erts/emulator/test/driver_SUITE_data/io_ready_exit_drv.c index 6afa46b3a2..e6a3edcd74 100644 --- a/erts/emulator/test/driver_SUITE_data/io_ready_exit_drv.c +++ b/erts/emulator/test/driver_SUITE_data/io_ready_exit_drv.c @@ -40,8 +40,9 @@ static void io_ready_exit_ready_input(ErlDrvData, ErlDrvEvent); static void io_ready_exit_ready_output(ErlDrvData, ErlDrvEvent); static void io_ready_exit_drv_output(ErlDrvData, char *, int); static void io_ready_exit_drv_finish(void); -static int io_ready_exit_drv_control(ErlDrvData, unsigned int, - char *, int, char **, int); +static ErlDrvSSizeT io_ready_exit_drv_control(ErlDrvData, unsigned int, + char *, ErlDrvSizeT, + char **, ErlDrvSizeT); static ErlDrvEntry io_ready_exit_drv_entry = { NULL, /* init */ @@ -56,7 +57,17 @@ static ErlDrvEntry io_ready_exit_drv_entry = { io_ready_exit_drv_control, NULL, /* timeout */ NULL, /* outputv */ - NULL /* ready_async */ + NULL, /* ready_async */ + NULL, /* flush */ + NULL, /* call */ + NULL, /* event */ + ERL_DRV_EXTENDED_MARKER, + ERL_DRV_EXTENDED_MAJOR_VERSION, + ERL_DRV_EXTENDED_MINOR_VERSION, + 0, /* ERL_DRV_FLAGs */ + NULL, /* handle2 */ + NULL, /* process_exit */ + NULL /* stop_select */ }; /* ------------------------------------------------------------------------- @@ -83,7 +94,7 @@ io_ready_exit_drv_stop(ErlDrvData drv_data) { #ifdef UNIX if (oeddp->fds[0] >= 0) { driver_select(oeddp->port, - (ErlDrvEvent) oeddp->fds[0], + (ErlDrvEvent) (ErlDrvSInt) oeddp->fds[0], DO_READ|DO_WRITE, 0); close(oeddp->fds[0]); @@ -109,15 +120,15 @@ io_ready_exit_ready_input(ErlDrvData drv_data, ErlDrvEvent event) driver_failure_atom(oeddp->port, "ready_input_driver_failure"); } -static int +static ErlDrvSSizeT io_ready_exit_drv_control(ErlDrvData drv_data, unsigned int command, - char *buf, int len, - char **rbuf, int rlen) + char *buf, ErlDrvSizeT len, + char **rbuf, ErlDrvSizeT rlen) { char *abuf; char *res_str; - int res_len; + ErlDrvSSizeT res_len; IOReadyExitDrvData *oeddp = (IOReadyExitDrvData *) drv_data; #ifndef UNIX res_str = "nyiftos"; @@ -127,9 +138,9 @@ io_ready_exit_drv_control(ErlDrvData drv_data, } else { res_str = "ok"; - write(oeddp->fds[1], "!", 1); + (void) write(oeddp->fds[1], "!", 1); driver_select(oeddp->port, - (ErlDrvEvent) oeddp->fds[0], + (ErlDrvEvent) (ErlDrvSInt) oeddp->fds[0], DO_READ|DO_WRITE, 1); } diff --git a/erts/emulator/test/driver_SUITE_data/ioq_exit_drv.c b/erts/emulator/test/driver_SUITE_data/ioq_exit_drv.c index e49de388b4..b2cc1e785a 100644 --- a/erts/emulator/test/driver_SUITE_data/ioq_exit_drv.c +++ b/erts/emulator/test/driver_SUITE_data/ioq_exit_drv.c @@ -1,7 +1,7 @@ /* * %CopyrightBegin% * - * Copyright Ericsson AB 2007-2010. All Rights Reserved. + * Copyright Ericsson AB 2007-2011. All Rights Reserved. * * The contents of this file are subject to the Erlang Public License, * Version 1.1, (the "License"); you may not use this file except in @@ -91,7 +91,8 @@ static ErlDrvData start(ErlDrvPort port, char *command); static void stop(ErlDrvData drv_data); static void ready_input(ErlDrvData drv_data, ErlDrvEvent event); static void ready_output(ErlDrvData drv_data, ErlDrvEvent event); -static int control(ErlDrvData, unsigned int, char *, int, char **, int); +static ErlDrvSSizeT control(ErlDrvData, unsigned int, + char *, ErlDrvSizeT, char **, ErlDrvSizeT); static void timeout(ErlDrvData drv_data); static void ready_async(ErlDrvData drv_data, ErlDrvThreadData thread_data); static void flush(ErlDrvData drv_data); @@ -155,10 +156,10 @@ start(ErlDrvPort port, char *command) return (ErlDrvData) ddp; } -static int control(ErlDrvData drv_data, - unsigned int command, - char *buf, int len, - char **rbuf, int rlen) +static ErlDrvSSizeT control(ErlDrvData drv_data, + unsigned int command, + char *buf, ErlDrvSizeT len, + char **rbuf, ErlDrvSizeT rlen) { IOQExitDrvData *ddp = (IOQExitDrvData *) drv_data; char *res_str = "nyiftos"; @@ -227,7 +228,7 @@ static int control(ErlDrvData drv_data, res_str = "ok"; done: { - int res_len = strlen(res_str); + ErlDrvSSizeT res_len = strlen(res_str); if (res_len > rlen) { char *abuf = driver_alloc(sizeof(char)*res_len); if (!abuf) diff --git a/erts/emulator/test/driver_SUITE_data/many_events_drv.c b/erts/emulator/test/driver_SUITE_data/many_events_drv.c index 7417dbf7f8..a34432a8fe 100644 --- a/erts/emulator/test/driver_SUITE_data/many_events_drv.c +++ b/erts/emulator/test/driver_SUITE_data/many_events_drv.c @@ -3,14 +3,17 @@ #endif #include <stdio.h> +#include <string.h> #include "erl_driver.h" static ErlDrvPort erlang_port; static ErlDrvData many_events_start(ErlDrvPort, char *); -static void from_erlang(ErlDrvData, char*, int); +static void from_erlang(ErlDrvData, char*, ErlDrvSizeT); static void from_port(ErlDrvData drv_data, ErlDrvEvent event); -static int many_events_call(ErlDrvData drv_data, unsigned int command, char *buf, - int len, char **rbuf, int rlen, unsigned *ret_flags); +static ErlDrvSSizeT many_events_call(ErlDrvData drv_data, unsigned int command, + char *buf, ErlDrvSizeT len, + char **rbuf, ErlDrvSizeT rlen, + unsigned *ret_flags); static ErlDrvEntry many_events_driver_entry = { NULL, /* Init */ many_events_start, @@ -26,7 +29,15 @@ static ErlDrvEntry many_events_driver_entry = { NULL, NULL, NULL, - many_events_call + many_events_call, + NULL, + ERL_DRV_EXTENDED_MARKER, + ERL_DRV_EXTENDED_MAJOR_VERSION, + ERL_DRV_EXTENDED_MINOR_VERSION, + 0, + NULL, + NULL, + NULL }; DRIVER_INIT(many_events_drv) @@ -41,7 +52,7 @@ many_events_start(ErlDrvPort port, char *buf) } static void -from_erlang(ErlDrvData data, char *buf, int count) +from_erlang(ErlDrvData data, char *buf, ErlDrvSizeT count) { int i; int num; @@ -87,9 +98,10 @@ static void from_port(ErlDrvData data, ErlDrvEvent ev) return; } -static int -many_events_call(ErlDrvData drv_data, unsigned int command, char *buf, - int len, char **rbuf, int rlen, unsigned *ret_flags) +static ErlDrvSSizeT +many_events_call(ErlDrvData drv_data, unsigned int command, + char *buf, ErlDrvSizeT len, char **rbuf, ErlDrvSizeT rlen, + unsigned *ret_flags) { *rbuf = buf; *ret_flags |= DRIVER_CALL_KEEP_BUFFER; diff --git a/erts/emulator/test/driver_SUITE_data/monitor_drv.c b/erts/emulator/test/driver_SUITE_data/monitor_drv.c index 1da6a56a72..3da067fd09 100644 --- a/erts/emulator/test/driver_SUITE_data/monitor_drv.c +++ b/erts/emulator/test/driver_SUITE_data/monitor_drv.c @@ -21,8 +21,9 @@ #include "erl_driver.h" static ErlDrvData monitor_drv_start(ErlDrvPort, char *); -static int monitor_drv_control(ErlDrvData, unsigned int, - char *, int, char **, int); +static void monitor_drv_stop(ErlDrvData data); +static ErlDrvSSizeT monitor_drv_control(ErlDrvData, unsigned int, + char *, ErlDrvSizeT, char **, ErlDrvSizeT); static void handle_monitor(ErlDrvData drv_data, ErlDrvMonitor *monitor); #define OP_I_AM_IPID 1 @@ -50,7 +51,7 @@ typedef struct { static ErlDrvEntry monitor_drv_entry = { NULL /* init */, monitor_drv_start, - NULL /* stop */, + monitor_drv_stop, NULL /* output */, NULL /* ready_input */, NULL /* ready_output */, @@ -122,16 +123,16 @@ static void handle_monitor(ErlDrvData drv_data, ErlDrvMonitor *monitor) return; } -static int +static ErlDrvSSizeT monitor_drv_control(ErlDrvData drv_data, unsigned int command, - char *ibuf, int ilen, - char **rbuf, int rlen) + char *ibuf, ErlDrvSizeT ilen, + char **rbuf, ErlDrvSizeT rlen) { MyDrvData *data = (MyDrvData *) drv_data; char *answer = NULL; char buff[64]; - int alen; + ErlDrvSSizeT alen; switch (command) { case OP_I_AM_IPID: diff --git a/erts/emulator/test/driver_SUITE_data/otp_6879_drv.c b/erts/emulator/test/driver_SUITE_data/otp_6879_drv.c index 8c0a9aadfd..ff44145ca7 100644 --- a/erts/emulator/test/driver_SUITE_data/otp_6879_drv.c +++ b/erts/emulator/test/driver_SUITE_data/otp_6879_drv.c @@ -20,11 +20,11 @@ #include <string.h> #include "erl_driver.h" -static int call(ErlDrvData drv_data, - unsigned int command, - char *buf, int len, - char **rbuf, int rlen, - unsigned int *flags); +static ErlDrvSSizeT call(ErlDrvData drv_data, + unsigned int command, + char *buf, ErlDrvSizeT len, + char **rbuf, ErlDrvSizeT rlen, + unsigned int *flags); static ErlDrvEntry otp_6879_drv_entry = { NULL /* init */, @@ -57,11 +57,11 @@ DRIVER_INIT(otp_6879_drv) } -static int call(ErlDrvData drv_data, - unsigned int command, - char *buf, int len, - char **rbuf, int rlen, - unsigned int *flags) +static ErlDrvSSizeT call(ErlDrvData drv_data, + unsigned int command, + char *buf, ErlDrvSizeT len, + char **rbuf, ErlDrvSizeT rlen, + unsigned int *flags) { /* echo call */ if (len > rlen) diff --git a/erts/emulator/test/driver_SUITE_data/otp_9302_drv.c b/erts/emulator/test/driver_SUITE_data/otp_9302_drv.c index beee1b735f..221fd0ce51 100644 --- a/erts/emulator/test/driver_SUITE_data/otp_9302_drv.c +++ b/erts/emulator/test/driver_SUITE_data/otp_9302_drv.c @@ -28,7 +28,7 @@ static void stop(ErlDrvData drv_data); static ErlDrvData start(ErlDrvPort port, char *command); static void output(ErlDrvData drv_data, - char *buf, int len); + char *buf, ErlDrvSizeT len); static void ready_async(ErlDrvData drv_data, ErlDrvThreadData thread_data); @@ -196,13 +196,13 @@ static void ready_async(ErlDrvData drv_data, } static void output(ErlDrvData drv_data, - char *buf, int len) + char *buf, ErlDrvSizeT len) { Otp9302Data *data = (Otp9302Data *) drv_data; ErlDrvTermData td_port = driver_mk_port(data->port); ErlDrvTermData td_receiver = driver_caller(data->port); ErlDrvTermData td_job = driver_mk_atom("job"); - unsigned int key = (unsigned int) data->port; + unsigned int key = (unsigned int) (ErlDrvSInt) data->port; long id[5]; Otp9302AsyncData *ad[5]; int i; diff --git a/erts/emulator/test/driver_SUITE_data/outputv_drv.c b/erts/emulator/test/driver_SUITE_data/outputv_drv.c index 87f66ae413..3e3d4a3a03 100644 --- a/erts/emulator/test/driver_SUITE_data/outputv_drv.c +++ b/erts/emulator/test/driver_SUITE_data/outputv_drv.c @@ -3,7 +3,9 @@ static ErlDrvPort erlang_port; static ErlDrvData outputv_start(ErlDrvPort, char*); -static void outputv_stop(ErlDrvData), outputv_read(ErlDrvData, char*, int), outputv(ErlDrvData, ErlIOVec*); +static void outputv_stop(ErlDrvData), + outputv_read(ErlDrvData, char*, ErlDrvSizeT), + outputv(ErlDrvData, ErlIOVec*); static ErlDrvEntry outputv_driver_entry = { @@ -19,6 +21,16 @@ static ErlDrvEntry outputv_driver_entry = NULL, NULL, outputv, + NULL, + NULL, + NULL, + NULL, + ERL_DRV_EXTENDED_MARKER, + ERL_DRV_EXTENDED_MAJOR_VERSION, + ERL_DRV_EXTENDED_MINOR_VERSION, + 0, + NULL, + NULL, NULL }; @@ -38,7 +50,7 @@ static ErlDrvData outputv_start(ErlDrvPort port, char *buf) return (ErlDrvData)port; } -static void outputv_read(ErlDrvData port, char *buf, int count) +static void outputv_read(ErlDrvData port, char *buf, ErlDrvSizeT count) { erlang_port = (ErlDrvPort)-1; } diff --git a/erts/emulator/test/driver_SUITE_data/peek_non_existing_queue_drv.c b/erts/emulator/test/driver_SUITE_data/peek_non_existing_queue_drv.c index 3a5b5af13a..8e203f74ec 100644 --- a/erts/emulator/test/driver_SUITE_data/peek_non_existing_queue_drv.c +++ b/erts/emulator/test/driver_SUITE_data/peek_non_existing_queue_drv.c @@ -66,7 +66,8 @@ typedef struct { static ErlDrvData start(ErlDrvPort, char *); static void stop(ErlDrvData); -static int control(ErlDrvData, unsigned int, char *, int, char **, int); +static ErlDrvSSizeT control(ErlDrvData, unsigned int, + char *, ErlDrvSizeT, char **, ErlDrvSizeT); static void ready_async(ErlDrvData, ErlDrvThreadData); static void async_test(void *); static void async_wait(void *); @@ -121,10 +122,10 @@ static void stop(ErlDrvData drv_data) driver_free(drv_data); } -static int control(ErlDrvData drv_data, - unsigned int command, - char *buf, int len, - char **rbuf, int rlen) +static ErlDrvSSizeT control(ErlDrvData drv_data, + unsigned int command, + char *buf, ErlDrvSizeT len, + char **rbuf, ErlDrvSizeT rlen) { PeekNonXQDrvData *dp = (PeekNonXQDrvData *) drv_data; unsigned int key = 0; @@ -158,7 +159,7 @@ static int control(ErlDrvData drv_data, } done: { - int res_len = strlen(res_str); + ErlDrvSSizeT res_len = strlen(res_str); if (res_len > rlen) { char *abuf = driver_alloc(sizeof(char)*res_len); if (!abuf) diff --git a/erts/emulator/test/driver_SUITE_data/queue_drv.c b/erts/emulator/test/driver_SUITE_data/queue_drv.c index ded69f89f9..a02b57dc9a 100644 --- a/erts/emulator/test/driver_SUITE_data/queue_drv.c +++ b/erts/emulator/test/driver_SUITE_data/queue_drv.c @@ -1,4 +1,5 @@ #include <stdio.h> +#include <string.h> #include "erl_driver.h" #define put_int32(i, s) {((char*)(s))[0] = (char)((i) >> 24) & 0xff; \ @@ -33,9 +34,10 @@ static ErlDrvPort erlang_port; static unsigned opcode; /* Opcode for next operation. */ static ErlDrvData queue_start(ErlDrvPort, char*); -static void queue_stop(ErlDrvData), queue_read(ErlDrvData, char*, int); +static void queue_stop(ErlDrvData), queue_read(ErlDrvData, char*, ErlDrvSizeT); static void queue_outputv(ErlDrvData, ErlIOVec*); -static int control(ErlDrvData, unsigned int, char*, int, char**, int); +static ErlDrvSSizeT control(ErlDrvData, unsigned int, + char*, ErlDrvSizeT, char**, ErlDrvSizeT); static ErlDrvBinary* read_head(ErlDrvPort, int bytes); static ErlDrvEntry queue_driver_entry = @@ -52,6 +54,16 @@ static ErlDrvEntry queue_driver_entry = control, NULL, queue_outputv, + NULL, + NULL, + NULL, + NULL, + ERL_DRV_EXTENDED_MARKER, + ERL_DRV_EXTENDED_MAJOR_VERSION, + ERL_DRV_EXTENDED_MINOR_VERSION, + 0, + NULL, + NULL, NULL }; @@ -73,7 +85,7 @@ static ErlDrvData queue_start(ErlDrvPort port, char *buf) } /* messages from Erlang */ -static void queue_read(ErlDrvData port, char *buf, int len) +static void queue_read(ErlDrvData port, char *buf, ErlDrvSizeT len) { } @@ -82,8 +94,9 @@ static void queue_stop(ErlDrvData port) erlang_port = (ErlDrvPort) -1; } -static int -control(ErlDrvData drv_data, unsigned command, char* buf, int len, char** rbuf, int rlen) +static ErlDrvSSizeT +control(ErlDrvData drv_data, unsigned command, + char* buf, ErlDrvSizeT len, char** rbuf, ErlDrvSizeT rlen) { ErlDrvBinary* b; diff --git a/erts/emulator/test/driver_SUITE_data/sys_info_1_0_drv.c b/erts/emulator/test/driver_SUITE_data/sys_info_base_drv.c index 0504778086..c22a415c59 100644 --- a/erts/emulator/test/driver_SUITE_data/sys_info_1_0_drv.c +++ b/erts/emulator/test/driver_SUITE_data/sys_info_base_drv.c @@ -3,34 +3,35 @@ * compliance with the License. You should have received a copy of the * Erlang Public License along with this software. If not, it can be * retrieved via the world wide web at http://www.erlang.org/. - * + * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See * the License for the specific language governing rights and limitations * under the License. - * + * * The Initial Developer of the Original Code is Ericsson Utvecklings AB. * Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings * AB. All Rights Reserved.'' - * + * * $Id$ */ /* * Author: Rickard Green * - * Description: Driver that fakes driver version 1.0 and tests + * Description: Driver that fakes driver version 2.0 and tests * driver_system_info(). * */ #include "sys_info_drv_impl.h" -#define SYS_INFO_DRV_MAJOR_VSN 1 +#define SYS_INFO_DRV_MAJOR_VSN 2 #define SYS_INFO_DRV_MINOR_VSN 0 -#define SYS_INFO_DRV_NAME_STR "sys_info_1_0_drv" -#define SYS_INFO_DRV_NAME sys_info_1_0_drv +#define SYS_INFO_DRV_NAME_STR "sys_info_base_drv" +#define SYS_INFO_DRV_NAME sys_info_base_drv #define SYS_INFO_DRV_LAST_FIELD smp_support +#define ERL_DRV_SYS_INFO_SIZE sizeof(ErlDrvSysInfo) #define SYS_INFO_DRV_RES_FORMAT "ok: " \ "drv_drv_vsn=%d.%d " \ @@ -38,8 +39,9 @@ "erts_vsn=%s " \ "otp_vsn=%s " \ "thread=%s " \ - "smp=%s" - + "smp=%s " \ + "async_thrs=%d " \ + "sched_thrs=%d" static size_t sys_info_drv_max_res_len(ErlDrvSysInfo *sip) @@ -51,6 +53,8 @@ sys_info_drv_max_res_len(ErlDrvSysInfo *sip) slen += strlen(sip->otp_release) + 1; slen += 5; /* threads */ slen += 5; /* smp */ + slen += 20; /* async_thrs */ + slen += 20; /* sched_thrs */ return slen; } @@ -66,7 +70,9 @@ sys_info_drv_sprintf_sys_info(ErlDrvSysInfo *sip, char *str) sip->erts_version, sip->otp_release, sip->thread_support ? "true" : "false", - sip->smp_support ? "true" : "false"); + sip->smp_support ? "true" : "false", + sip->async_threads, + sip->scheduler_threads); } #include "sys_info_drv_impl.c" diff --git a/erts/emulator/test/driver_SUITE_data/sys_info_drv_impl.c b/erts/emulator/test/driver_SUITE_data/sys_info_drv_impl.c index 2d3203ae5d..c6c70a2075 100644 --- a/erts/emulator/test/driver_SUITE_data/sys_info_drv_impl.c +++ b/erts/emulator/test/driver_SUITE_data/sys_info_drv_impl.c @@ -46,7 +46,8 @@ #endif static ErlDrvData start(ErlDrvPort, char *); -static int control(ErlDrvData, unsigned int, char *, int, char **, int); +static ErlDrvSSizeT control(ErlDrvData, unsigned int, + char *, ErlDrvSizeT, char **, ErlDrvSizeT); static ErlDrvEntry drv_entry = { NULL /* init */, @@ -84,13 +85,13 @@ start(ErlDrvPort port, char *command) return (ErlDrvData) port; } -static int +static ErlDrvSSizeT control(ErlDrvData drv_data, unsigned int command, - char *buf, int len, - char **rbuf, int rlen) + char *buf, ErlDrvSizeT len, + char **rbuf, ErlDrvSizeT rlen) { - int res; + ErlDrvSSizeT res; char *str; size_t slen, slen2; ErlDrvPort port = (ErlDrvPort) drv_data; diff --git a/erts/emulator/test/driver_SUITE_data/sys_info_1_1_drv.c b/erts/emulator/test/driver_SUITE_data/sys_info_prev_drv.c index fa21828284..815d96cc97 100644 --- a/erts/emulator/test/driver_SUITE_data/sys_info_1_1_drv.c +++ b/erts/emulator/test/driver_SUITE_data/sys_info_prev_drv.c @@ -3,34 +3,35 @@ * compliance with the License. You should have received a copy of the * Erlang Public License along with this software. If not, it can be * retrieved via the world wide web at http://www.erlang.org/. - * + * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See * the License for the specific language governing rights and limitations * under the License. - * + * * The Initial Developer of the Original Code is Ericsson Utvecklings AB. * Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings * AB. All Rights Reserved.'' - * + * * $Id$ */ /* * Author: Rickard Green * - * Description: Driver that fakes driver version 1.1 and tests + * Description: Driver that fakes driver version 2.0 and tests * driver_system_info(). * */ #include "sys_info_drv_impl.h" -#define SYS_INFO_DRV_MAJOR_VSN 1 -#define SYS_INFO_DRV_MINOR_VSN 1 -#define SYS_INFO_DRV_NAME_STR "sys_info_1_1_drv" -#define SYS_INFO_DRV_NAME sys_info_1_1_drv +#define SYS_INFO_DRV_MAJOR_VSN 2 +#define SYS_INFO_DRV_MINOR_VSN 0 +#define SYS_INFO_DRV_NAME_STR "sys_info_prev_drv" +#define SYS_INFO_DRV_NAME sys_info_prev_drv #define SYS_INFO_DRV_LAST_FIELD scheduler_threads +#define ERL_DRV_SYS_INFO_SIZE sizeof(ErlDrvSysInfo) #define SYS_INFO_DRV_RES_FORMAT "ok: " \ "drv_drv_vsn=%d.%d " \ @@ -42,7 +43,6 @@ "async_thrs=%d " \ "sched_thrs=%d" - static size_t sys_info_drv_max_res_len(ErlDrvSysInfo *sip) { @@ -76,5 +76,3 @@ sys_info_drv_sprintf_sys_info(ErlDrvSysInfo *sip, char *str) } #include "sys_info_drv_impl.c" - - diff --git a/erts/emulator/test/driver_SUITE_data/thr_alloc_drv.c b/erts/emulator/test/driver_SUITE_data/thr_alloc_drv.c index c7edbba7f6..95a6ae9bdf 100644 --- a/erts/emulator/test/driver_SUITE_data/thr_alloc_drv.c +++ b/erts/emulator/test/driver_SUITE_data/thr_alloc_drv.c @@ -21,14 +21,8 @@ #include "erl_driver.h" ErlDrvData start(ErlDrvPort port, char *command); -int control(ErlDrvData drv_data, unsigned int command, char *buf, - int len, char **rbuf, int rlen); - -static int call(ErlDrvData drv_data, - unsigned int command, - char *buf, int len, - char **rbuf, int rlen, - unsigned int *flags); +ErlDrvSSizeT control(ErlDrvData drv_data, unsigned int command, char *buf, + ErlDrvSizeT len, char **rbuf, ErlDrvSizeT rlen); static ErlDrvEntry thr_alloc_drv_entry = { NULL /* init */, @@ -76,12 +70,12 @@ ErlDrvData start(ErlDrvPort port, char *command) return (ErlDrvData) port; } -int control(ErlDrvData drv_data, unsigned int command, char *buf, - int len, char **rbuf, int rlen) +ErlDrvSSizeT control(ErlDrvData drv_data, unsigned int command, char *buf, + ErlDrvSizeT len, char **rbuf, ErlDrvSizeT rlen) { ErlDrvPort port = (ErlDrvPort) drv_data; char *result = "failure"; - int result_len; + ErlDrvSSizeT result_len; if (len <= 20) { int res; ErlDrvTid tid; diff --git a/erts/emulator/test/driver_SUITE_data/thr_free_drv.c b/erts/emulator/test/driver_SUITE_data/thr_free_drv.c index 622a62ebea..439fe6a184 100644 --- a/erts/emulator/test/driver_SUITE_data/thr_free_drv.c +++ b/erts/emulator/test/driver_SUITE_data/thr_free_drv.c @@ -45,8 +45,8 @@ typedef struct { static ErlDrvData start(ErlDrvPort port, char *command); static void stop(ErlDrvData data); -static int control(ErlDrvData drv_data, unsigned int command, char *buf, - int len, char **rbuf, int rlen); +static ErlDrvSSizeT control(ErlDrvData drv_data, unsigned int command, char *buf, + ErlDrvSizeT len, char **rbuf, ErlDrvSizeT rlen); static ErlDrvEntry thr_free_drv_entry = { NULL /* init */, @@ -175,7 +175,7 @@ fail: driver_free(ttd[t].blocks[b]); } } - + driver_free(td); return ERL_DRV_ERROR_GENERAL; } @@ -194,14 +194,14 @@ static void stop(ErlDrvData drv_data) driver_free(td); } -static int control(ErlDrvData drv_data, unsigned int command, char *buf, - int len, char **rbuf, int rlen) +static ErlDrvSSizeT control(ErlDrvData drv_data, unsigned int command, char *buf, + ErlDrvSizeT len, char **rbuf, ErlDrvSizeT rlen) { test_data *td = (test_data *) drv_data; char *result = "failure"; int i, b; int res; - int result_len; + ErlDrvSSizeT result_len; if (td->b == -1) { erl_drv_mutex_lock(td->ttd[0].mtx); diff --git a/erts/emulator/test/driver_SUITE_data/timer_drv.c b/erts/emulator/test/driver_SUITE_data/timer_drv.c index b96a95dd4c..8c3f203a64 100644 --- a/erts/emulator/test/driver_SUITE_data/timer_drv.c +++ b/erts/emulator/test/driver_SUITE_data/timer_drv.c @@ -22,7 +22,9 @@ static ErlDrvPort erlang_port; static ErlDrvData timer_start(ErlDrvPort, char*); -static void timer_stop(ErlDrvData), timer_read(ErlDrvData, char*, int), timer(ErlDrvData); +static void timer_stop(ErlDrvData); +static void timer_read(ErlDrvData, char*, ErlDrvSizeT); +static void timer(ErlDrvData); static ErlDrvEntry timer_driver_entry = { @@ -38,6 +40,16 @@ static ErlDrvEntry timer_driver_entry = NULL, timer, NULL, + NULL, + NULL, + NULL, + NULL, + ERL_DRV_EXTENDED_MARKER, + ERL_DRV_EXTENDED_MAJOR_VERSION, + ERL_DRV_EXTENDED_MINOR_VERSION, + 0, + NULL, + NULL, NULL }; @@ -57,8 +69,9 @@ static ErlDrvData timer_start(ErlDrvPort port, char *buf) } /* set the timer, this is monitored from erlang measuring the time */ -static void timer_read(ErlDrvData port, char *buf, int len) +static void timer_read(ErlDrvData p, char *buf, ErlDrvSizeT len) { + ErlDrvPort port = (ErlDrvPort) p; char reply[1]; if (buf[0] == START_TIMER) { diff --git a/erts/emulator/test/erl_drv_thread_SUITE_data/testcase_driver.c b/erts/emulator/test/erl_drv_thread_SUITE_data/testcase_driver.c index 1e98844838..b4542f3e36 100644 --- a/erts/emulator/test/erl_drv_thread_SUITE_data/testcase_driver.c +++ b/erts/emulator/test/erl_drv_thread_SUITE_data/testcase_driver.c @@ -50,13 +50,33 @@ typedef struct { ErlDrvData testcase_drv_start(ErlDrvPort port, char *command); void testcase_drv_stop(ErlDrvData drv_data); -void testcase_drv_run(ErlDrvData drv_data, char *buf, int len); +void testcase_drv_run(ErlDrvData drv_data, char *buf, ErlDrvSizeT len); static ErlDrvEntry testcase_drv_entry = { NULL, testcase_drv_start, testcase_drv_stop, - testcase_drv_run + testcase_drv_run, + NULL, + NULL, + NULL, + NULL, + NULL, /* handle */ + NULL, /* control */ + NULL, /* timeout */ + NULL, /* outputv */ + NULL, /* ready_async */ + NULL, + NULL, + NULL, + ERL_DRV_EXTENDED_MARKER, + ERL_DRV_EXTENDED_MAJOR_VERSION, + ERL_DRV_EXTENDED_MINOR_VERSION, + 0, + NULL, + NULL, + NULL, + }; @@ -92,7 +112,7 @@ testcase_drv_stop(ErlDrvData drv_data) } void -testcase_drv_run(ErlDrvData drv_data, char *buf, int len) +testcase_drv_run(ErlDrvData drv_data, char *buf, ErlDrvSizeT len) { InternalTestCaseState_t *itcs = (InternalTestCaseState_t *) drv_data; ErlDrvTermData result_atom; diff --git a/erts/emulator/test/float_SUITE_data/fp_drv.c b/erts/emulator/test/float_SUITE_data/fp_drv.c index eb453f6cd6..b80385c3f9 100644 --- a/erts/emulator/test/float_SUITE_data/fp_drv.c +++ b/erts/emulator/test/float_SUITE_data/fp_drv.c @@ -22,6 +22,7 @@ # define PRINTF(X) #endif +#include <string.h> #include <math.h> #ifdef __WIN32__ #include <float.h> @@ -37,7 +38,8 @@ int _finite(double x); #define ERTS_FP_CONTROL_TEST 0 #define ERTS_FP_THREAD_TEST 1 -static int control(ErlDrvData, unsigned int, char *, int, char **, int); +static ErlDrvSSizeT control(ErlDrvData, unsigned int, char *, + ErlDrvSizeT, char **, ErlDrvSizeT); static ErlDrvEntry fp_drv_entry = { NULL /* init */, @@ -97,10 +99,10 @@ do_test(void *unused) return "ok"; } -static int control(ErlDrvData drv_data, - unsigned int command, - char *buf, int len, - char **rbuf, int rlen) +static ErlDrvSSizeT control(ErlDrvData drv_data, + unsigned int command, + char *buf, ErlDrvSizeT len, + char **rbuf, ErlDrvSizeT rlen) { char *res_str; PRINTF(("control(%p, %d, ...) called\r\n", drv_data, command)); diff --git a/erts/emulator/test/fun_r12_SUITE.erl b/erts/emulator/test/fun_r13_SUITE.erl index 3b1dfc9825..76ddf9fec9 100644 --- a/erts/emulator/test/fun_r12_SUITE.erl +++ b/erts/emulator/test/fun_r13_SUITE.erl @@ -17,10 +17,10 @@ %% %CopyrightEnd% %% --module(fun_r12_SUITE). --compile(r12). +-module(fun_r13_SUITE). +-compile(r13). --export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, +-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, init_per_group/2,end_per_group/2, init_per_testcase/2,end_per_testcase/2,dist_old_release/1]). @@ -29,10 +29,10 @@ suite() -> [{ct_hooks,[ts_install_cth]}]. -all() -> +all() -> [dist_old_release]. -groups() -> +groups() -> []. init_per_suite(Config) -> diff --git a/erts/emulator/test/mtx_SUITE.erl b/erts/emulator/test/mtx_SUITE.erl index 879d2f61dd..024c3456a8 100644 --- a/erts/emulator/test/mtx_SUITE.erl +++ b/erts/emulator/test/mtx_SUITE.erl @@ -122,7 +122,7 @@ long_rwlock(Config) when is_list(Config) -> %% A very short run time is expected, since %% threads in the test mostly wait ?t:format("RunTime=~p~n", [RunTime]), - ?line true = RunTime < 100, + ?line true = RunTime < 400, ?line RunTimeStr = "Run-time during test was "++integer_to_list(RunTime)++" ms.", case LLRes of ok -> @@ -281,7 +281,7 @@ hammer_sched_rwlock_test(FreqRead, LockCheck, Blocking, WaitLocked, WaitUnlocked _ -> {_, RunTime} = statistics(runtime), ?t:format("RunTime=~p~n", [RunTime]), - ?line true = RunTime < 500, + ?line true = RunTime < 700, {comment, "Run-time during test was " ++ integer_to_list(RunTime) 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/port_SUITE_data/echo_drv.c b/erts/emulator/test/port_SUITE_data/echo_drv.c index 25eda116fe..1d39c6a00c 100644 --- a/erts/emulator/test/port_SUITE_data/echo_drv.c +++ b/erts/emulator/test/port_SUITE_data/echo_drv.c @@ -1,4 +1,5 @@ #include <stdio.h> +#include <string.h> #include "erl_driver.h" @@ -17,11 +18,9 @@ typedef struct _erl_drv_data EchoDrvData; static EchoDrvData *echo_drv_start(ErlDrvPort port, char *command); static void echo_drv_stop(EchoDrvData *data_p); -static void echo_drv_output(EchoDrvData *data_p, char *buf, int len); +static void echo_drv_output(ErlDrvData drv_data, char *buf, + ErlDrvSizeT len); static void echo_drv_finish(void); -static int echo_drv_control(EchoDrvData *data_p, unsigned int command, - char *buf, int len, - char **rbuf, int rlen); static ErlDrvEntry echo_drv_entry = { NULL, /* init */ @@ -33,10 +32,20 @@ static ErlDrvEntry echo_drv_entry = { "echo_drv", echo_drv_finish, NULL, /* handle */ - echo_drv_control, + NULL, /* control */ NULL, /* timeout */ NULL, /* outputv */ - NULL /* ready_async */ + NULL, /* ready_async */ + NULL, + NULL, + NULL, + ERL_DRV_EXTENDED_MARKER, + ERL_DRV_EXTENDED_MAJOR_VERSION, + ERL_DRV_EXTENDED_MINOR_VERSION, + 0, + NULL, + NULL, + NULL, }; @@ -68,7 +77,8 @@ static EchoDrvData *echo_drv_start(ErlDrvPort port, char *command) { static void echo_drv_stop(EchoDrvData *data_p) { } -static void echo_drv_output(EchoDrvData *data_p, char *buf, int len) { +static void echo_drv_output(ErlDrvData drv_data, char *buf, ErlDrvSizeT len) { + EchoDrvData *data_p = (EchoDrvData *) drv_data; void *void_ptr; ErlDrvPort port = void_ptr = data_p; @@ -77,9 +87,3 @@ static void echo_drv_output(EchoDrvData *data_p, char *buf, int len) { static void echo_drv_finish() { } - -static int echo_drv_control(EchoDrvData *data_p, unsigned int command, - char *buf, int len, - char **rbuf, int rlen) { - return 0; -} diff --git a/erts/emulator/test/port_SUITE_data/exit_drv.c b/erts/emulator/test/port_SUITE_data/exit_drv.c index 60f1b321bd..5f366b3545 100644 --- a/erts/emulator/test/port_SUITE_data/exit_drv.c +++ b/erts/emulator/test/port_SUITE_data/exit_drv.c @@ -5,11 +5,9 @@ typedef struct _erl_drv_data ExitDrvData; static ExitDrvData *exit_drv_start(ErlDrvPort port, char *command); static void exit_drv_stop(ExitDrvData *data_p); -static void exit_drv_output(ExitDrvData *data_p, char *buf, int len); +static void exit_drv_output(ExitDrvData *data_p, char *buf, + ErlDrvSizeT len); static void exit_drv_finish(void); -static int exit_drv_control(ExitDrvData *data_p, unsigned int command, - char *buf, int len, - char **rbuf, int rlen); static ErlDrvEntry exit_drv_entry = { NULL, /* init */ @@ -21,10 +19,20 @@ static ErlDrvEntry exit_drv_entry = { "exit_drv", exit_drv_finish, NULL, /* handle */ - exit_drv_control, + NULL, /* control */ NULL, /* timeout */ NULL, /* outputv */ - NULL /* ready_async */ + NULL, /* ready_async */ + NULL, + NULL, + NULL, + ERL_DRV_EXTENDED_MARKER, + ERL_DRV_EXTENDED_MAJOR_VERSION, + ERL_DRV_EXTENDED_MINOR_VERSION, + 0, + NULL, + NULL, + NULL, }; DRIVER_INIT(exit_drv) @@ -45,7 +53,7 @@ exit_drv_stop(ExitDrvData *datap) } static void -exit_drv_output(ExitDrvData *datap, char *buf, int len) +exit_drv_output(ExitDrvData *datap, char *buf, ErlDrvSizeT len) { driver_exit((ErlDrvPort) datap, 0); } @@ -55,14 +63,3 @@ exit_drv_finish(void) { } - -static int -exit_drv_control(ExitDrvData *datap, - unsigned int command, - char *buf, - int len, - char **rbuf, - int rlen) -{ - return 0; -} diff --git a/erts/emulator/test/port_SUITE_data/failure_drv.c b/erts/emulator/test/port_SUITE_data/failure_drv.c index 34d48e00f8..5826e6d5a9 100644 --- a/erts/emulator/test/port_SUITE_data/failure_drv.c +++ b/erts/emulator/test/port_SUITE_data/failure_drv.c @@ -5,10 +5,8 @@ typedef struct _erl_drv_data FailureDrvData; static FailureDrvData *failure_drv_start(ErlDrvPort, char *); static void failure_drv_stop(FailureDrvData *); -static void failure_drv_output(FailureDrvData *, char *, int); +static void failure_drv_output(ErlDrvData, char *, ErlDrvSizeT); static void failure_drv_finish(void); -static int failure_drv_control(FailureDrvData *, unsigned int, - char *, int, char **, int); static ErlDrvEntry failure_drv_entry = { NULL, /* init */ @@ -18,12 +16,22 @@ static ErlDrvEntry failure_drv_entry = { NULL, /* ready_input */ NULL, /* ready_output */ "failure_drv", - failure_drv_finish, + NULL, /* finish */ NULL, /* handle */ - failure_drv_control, + NULL, /* control */ NULL, /* timeout */ NULL, /* outputv */ - NULL /* ready_async */ + NULL, /* ready_async */ + NULL, + NULL, + NULL, + ERL_DRV_EXTENDED_MARKER, + ERL_DRV_EXTENDED_MAJOR_VERSION, + ERL_DRV_EXTENDED_MINOR_VERSION, + 0, + NULL, + NULL, + NULL, }; @@ -46,7 +54,8 @@ static FailureDrvData *failure_drv_start(ErlDrvPort port, char *command) { static void failure_drv_stop(FailureDrvData *data_p) { } -static void failure_drv_output(FailureDrvData *data_p, char *buf, int len) { +static void failure_drv_output(ErlDrvData drv_data, char *buf, ErlDrvSizeT len) { + FailureDrvData *data_p = (FailureDrvData *) drv_data; void *void_ptr; ErlDrvPort port = void_ptr = data_p; @@ -55,9 +64,3 @@ static void failure_drv_output(FailureDrvData *data_p, char *buf, int len) { static void failure_drv_finish() { } - -static int failure_drv_control(FailureDrvData *data_p, unsigned int command, - char *buf, int len, - char **rbuf, int rlen) { - return 0; -} diff --git a/erts/emulator/test/port_bif_SUITE_data/control_drv.c b/erts/emulator/test/port_bif_SUITE_data/control_drv.c index e9f57a887a..b937a8bb15 100644 --- a/erts/emulator/test/port_bif_SUITE_data/control_drv.c +++ b/erts/emulator/test/port_bif_SUITE_data/control_drv.c @@ -1,13 +1,15 @@ #include <stdio.h> #include <stdlib.h> +#include <string.h> #include "erl_driver.h" static ErlDrvPort erlang_port; static ErlDrvData control_start(ErlDrvPort, char*); static void control_stop(ErlDrvData); -static void control_read(ErlDrvData, char*, int); -static int control_control(ErlDrvData, unsigned int, char*, int, char**, int); +static void control_read(ErlDrvData, char*, ErlDrvSizeT); +static ErlDrvSSizeT control_control(ErlDrvData, unsigned int, char*, + ErlDrvSizeT, char**, ErlDrvSizeT); static ErlDrvEntry control_driver_entry = { @@ -21,9 +23,19 @@ static ErlDrvEntry control_driver_entry = NULL, NULL, control_control, + NULL, /* timeout */ + NULL, /* outputv */ + NULL, /* ready_async */ + NULL, + NULL, + NULL, + ERL_DRV_EXTENDED_MARKER, + ERL_DRV_EXTENDED_MAJOR_VERSION, + ERL_DRV_EXTENDED_MINOR_VERSION, + 0, + NULL, NULL, NULL, - NULL }; DRIVER_INIT(control_drv) @@ -41,7 +53,7 @@ static ErlDrvData control_start(ErlDrvPort port,char *buf) return (ErlDrvData)port; } -static void control_read(ErlDrvData port, char *buf, int count) +static void control_read(ErlDrvData port, char *buf, ErlDrvSizeT count) { driver_output(erlang_port, buf, count); } @@ -51,8 +63,9 @@ static void control_stop(ErlDrvData port) erlang_port = (ErlDrvPort)-1; } -static int control_control(ErlDrvData port, unsigned command, char* buf, int count, - char** res, int res_size) +static ErlDrvSSizeT control_control(ErlDrvData port, unsigned command, + char* buf, ErlDrvSizeT count, + char** res, ErlDrvSizeT res_size) { switch (command) { case 'e': diff --git a/erts/emulator/test/scheduler_SUITE.erl b/erts/emulator/test/scheduler_SUITE.erl index debb54579b..8931562828 100644 --- a/erts/emulator/test/scheduler_SUITE.erl +++ b/erts/emulator/test/scheduler_SUITE.erl @@ -55,7 +55,7 @@ scheduler_suspend/1, reader_groups/1]). --define(DEFAULT_TIMEOUT, ?t:minutes(10)). +-define(DEFAULT_TIMEOUT, ?t:minutes(15)). -define(MIN_SCHEDULER_TEST_TIMEOUT, ?t:minutes(1)). @@ -519,16 +519,18 @@ bound_loop(NS, N, M, Sched) -> bindings(Node, BindType) -> Parent = self(), Ref = make_ref(), - spawn_link(Node, - fun () -> - enable_internal_state(), - Res = (catch erts_debug:get_internal_state( - {fake_scheduler_bindings, BindType})), - Parent ! {Ref, Res} - end), + Pid = spawn_link(Node, + fun () -> + enable_internal_state(), + Res = (catch erts_debug:get_internal_state( + {fake_scheduler_bindings, + BindType})), + Parent ! {Ref, Res} + end), receive {Ref, Res} -> ?t:format("~p: ~p~n", [BindType, Res]), + unlink(Pid), Res end. @@ -1684,7 +1686,7 @@ do_it(Tracer, Low, Normal, High, Max, RedsPerSchedLimit) -> EndWait = now(), BalanceWait = timer:now_diff(EndWait,StartWait) div 1000, erlang:display({balance_wait, BalanceWait}), - Timeout = ?DEFAULT_TIMEOUT - ?t:seconds(10) - BalanceWait, + Timeout = ?DEFAULT_TIMEOUT - ?t:minutes(4) - BalanceWait, Res = case Timeout < ?MIN_SCHEDULER_TEST_TIMEOUT of true -> stop_work(Low, Normal, High, Max), diff --git a/erts/emulator/test/send_term_SUITE_data/send_term_drv.c b/erts/emulator/test/send_term_SUITE_data/send_term_drv.c index 165cce2e9d..b3feca79f0 100644 --- a/erts/emulator/test/send_term_SUITE_data/send_term_drv.c +++ b/erts/emulator/test/send_term_SUITE_data/send_term_drv.c @@ -24,7 +24,7 @@ static ErlDrvPort erlang_port; static ErlDrvData send_term_drv_start(ErlDrvPort port, char *command); static void send_term_drv_stop(ErlDrvData drv_data); -static void send_term_drv_run(ErlDrvData drv_data, char *buf, int len); +static void send_term_drv_run(ErlDrvData drv_data, char *buf, ErlDrvSizeT len); static int make_ext_term_list(ErlDrvTermData *td, int bad); @@ -39,6 +39,22 @@ static ErlDrvEntry send_term_drv_entry = { NULL, NULL, "send_term_drv", + NULL, + NULL, /* handle */ + NULL, /* control */ + NULL, /* timeout */ + NULL, /* outputv */ + NULL, /* ready_async */ + NULL, + NULL, + NULL, + ERL_DRV_EXTENDED_MARKER, + ERL_DRV_EXTENDED_MAJOR_VERSION, + ERL_DRV_EXTENDED_MINOR_VERSION, + 0, + NULL, + NULL, + NULL, }; DRIVER_INIT(send_term_drv) @@ -64,7 +80,7 @@ static void send_term_drv_stop(ErlDrvData drv_data) static void output_term(ErlDrvTermData* msg, int len); static void fail_term(ErlDrvTermData* msg, int len, int line); -static void send_term_drv_run(ErlDrvData port, char *buf, int count) +static void send_term_drv_run(ErlDrvData port, char *buf, ErlDrvSizeT count) { char buf7[1024]; ErlDrvTermData spec[1024]; 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/test/system_profile_SUITE_data/echo_drv.c b/erts/emulator/test/system_profile_SUITE_data/echo_drv.c index d968ff06f9..e0b6ff804c 100644 --- a/erts/emulator/test/system_profile_SUITE_data/echo_drv.c +++ b/erts/emulator/test/system_profile_SUITE_data/echo_drv.c @@ -9,11 +9,9 @@ static EchoDrvData echo_drv_data, *echo_drv_data_p; static EchoDrvData *echo_drv_start(ErlDrvPort port, char *command); static void echo_drv_stop(EchoDrvData *data_p); -static void echo_drv_output(EchoDrvData *data_p, char *buf, int len); +static void echo_drv_output(ErlDrvData drv_data, char *buf, + ErlDrvSizeT len); static void echo_drv_finish(void); -static int echo_drv_control(EchoDrvData *data_p, unsigned int command, - char *buf, int len, - char **rbuf, int rlen); static ErlDrvEntry echo_drv_entry = { NULL, /* init */ @@ -25,10 +23,21 @@ static ErlDrvEntry echo_drv_entry = { "echo_drv", echo_drv_finish, NULL, /* handle */ - echo_drv_control, + NULL, /* control */ NULL, /* timeout */ NULL, /* outputv */ - NULL /* ready_async */ + NULL, /* ready_async */ + NULL, + NULL, + NULL, + ERL_DRV_EXTENDED_MARKER, + ERL_DRV_EXTENDED_MAJOR_VERSION, + ERL_DRV_EXTENDED_MINOR_VERSION, + 0, + NULL, + NULL, + NULL + }; DRIVER_INIT(echo_drv) @@ -51,16 +60,11 @@ static void echo_drv_stop(EchoDrvData *data_p) { echo_drv_data_p = NULL; } -static void echo_drv_output(EchoDrvData *data_p, char *buf, int len) { +static void echo_drv_output(ErlDrvData drv_data, char *buf, ErlDrvSizeT len) { + EchoDrvData* data_p = (EchoDrvData *) drv_data; driver_output(data_p->erlang_port, buf, len); } static void echo_drv_finish() { echo_drv_data_p = NULL; } - -static int echo_drv_control(EchoDrvData *data_p, unsigned int command, - char *buf, int len, - char **rbuf, int rlen) { - return 0; -} diff --git a/erts/emulator/test/time_SUITE.erl b/erts/emulator/test/time_SUITE.erl index bd48a0a7db..4d12e3449c 100644 --- a/erts/emulator/test/time_SUITE.erl +++ b/erts/emulator/test/time_SUITE.erl @@ -32,6 +32,7 @@ -export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, init_per_group/2,end_per_group/2, univ_to_local/1, local_to_univ/1, bad_univ_to_local/1, bad_local_to_univ/1, + univ_to_seconds/1, seconds_to_univ/1, consistency/1, now_unique/1, now_update/1, timestamp/1]). @@ -59,7 +60,9 @@ suite() -> [{ct_hooks,[ts_install_cth]}]. all() -> [univ_to_local, local_to_univ, local_to_univ_utc, - bad_univ_to_local, bad_local_to_univ, consistency, + bad_univ_to_local, bad_local_to_univ, + univ_to_seconds, seconds_to_univ, + consistency, {group, now}, timestamp]. groups() -> @@ -162,6 +165,30 @@ bad_test_local_to_univ([Local|Rest]) -> bad_test_local_to_univ([]) -> ok. + +%% Test universaltime to seconds conversions +univ_to_seconds(Config) when is_list(Config) -> + test_univ_to_seconds(ok_utc_seconds()). + +test_univ_to_seconds([{Datetime, Seconds}|DSs]) -> + io:format("universaltime = ~p -> seconds = ~p", [Datetime, Seconds]), + Seconds = erlang:universaltime_to_posixtime(Datetime), + test_univ_to_seconds(DSs); +test_univ_to_seconds([]) -> + ok. + +%% Test seconds to universaltime conversions +seconds_to_univ(Config) when is_list(Config) -> + test_seconds_to_univ(ok_utc_seconds()). + +test_seconds_to_univ([{Datetime, Seconds}|DSs]) -> + io:format("universaltime = ~p <- seconds = ~p", [Datetime, Seconds]), + Datetime = erlang:posixtime_to_universaltime(Seconds), + test_seconds_to_univ(DSs); +test_seconds_to_univ([]) -> + ok. + + %% Test that the the different time functions return %% consistent results. (See the test case for assumptions %% and limitations.) @@ -453,6 +480,32 @@ dst_dates() -> {1998, 06, 3}, {1999, 06, 4}]. +%% exakt utc {date(), time()} which corresponds to the same seconds since 1 jan 1970 +%% negative seconds are ok +%% generated with date --date='1979-05-28 12:30:35 UTC' +%s +ok_utc_seconds() -> [ + { {{1970, 1, 1},{ 0, 0, 0}}, 0 }, + { {{1970, 1, 1},{ 0, 0, 1}}, 1 }, + { {{1969,12,31},{23,59,59}}, -1 }, + { {{1920,12,31},{23,59,59}}, -1546300801 }, + { {{1600,02,19},{15,14,08}}, -11671807552 }, + { {{1979,05,28},{12,30,35}}, 296742635 }, + { {{1999,12,31},{23,59,59}}, 946684799 }, + { {{2000, 1, 1},{ 0, 0, 0}}, 946684800 }, + { {{2000, 1, 1},{ 0, 0, 1}}, 946684801 }, + + { {{2038, 1,19},{03,14,07}}, 2147483647 }, % Sint32 full - 1 + { {{2038, 1,19},{03,14,08}}, 2147483648 }, % Sint32 full + { {{2038, 1,19},{03,14,09}}, 2147483649 }, % Sint32 full + 1 + + { {{2106, 2, 7},{ 6,28,14}}, 4294967294 }, % Uint32 full 0xFFFFFFFF - 1 + { {{2106, 2, 7},{ 6,28,15}}, 4294967295 }, % Uint32 full 0xFFFFFFFF + { {{2106, 2, 7},{ 6,28,16}}, 4294967296 }, % Uint32 full 0xFFFFFFFF + 1 + { {{2012,12, 6},{16,28,08}}, 1354811288 }, + { {{2412,12, 6},{16,28,08}}, 13977592088 } + ]. + + %% The following dates should not be near the end or beginning of %% a month, because they will be used to test when the dates are %% different in UTC and local time. diff --git a/erts/emulator/test/trace_port_SUITE_data/echo_drv.c b/erts/emulator/test/trace_port_SUITE_data/echo_drv.c index 15c4ca11fe..a8d4ede4fe 100644 --- a/erts/emulator/test/trace_port_SUITE_data/echo_drv.c +++ b/erts/emulator/test/trace_port_SUITE_data/echo_drv.c @@ -25,12 +25,14 @@ static EchoDrvData echo_drv_data, *echo_drv_data_p; **/ static EchoDrvData *echo_drv_start(ErlDrvPort port, char *command); -static void echo_drv_stop(EchoDrvData *data_p); -static void echo_drv_output(EchoDrvData *data_p, char *buf, int len); +static void echo_drv_stop(ErlDrvData drv_data); +static void echo_drv_output(ErlDrvData drv_data, char *buf, + ErlDrvSizeT len); static void echo_drv_finish(void); -static int echo_drv_control(EchoDrvData *data_p, unsigned int command, - char *buf, int len, - char **rbuf, int rlen); +static ErlDrvSSizeT echo_drv_control(ErlDrvData drv_data, + unsigned int command, + char *buf, ErlDrvSizeT len, + char **rbuf, ErlDrvSizeT rlen); static ErlDrvEntry echo_drv_entry = { NULL, /* init */ @@ -45,11 +47,19 @@ static ErlDrvEntry echo_drv_entry = { echo_drv_control, NULL, /* timeout */ NULL, /* outputv */ - NULL /* ready_async */ + NULL, /* ready_async */ + NULL, + NULL, + NULL, + ERL_DRV_EXTENDED_MARKER, + ERL_DRV_EXTENDED_MAJOR_VERSION, + ERL_DRV_EXTENDED_MINOR_VERSION, + 0, + NULL, + NULL, + NULL }; - - /* ------------------------------------------------------------------------- ** Entry functions **/ @@ -75,7 +85,8 @@ static void echo_drv_stop(EchoDrvData *data_p) { echo_drv_data_p = NULL; } -static void echo_drv_output(EchoDrvData *data_p, char *buf, int len) { +static void echo_drv_output(ErlDrvData drv_data, char *buf, ErlDrvSizeT len) { + EchoDrvData* data_p = (EchoDrvData *) drv_data; driver_output(data_p->erlang_port, buf, len); switch (data_p->heavy) { case heavy_off: @@ -95,9 +106,11 @@ static void echo_drv_finish() { echo_drv_data_p = NULL; } -static int echo_drv_control(EchoDrvData *data_p, unsigned int command, - char *buf, int len, - char **rbuf, int rlen) { +static ErlDrvSSizeT echo_drv_control(ErlDrvData drv_data, + unsigned int command, + char *buf, ErlDrvSizeT len, + char **rbuf, ErlDrvSizeT rlen) { + EchoDrvData* data_p = (EchoDrvData *) drv_data; switch (command) { case 'h': data_p->heavy = heavy_set; 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 +} + |