diff options
Diffstat (limited to 'erts/emulator')
-rw-r--r-- | erts/emulator/beam/beam_load.c | 1 | ||||
-rw-r--r-- | erts/emulator/beam/binary.c | 2 | ||||
-rw-r--r-- | erts/emulator/beam/erl_alloc.c | 30 | ||||
-rw-r--r-- | erts/emulator/beam/erl_bif_re.c | 8 | ||||
-rw-r--r-- | erts/emulator/beam/erl_message.h | 4 | ||||
-rw-r--r-- | erts/emulator/beam/erl_nif.c | 38 | ||||
-rw-r--r-- | erts/emulator/beam/erl_nif.h | 3 | ||||
-rw-r--r-- | erts/emulator/beam/erl_nif_api_funcs.h | 2 | ||||
-rw-r--r-- | erts/emulator/beam/erl_process.h | 4 | ||||
-rw-r--r-- | erts/emulator/beam/erl_unicode.c | 58 | ||||
-rw-r--r-- | erts/emulator/beam/global.h | 2 | ||||
-rw-r--r-- | erts/emulator/hipe/hipe_mode_switch.c | 27 | ||||
-rw-r--r-- | erts/emulator/test/alloc_SUITE.erl | 22 | ||||
-rw-r--r-- | erts/emulator/test/nif_SUITE.erl | 17 | ||||
-rw-r--r-- | erts/emulator/test/nif_SUITE_data/nif_SUITE.c | 20 | ||||
-rw-r--r-- | erts/emulator/test/port_trace_SUITE.erl | 44 | ||||
-rw-r--r-- | erts/emulator/test/port_trace_SUITE_data/echo_drv.c | 36 |
17 files changed, 257 insertions, 61 deletions
diff --git a/erts/emulator/beam/beam_load.c b/erts/emulator/beam/beam_load.c index 95489d9a63..0c2743beb2 100644 --- a/erts/emulator/beam/beam_load.c +++ b/erts/emulator/beam/beam_load.c @@ -4424,6 +4424,7 @@ gen_get_map_elements(LoaderState* stp, GenOpArg Fail, GenOpArg Src, int good_hash; #endif + ERTS_UNDEF(hx, 0); ASSERT(Size.type == TAG_u); NEW_GENOP(stp, op); diff --git a/erts/emulator/beam/binary.c b/erts/emulator/beam/binary.c index cfd8fbe2f5..071a356260 100644 --- a/erts/emulator/beam/binary.c +++ b/erts/emulator/beam/binary.c @@ -117,7 +117,7 @@ new_binary(Process *p, byte *buf, Uint len) * When heap binary is not desired... */ -Eterm erts_new_mso_binary(Process *p, byte *buf, int len) +Eterm erts_new_mso_binary(Process *p, byte *buf, Uint len) { ProcBin* pb; Binary* bptr; diff --git a/erts/emulator/beam/erl_alloc.c b/erts/emulator/beam/erl_alloc.c index c367d4162c..3c2c9def3b 100644 --- a/erts/emulator/beam/erl_alloc.c +++ b/erts/emulator/beam/erl_alloc.c @@ -137,10 +137,13 @@ static ErtsAllocatorState_t exec_alloc_state; #endif static ErtsAllocatorState_t test_alloc_state; -#define ERTS_ALC_INFO_A_ALLOC_UTIL (ERTS_ALC_A_MAX + 1) -#define ERTS_ALC_INFO_A_MSEG_ALLOC (ERTS_ALC_A_MAX + 2) -#define ERTS_ALC_INFO_A_ERTS_MMAP (ERTS_ALC_A_MAX + 3) -#define ERTS_ALC_INFO_A_MAX ERTS_ALC_INFO_A_ERTS_MMAP +enum { + ERTS_ALC_INFO_A_ALLOC_UTIL = ERTS_ALC_A_MAX + 1, + ERTS_ALC_INFO_A_MSEG_ALLOC, + ERTS_ALC_INFO_A_ERTS_MMAP, + ERTS_ALC_INFO_A_DISABLED_EXEC, /* fake a disabled "exec_alloc" */ + ERTS_ALC_INFO_A_END +}; typedef struct { erts_smp_atomic32_t refc; @@ -150,7 +153,7 @@ typedef struct { Process *proc; Eterm ref; Eterm ref_heap[REF_THING_SIZE]; - int allocs[ERTS_ALC_INFO_A_MAX - ERTS_ALC_A_MIN + 1 + 1]; + int allocs[ERTS_ALC_INFO_A_END - ERTS_ALC_A_MIN + 1]; } ErtsAllocInfoReq; ERTS_SCHED_PREF_QUICK_ALLOC_IMPL(aireq, @@ -3260,6 +3263,12 @@ reply_alloc_info(void *vair) am_false); #endif break; +#ifndef ERTS_ALC_A_EXEC + case ERTS_ALC_INFO_A_DISABLED_EXEC: + alloc_atom = erts_bld_atom(hpp, szp, "exec_alloc"); + ainfo = erts_bld_tuple2(hpp, szp, alloc_atom, am_false); + break; +#endif default: alloc_atom = erts_bld_atom(hpp, szp, (char *) ERTS_ALC_A2AD(ai)); @@ -3287,7 +3296,8 @@ reply_alloc_info(void *vair) switch (ai) { case ERTS_ALC_A_SYSTEM: case ERTS_ALC_INFO_A_ALLOC_UTIL: - case ERTS_ALC_INFO_A_ERTS_MMAP: + case ERTS_ALC_INFO_A_ERTS_MMAP: + case ERTS_ALC_INFO_A_DISABLED_EXEC: break; case ERTS_ALC_INFO_A_MSEG_ALLOC: #if HAVE_ERTS_MSEG && defined(ERTS_SMP) @@ -3359,7 +3369,7 @@ erts_request_alloc_info(struct process *c_p, int internal) { ErtsAllocInfoReq *air = aireq_alloc(); - Eterm req_ai[ERTS_ALC_INFO_A_MAX+1] = {0}; + Eterm req_ai[ERTS_ALC_INFO_A_END] = {0}; Eterm alist; Eterm *hp; int airix = 0, ai; @@ -3399,6 +3409,12 @@ erts_request_alloc_info(struct process *c_p, ai = ERTS_ALC_INFO_A_ERTS_MMAP; goto save_alloc; } +#ifndef ERTS_ALC_A_EXEC + if (erts_is_atom_str("exec_alloc", alloc, 0)) { + ai = ERTS_ALC_INFO_A_DISABLED_EXEC; + goto save_alloc; + } +#endif if (erts_is_atom_str("alloc_util", alloc, 0)) { ai = ERTS_ALC_INFO_A_ALLOC_UTIL; save_alloc: diff --git a/erts/emulator/beam/erl_bif_re.c b/erts/emulator/beam/erl_bif_re.c index f4daecd2a4..ff7746ce1d 100644 --- a/erts/emulator/beam/erl_bif_re.c +++ b/erts/emulator/beam/erl_bif_re.c @@ -630,9 +630,15 @@ static Eterm build_exec_return(Process *p, int rc, RestartContext *restartp, Ete } } else { ReturnInfo *ri; - ReturnInfo defri = {RetIndex,0,{0}}; + ReturnInfo defri; if (restartp->ret_info == NULL) { + /* OpenBSD 5.8 gcc compiler for some reason creates + bad code if the above initialization is done + inline with the struct. So don't do that. */ + defri.type = RetIndex; + defri.num_spec = 0; + defri.v[0] = 0; ri = &defri; } else { ri = restartp->ret_info; diff --git a/erts/emulator/beam/erl_message.h b/erts/emulator/beam/erl_message.h index 851ac37fda..4493df1c1a 100644 --- a/erts/emulator/beam/erl_message.h +++ b/erts/emulator/beam/erl_message.h @@ -112,8 +112,8 @@ typedef struct erl_heap_fragment ErlHeapFragment; struct erl_heap_fragment { ErlHeapFragment* next; /* Next heap fragment */ ErlOffHeap off_heap; /* Offset heap data. */ - unsigned alloc_size; /* Size in (half)words of mem */ - unsigned used_size; /* With terms to be moved to heap by GC */ + Uint alloc_size; /* Size in (half)words of mem */ + Uint used_size; /* With terms to be moved to heap by GC */ Eterm mem[1]; /* Data */ }; diff --git a/erts/emulator/beam/erl_nif.c b/erts/emulator/beam/erl_nif.c index 8a3007d52a..606b73c7b5 100644 --- a/erts/emulator/beam/erl_nif.c +++ b/erts/emulator/beam/erl_nif.c @@ -96,7 +96,7 @@ void dtrace_nifenv_str(ErlNifEnv *, char *); #endif #define MIN_HEAP_FRAG_SZ 200 -static Eterm* alloc_heap_heavy(ErlNifEnv* env, unsigned need, Eterm* hp); +static Eterm* alloc_heap_heavy(ErlNifEnv* env, size_t need, Eterm* hp); static ERTS_INLINE int is_scheduler(void) @@ -135,7 +135,7 @@ execution_state(ErlNifEnv *env, Process **c_pp, int *schedp) } } -static ERTS_INLINE Eterm* alloc_heap(ErlNifEnv* env, unsigned need) +static ERTS_INLINE Eterm* alloc_heap(ErlNifEnv* env, size_t need) { Eterm* hp = env->hp; env->hp += need; @@ -145,7 +145,7 @@ static ERTS_INLINE Eterm* alloc_heap(ErlNifEnv* env, unsigned need) return alloc_heap_heavy(env, need, hp); } -static Eterm* alloc_heap_heavy(ErlNifEnv* env, unsigned need, Eterm* hp) +static Eterm* alloc_heap_heavy(ErlNifEnv* env, size_t need, Eterm* hp) { env->hp = hp; if (env->heap_frag == NULL) { @@ -166,7 +166,7 @@ static Eterm* alloc_heap_heavy(ErlNifEnv* env, unsigned need, Eterm* hp) } #if SIZEOF_LONG != ERTS_SIZEOF_ETERM -static ERTS_INLINE void ensure_heap(ErlNifEnv* env, unsigned may_need) +static ERTS_INLINE void ensure_heap(ErlNifEnv* env, size_t may_need) { if (env->hp + may_need > env->hp_end) { alloc_heap_heavy(env, may_need, env->hp); @@ -667,6 +667,9 @@ int enif_send(ErlNifEnv* env, const ErlNifPid* to_pid, erts_smp_proc_trylock(rp, ERTS_PROC_LOCK_MSGQ) == EBUSY) { if (!msgq) { +#ifdef ERTS_SMP + ErtsThrPrgrDelayHandle dhndl; +#endif msgq = erts_alloc(ERTS_ALC_T_TRACE_MSG_QUEUE, sizeof(ErlTraceMessageQueue)); @@ -681,8 +684,15 @@ int enif_send(ErlNifEnv* env, const ErlNifPid* to_pid, erts_smp_proc_unlock(t_p, ERTS_PROC_LOCK_TRACE); +#ifdef ERTS_SMP + if (!scheduler) + dhndl = erts_thr_progress_unmanaged_delay(); +#endif erts_schedule_flush_trace_messages(t_p->common.id); - +#ifdef ERTS_SMP + if (!scheduler) + erts_thr_progress_unmanaged_continue(dhndl); +#endif } else { msgq->len++; *msgq->last = mp; @@ -1197,7 +1207,7 @@ Eterm enif_make_sub_binary(ErlNifEnv* env, ERL_NIF_TERM bin_term, Eterm orig; Uint offset, bit_offset, bit_size; #ifdef DEBUG - unsigned src_size; + size_t src_size; ASSERT(is_binary(bin_term)); src_size = binary_size(bin_term); @@ -1669,7 +1679,8 @@ int enif_is_process_alive(ErlNifEnv* env, ErlNifPid *proc) return !!rp; #else erts_exit(ERTS_ABORT_EXIT, "enif_is_process_alive: " - "called from non-scheduler thread"); + "called from non-scheduler thread " + "in non-smp emulator"); return 0; #endif } @@ -1694,7 +1705,8 @@ int enif_is_port_alive(ErlNifEnv *env, ErlNifPort *port) return !!prt; #else erts_exit(ERTS_ABORT_EXIT, "enif_is_port_alive: " - "called from non-scheduler thread"); + "called from non-scheduler thread " + "in non-smp emulator"); return 0; #endif } @@ -1810,6 +1822,16 @@ int enif_fprintf(void* filep, const char* format, ...) return ret; } +int enif_snprintf(char *buffer, size_t size, const char* format, ...) +{ + int ret; + va_list arglist; + va_start(arglist, format); + ret = erts_vsnprintf(buffer, size, format, arglist); + va_end(arglist); + return ret; +} + /*********************************************************** ** Memory managed (GC'ed) "resource" objects ** ***********************************************************/ diff --git a/erts/emulator/beam/erl_nif.h b/erts/emulator/beam/erl_nif.h index 02c82415fd..da7a754757 100644 --- a/erts/emulator/beam/erl_nif.h +++ b/erts/emulator/beam/erl_nif.h @@ -49,9 +49,10 @@ ** 2.8: 18.0 add enif_has_pending_exception ** 2.9: 18.2 enif_getenv ** 2.10: Time API +** 2.11: 19.0 enif_snprintf */ #define ERL_NIF_MAJOR_VERSION 2 -#define ERL_NIF_MINOR_VERSION 10 +#define ERL_NIF_MINOR_VERSION 11 /* * The emulator will refuse to load a nif-lib with a major version diff --git a/erts/emulator/beam/erl_nif_api_funcs.h b/erts/emulator/beam/erl_nif_api_funcs.h index 1bdac51d1f..b211ab4b16 100644 --- a/erts/emulator/beam/erl_nif_api_funcs.h +++ b/erts/emulator/beam/erl_nif_api_funcs.h @@ -174,6 +174,7 @@ ERL_NIF_API_FUNC_DECL(int, enif_term_to_binary, (ErlNifEnv *env, ERL_NIF_TERM te ERL_NIF_API_FUNC_DECL(size_t, enif_binary_to_term, (ErlNifEnv *env, const unsigned char* data, size_t sz, ERL_NIF_TERM *term, unsigned int opts)); ERL_NIF_API_FUNC_DECL(int, enif_port_command, (ErlNifEnv *env, const ErlNifPort* to_port, ErlNifEnv *msg_env, ERL_NIF_TERM msg)); ERL_NIF_API_FUNC_DECL(int,enif_is_on_dirty_scheduler,(ErlNifEnv*)); +ERL_NIF_API_FUNC_DECL(int,enif_snprintf,(char * buffer, size_t size, const char *format, ...)); /* ** ADD NEW ENTRIES HERE (before this comment) !!! @@ -330,6 +331,7 @@ ERL_NIF_API_FUNC_DECL(int,enif_is_on_dirty_scheduler,(ErlNifEnv*)); # define enif_binary_to_term ERL_NIF_API_FUNC_MACRO(enif_binary_to_term) # define enif_port_command ERL_NIF_API_FUNC_MACRO(enif_port_command) # define enif_is_on_dirty_scheduler ERL_NIF_API_FUNC_MACRO(enif_is_on_dirty_scheduler) +# define enif_snprintf ERL_NIF_API_FUNC_MACRO(enif_snprintf) /* ** ADD NEW ENTRIES HERE (before this comment) diff --git a/erts/emulator/beam/erl_process.h b/erts/emulator/beam/erl_process.h index 2801947613..b44ac442aa 100644 --- a/erts/emulator/beam/erl_process.h +++ b/erts/emulator/beam/erl_process.h @@ -960,7 +960,6 @@ struct process { Uint heap_sz; /* Size of heap in words */ Uint min_heap_size; /* Minimum size of heap (in words). */ Uint min_vheap_size; /* Minimum size of virtual heap (in words). */ - Uint max_heap_size; /* Maximum size of heap (in words). */ #if !defined(NO_FPE_SIGNALS) || defined(HIPE) volatile unsigned long fp_exception; @@ -1061,6 +1060,7 @@ struct process { Eterm *old_hend; /* Heap pointers for generational GC. */ Eterm *old_htop; Eterm *old_heap; + Uint max_heap_size; /* Maximum size of heap (in words). */ Uint16 gen_gcs; /* Number of (minor) generational GCs. */ Uint16 max_gen_gcs; /* Max minor gen GCs before fullsweep. */ ErlOffHeap off_heap; /* Off-heap data updated by copy_struct(). */ @@ -1339,7 +1339,7 @@ ERTS_GLB_INLINE void erts_heap_frag_shrink(Process* p, Eterm* hp) { ErlHeapFragment* hf = MBUF(p); - ASSERT(hf!=NULL && (hp - hf->mem < (unsigned long)hf->alloc_size)); + ASSERT(hf!=NULL && (hp - hf->mem < hf->alloc_size)); hf->used_size = hp - hf->mem; } diff --git a/erts/emulator/beam/erl_unicode.c b/erts/emulator/beam/erl_unicode.c index 3c3536c021..bd5e1482fb 100644 --- a/erts/emulator/beam/erl_unicode.c +++ b/erts/emulator/beam/erl_unicode.c @@ -55,7 +55,7 @@ static BIF_RETTYPE finalize_list_to_list(Process *p, Uint num_processed_bytes, Uint num_bytes_to_process, Uint num_resulting_chars, - int state, int left, + int state, Sint left, Eterm tail); static BIF_RETTYPE characters_to_utf8_trap(BIF_ALIST_3); static BIF_RETTYPE characters_to_list_trap_1(BIF_ALIST_3); @@ -173,12 +173,13 @@ static ERTS_INLINE int allowed_iterations(Process *p) else return tmp; } -static ERTS_INLINE int cost_to_proc(Process *p, int cost) + +static ERTS_INLINE void cost_to_proc(Process *p, Sint cost) { - int x = (cost / LOOP_FACTOR); + Sint x = (cost / LOOP_FACTOR); BUMP_REDS(p,x); - return x; } + static ERTS_INLINE int simple_loops_to_common(int cost) { int factor = (LOOP_FACTOR_SIMPLE / LOOP_FACTOR); @@ -243,14 +244,15 @@ static int utf8_len(byte first) return -1; } -static int copy_utf8_bin(byte *target, byte *source, Uint size, - byte *leftover, int *num_leftovers, - byte **err_pos, Uint *characters) { - int copied = 0; +static Uint copy_utf8_bin(byte *target, byte *source, Uint size, + byte *leftover, int *num_leftovers, + byte **err_pos, Uint *characters) +{ + Uint copied = 0; if (leftover != NULL && *num_leftovers) { int need = utf8_len(leftover[0]); int from_source = need - (*num_leftovers); - int c; + Uint c; byte *tmp_err_pos = NULL; ASSERT(need > 0); ASSERT(from_source > 0); @@ -502,8 +504,8 @@ L_Again: /* Restart with sublist, old listend was pushed on stack */ } -static Eterm do_build_utf8(Process *p, Eterm ioterm, int *left, int latin1, - byte *target, int *pos, Uint *characters, int *err, +static Eterm do_build_utf8(Process *p, Eterm ioterm, Sint *left, int latin1, + byte *target, Uint *pos, Uint *characters, int *err, byte *leftover, int *num_leftovers) { int c; @@ -573,7 +575,7 @@ static Eterm do_build_utf8(Process *p, Eterm ioterm, int *left, int latin1, } if (!latin1) { - int num; + Uint num; byte *err_pos = NULL; num = copy_utf8_bin(target + (*pos), bytes, size, leftover, num_leftovers,&err_pos,characters); @@ -804,7 +806,7 @@ static int check_leftovers(byte *source, int size) -static BIF_RETTYPE build_utf8_return(Process *p,Eterm bin,int pos, +static BIF_RETTYPE build_utf8_return(Process *p,Eterm bin,Uint pos, Eterm rest_term,int err, byte *leftover,int num_leftovers,Eterm latin1) { @@ -859,8 +861,8 @@ static BIF_RETTYPE characters_to_utf8_trap(BIF_ALIST_3) #endif byte* bytes; Eterm rest_term; - int left, sleft; - int pos; + Sint left, sleft; + Uint pos; int err; byte leftover[4]; /* used for temp buffer too, otherwise 3 bytes would have been enough */ @@ -874,7 +876,7 @@ static BIF_RETTYPE characters_to_utf8_trap(BIF_ALIST_3) real_bin = binary_val(BIF_ARG_1); ASSERT(*real_bin == HEADER_PROC_BIN); #endif - pos = (int) binary_size(BIF_ARG_1); + pos = binary_size(BIF_ARG_1); bytes = binary_bytes(BIF_ARG_1); sleft = left = allowed_iterations(BIF_P); err = 0; @@ -934,9 +936,9 @@ BIF_RETTYPE unicode_characters_to_binary_2(BIF_ALIST_2) int latin1; Eterm bin; byte *bytes; - int pos; + Uint pos; int err; - int left, sleft; + Sint left, sleft; Eterm rest_term, subject; byte leftover[4]; /* used for temp buffer too, o therwise 3 bytes would have been enough */ @@ -999,7 +1001,7 @@ BIF_RETTYPE unicode_characters_to_binary_2(BIF_ALIST_2) byte *t = NULL; Uint sz = binary_size(bin); byte *by = erts_get_aligned_binary_bytes(bin,&t); - int i; + Uint i; erts_printf("<<"); for (i = 0;i < sz; ++i) { erts_printf((i == sz -1) ? "0x%X" : "0x%X, ", (unsigned) by[i]); @@ -1007,7 +1009,7 @@ BIF_RETTYPE unicode_characters_to_binary_2(BIF_ALIST_2) erts_printf(">>: "); erts_free_aligned_binary_bytes(t); } - erts_printf("%d - %d = %d\n",sleft,left,sleft - left); + erts_printf("%ld - %ld = %ld\n", sleft, left, sleft - left); } #endif cost_to_proc(BIF_P, sleft - left); @@ -1015,10 +1017,10 @@ BIF_RETTYPE unicode_characters_to_binary_2(BIF_ALIST_2) leftover,num_leftovers,BIF_ARG_2); } -static BIF_RETTYPE build_list_return(Process *p, byte *bytes, int pos, Uint characters, +static BIF_RETTYPE build_list_return(Process *p, byte *bytes, Uint pos, Uint characters, Eterm rest_term, int err, byte *leftover, int num_leftovers, - Eterm latin1, int left) + Eterm latin1, Sint left) { Eterm *hp; @@ -1070,11 +1072,11 @@ static BIF_RETTYPE characters_to_list_trap_1(BIF_ALIST_3) { RestartContext *rc; byte* bytes; - int pos; + Uint pos; Uint characters; int err; Eterm rest_term; - int left, sleft; + Sint left, sleft; int latin1 = 0; byte leftover[4]; /* used for temp buffer too, @@ -1107,9 +1109,9 @@ BIF_RETTYPE unicode_characters_to_list_2(BIF_ALIST_2) int latin1; Uint characters = 0; byte *bytes; - int pos; + Uint pos; int err; - int left, sleft; + Sint left, sleft; Eterm rest_term; byte leftover[4]; /* used for temp buffer too, o therwise 3 bytes would have been enough */ @@ -1541,7 +1543,7 @@ static BIF_RETTYPE finalize_list_to_list(Process *p, Uint num_processed_bytes, Uint num_bytes_to_process, Uint num_resulting_chars, - int state, int left, + int state, Sint left, Eterm tail) { Uint num_built; /* characters */ @@ -2016,7 +2018,7 @@ char *erts_convert_filename_to_encoding(Eterm name, char *statbuf, size_t statbu ++need; } if (used) - *used = (Sint) need; + *used = need; if (need+extra > statbuf_size) { name_buf = (char *) erts_alloc(alloc_type, need+extra); } else { diff --git a/erts/emulator/beam/global.h b/erts/emulator/beam/global.h index 1abcc6cbf4..b76b9cd874 100644 --- a/erts/emulator/beam/global.h +++ b/erts/emulator/beam/global.h @@ -947,7 +947,7 @@ ERTS_GLB_INLINE Eterm erts_equeue_get(ErtsEQueue *q) { void erts_emasculate_writable_binary(ProcBin* pb); Eterm erts_new_heap_binary(Process *p, byte *buf, int len, byte** datap); -Eterm erts_new_mso_binary(Process*, byte*, int); +Eterm erts_new_mso_binary(Process*, byte*, Uint); Eterm new_binary(Process*, byte*, Uint); Eterm erts_realloc_binary(Eterm bin, size_t size); diff --git a/erts/emulator/hipe/hipe_mode_switch.c b/erts/emulator/hipe/hipe_mode_switch.c index f532d3151f..884331e969 100644 --- a/erts/emulator/hipe/hipe_mode_switch.c +++ b/erts/emulator/hipe/hipe_mode_switch.c @@ -174,6 +174,33 @@ void hipe_mode_switch_init(void) make_catch(beam_catches_cons(hipe_beam_pc_throw, BEAM_CATCHES_NIL)); hipe_mfa_info_table_init(); + +#if (defined(__i386__) || defined(__x86_64__)) && defined(__linux__) + /* Verify that the offset of c-p->hipe does not change. + The ErLLVM hipe backend depends on it being in a specific + position. Kostis et al has promised to fix this in upstream + llvm by OTP 20, so it should be possible to remove these asserts + after that. */ + ERTS_CT_ASSERT(sizeof(ErtsPTabElementCommon) == + (sizeof(Eterm) + /* id */ + sizeof(((ErtsPTabElementCommon*)0)->refc) + + sizeof(ErtsTracer) + /* tracer */ + sizeof(Uint) + /* trace_flags */ + sizeof(erts_smp_atomic_t) + /* timer */ + sizeof(((ErtsPTabElementCommon*)0)->u))); + + ERTS_CT_ASSERT(offsetof(Process, hipe) == + (sizeof(ErtsPTabElementCommon) + /* common */ + sizeof(Eterm*) + /* htop */ + sizeof(Eterm*) + /* stop */ + sizeof(Eterm*) + /* heap */ + sizeof(Eterm*) + /* hend */ + sizeof(Uint) + /* heap_sz */ + sizeof(Uint) + /* min_heap_size */ + sizeof(Uint) + /* min_vheap_size */ + sizeof(volatile unsigned long))); /* fp_exception */ +#endif + } void hipe_set_call_trap(Uint *bfun, void *nfun, int is_closure) diff --git a/erts/emulator/test/alloc_SUITE.erl b/erts/emulator/test/alloc_SUITE.erl index 1f7b499dcb..84cf4921d3 100644 --- a/erts/emulator/test/alloc_SUITE.erl +++ b/erts/emulator/test/alloc_SUITE.erl @@ -73,16 +73,32 @@ migration(Cfg) -> end. erts_mmap(Config) when is_list(Config) -> - case os:type() of - {unix, _} -> + case {os:type(), mmsc_flags()} of + {{unix,_}, false} -> [erts_mmap_do(Config, SCO, SCRPM, SCRFSD) || SCO <-[true,false], SCRFSD <-[1234,0], SCRPM <- [true,false]]; - {SkipOs,_} -> + {{unix,_}, Flags} -> + {skipped, Flags}; + {{SkipOs,_},_} -> {skipped, lists:flatten(["Not run on " | io_lib:format("~p",[SkipOs])])} end. +%% Check if there are ERL_FLAGS set that will mess up this test case +mmsc_flags() -> + case mmsc_flags("ERL_FLAGS") of + false -> mmsc_flags("ERL_ZFLAGS"); + Flags -> Flags + end. +mmsc_flags(Env) -> + case os:getenv(Env) of + false -> false; + V -> case string:str(V, "+MMsc") of + 0 -> false; + P -> Env ++ "=" ++ string:substr(V, P) + end + end. erts_mmap_do(Config, SCO, SCRPM, SCRFSD) -> %% We use the number of schedulers + 1 * approx main carriers size diff --git a/erts/emulator/test/nif_SUITE.erl b/erts/emulator/test/nif_SUITE.erl index a1e1495480..a0e9f1bad6 100644 --- a/erts/emulator/test/nif_SUITE.erl +++ b/erts/emulator/test/nif_SUITE.erl @@ -45,7 +45,8 @@ nif_now_time/1, nif_cpu_time/1, nif_unique_integer/1, nif_is_process_alive/1, nif_is_port_alive/1, nif_term_to_binary/1, nif_binary_to_term/1, - nif_port_command/1 + nif_port_command/1, + nif_snprintf/1 ]). -export([many_args_100/100]). @@ -79,8 +80,8 @@ all() -> nif_now_time, nif_cpu_time, nif_unique_integer, nif_is_process_alive, nif_is_port_alive, nif_term_to_binary, nif_binary_to_term, - nif_port_command - ]. + nif_port_command, + nif_snprintf]. init_per_testcase(_Case, Config) -> Config. @@ -1952,9 +1953,18 @@ nif_port_command(Config) -> port_close(Port), {'EXIT', {badarg, _}} = (catch port_command_nif(Port, "hello\n")), + ok. +nif_snprintf(Config) -> + ensure_lib_loaded(Config), + <<"ok",0>> = format_term_nif(3,ok), + <<"o",0>> = format_term_nif(2,ok), + <<"\"hello world\"",0>> = format_term_nif(14,"hello world"), + <<"{{hello,world,-33},3.14",_/binary>> = format_term_nif(50,{{hello,world, -33}, 3.14, self()}), + <<"{{hello,world,-33},",0>> = format_term_nif(20,{{hello,world, -33}, 3.14, self()}), ok. + %% The NIFs: lib_version() -> undefined. call_history() -> ?nif_stub. @@ -2015,6 +2025,7 @@ is_port_alive_nif(_) -> ?nif_stub. term_to_binary_nif(_, _) -> ?nif_stub. binary_to_term_nif(_, _, _) -> ?nif_stub. port_command_nif(_, _) -> ?nif_stub. +format_term_nif(_,_) -> ?nif_stub. %% maps is_map_nif(_) -> ?nif_stub. diff --git a/erts/emulator/test/nif_SUITE_data/nif_SUITE.c b/erts/emulator/test/nif_SUITE_data/nif_SUITE.c index 73073ad59f..13846244d4 100644 --- a/erts/emulator/test/nif_SUITE_data/nif_SUITE.c +++ b/erts/emulator/test/nif_SUITE_data/nif_SUITE.c @@ -1998,6 +1998,23 @@ static ERL_NIF_TERM port_command(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar return atom_true; } +static ERL_NIF_TERM format_term(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +{ + ErlNifBinary obin; + unsigned int size; + + if (!enif_get_uint(env, argv[0], &size)) + return enif_make_badarg(env); + if (!enif_alloc_binary(size,&obin)) + return enif_make_badarg(env); + + if (enif_snprintf((char*)obin.data, (size_t)size, "%T", argv[1]) < 0) + return atom_false; + + return enif_make_binary(env,&obin); +} + + static ErlNifFunc nif_funcs[] = { {"lib_version", 0, lib_version}, @@ -2073,7 +2090,8 @@ static ErlNifFunc nif_funcs[] = {"is_port_alive_nif", 1, is_port_alive}, {"term_to_binary_nif", 2, term_to_binary}, {"binary_to_term_nif", 3, binary_to_term}, - {"port_command_nif", 2, port_command} + {"port_command_nif", 2, port_command}, + {"format_term_nif", 2, format_term} }; ERL_NIF_INIT(nif_SUITE,nif_funcs,load,reload,upgrade,unload) diff --git a/erts/emulator/test/port_trace_SUITE.erl b/erts/emulator/test/port_trace_SUITE.erl index bfdea0761b..5d9a75bcd3 100644 --- a/erts/emulator/test/port_trace_SUITE.erl +++ b/erts/emulator/test/port_trace_SUITE.erl @@ -31,7 +31,8 @@ failure_atom/1, failure_posix/1, failure/1, output_term/1, driver_output_term/1, - send_term/1, driver_send_term/1]). + send_term/1, driver_send_term/1, + driver_remote_send_term/1]). -define(ECHO_DRV_NOOP, 0). -define(ECHO_DRV_OUTPUT, 1). @@ -48,6 +49,7 @@ -define(ECHO_DRV_SEND_TERM, 12). -define(ECHO_DRV_DRIVER_SEND_TERM, 13). -define(ECHO_DRV_SAVE_CALLER, 14). +-define(ECHO_DRV_REMOTE_SEND_TERM, 15). suite() -> [{ct_hooks,[ts_install_cth]}, {timetrap, {seconds, 30}}]. @@ -60,7 +62,8 @@ all() -> failure_atom, failure_posix, failure, output_term, driver_output_term, - send_term, driver_send_term]. + send_term, driver_send_term, + driver_remote_send_term]. init_per_suite(Config) -> Config. @@ -75,6 +78,13 @@ end_per_group(_GroupName, Config) -> Config. +init_per_testcase(driver_remote_send_term, Config) -> + case erlang:system_info(smp_support) of + false -> + {skip,"Only supported on smp systems"}; + true -> + init_per_testcase(driver_remote_send_term_smp, Config) + end; init_per_testcase(Func, Config) when is_atom(Func), is_list(Config) -> erlang:trace(all, false, [all]), os:unsetenv("OUTPUTV"), @@ -543,6 +553,34 @@ driver_send_term(_Config) -> ok. +%% Test that driver_send_term from non-scheduler thread does not +%% generate trace messages. +driver_remote_send_term(_Config) -> + + Flags = [send], + {Prt, S} = trace_and_open(Flags,[binary]), + + erlang:port_command(Prt, <<?ECHO_DRV_REMOTE_SEND_TERM, 123456:32>>), + recv({echo, Prt, <<123456:32>>}), + [] = flush(), + + Pid = spawn_link( + fun() -> + erlang:port_command(Prt, <<?ECHO_DRV_SAVE_CALLER>>), + S ! ok, + receive M -> S ! M end + end), + recv(ok), + erlang:trace(Pid, true, ['receive']), + + erlang:port_command(Prt, <<?ECHO_DRV_REMOTE_SEND_TERM, 123456:32>>), + recv({echo, Prt, <<123456:32>>}), + [{trace, Pid, 'receive', {echo, Prt, <<123456:32>>}}] = flush(), + + close(Prt, Flags), + + ok. + %%%%%%%%%%%%%%%%%%% %% Helper functions %%%%%%%%%%%%%%%%%%% @@ -598,7 +636,7 @@ f(From) -> end. recv(Msg) -> - receive Msg -> ok after 100 -> ct:fail({did_not_get_data,Msg,flush()}) end. + receive Msg -> ok after 1000 -> ct:fail({did_not_get_data,Msg,flush()}) end. load_drv(Config) -> Path = proplists:get_value(data_dir, Config), diff --git a/erts/emulator/test/port_trace_SUITE_data/echo_drv.c b/erts/emulator/test/port_trace_SUITE_data/echo_drv.c index b5ae9389b4..b545523192 100644 --- a/erts/emulator/test/port_trace_SUITE_data/echo_drv.c +++ b/erts/emulator/test/port_trace_SUITE_data/echo_drv.c @@ -14,6 +14,13 @@ typedef struct _erl_drv_data { ErlDrvTermData caller; } EchoDrvData; +struct remote_send_term { + char *buf; + int len; + ErlDrvTermData port; + ErlDrvTermData caller; +}; + #define ECHO_DRV_NOOP 0 #define ECHO_DRV_OUTPUT 1 #define ECHO_DRV_OUTPUT2 2 @@ -29,6 +36,7 @@ typedef struct _erl_drv_data { #define ECHO_DRV_SEND_TERM 12 #define ECHO_DRV_DRIVER_SEND_TERM 13 #define ECHO_DRV_SAVE_CALLER 14 +#define ECHO_DRV_REMOTE_SEND_TERM 15 /* ------------------------------------------------------------------------- @@ -78,6 +86,8 @@ static ErlDrvEntry echo_drv_entry = { NULL }; +static void send_term_thread(void *); + /* ------------------------------------------------------------------------- ** Entry functions **/ @@ -200,6 +210,18 @@ static void echo_drv_output(ErlDrvData drv_data, char *buf, ErlDrvSizeT len) { } break; } + case ECHO_DRV_REMOTE_SEND_TERM: + { + ErlDrvTid tid; + struct remote_send_term *t = malloc(sizeof(struct remote_send_term)); + t->len = len-1; + t->buf = malloc(len-1); + t->port = driver_mk_port(port); + t->caller = data_p->caller; + memcpy(t->buf, buf+1, t->len); + erl_drv_thread_create("tmp_thread", &tid, send_term_thread, t, NULL); + break; + } case ECHO_DRV_SAVE_CALLER: data_p->caller = driver_caller(port); break; @@ -239,3 +261,17 @@ static ErlDrvSSizeT echo_drv_call(ErlDrvData drv_data, memcpy(*rbuf, buf+command, len-command); return len-command; } + +static void send_term_thread(void *a) +{ + struct remote_send_term *t = (struct remote_send_term*)a; + ErlDrvTermData term[] = { + ERL_DRV_ATOM, driver_mk_atom("echo"), + ERL_DRV_PORT, t->port, + ERL_DRV_BUF2BINARY, (ErlDrvTermData)(t->buf), + (ErlDrvTermData)(t->len), + ERL_DRV_TUPLE, 3}; + erl_drv_send_term(t->port, t->caller, + term, sizeof(term) / sizeof(ErlDrvTermData)); + return; +} |