diff options
Diffstat (limited to 'erts/emulator/beam')
-rw-r--r-- | erts/emulator/beam/beam_bif_load.c | 46 | ||||
-rw-r--r-- | erts/emulator/beam/big.c | 11 | ||||
-rw-r--r-- | erts/emulator/beam/erl_bif_info.c | 26 | ||||
-rw-r--r-- | erts/emulator/beam/erl_gc.c | 5 | ||||
-rw-r--r-- | erts/emulator/beam/erl_port_task.c | 37 | ||||
-rw-r--r-- | erts/emulator/beam/erl_process.c | 3 | ||||
-rw-r--r-- | erts/emulator/beam/erl_process.h | 1 | ||||
-rw-r--r-- | erts/emulator/beam/erl_sched_spec_pre_alloc.c | 2 | ||||
-rw-r--r-- | erts/emulator/beam/erl_time_sup.c | 50 | ||||
-rw-r--r-- | erts/emulator/beam/erl_utils.h | 1 | ||||
-rw-r--r-- | erts/emulator/beam/io.c | 62 | ||||
-rw-r--r-- | erts/emulator/beam/sys.h | 14 |
12 files changed, 152 insertions, 106 deletions
diff --git a/erts/emulator/beam/beam_bif_load.c b/erts/emulator/beam/beam_bif_load.c index 27d6823d3c..b664532c1c 100644 --- a/erts/emulator/beam/beam_bif_load.c +++ b/erts/emulator/beam/beam_bif_load.c @@ -1051,23 +1051,32 @@ erts_proc_copy_literal_area(Process *c_p, int *redsp, int fcalls, int gc_allowed return am_ok; -literal_gc: +literal_gc: { + int hibernated = !!(c_p->flags & F_HIBERNATED); + int gc_cost; - if (!gc_allowed) - return am_need_gc; + if (!gc_allowed) + return am_need_gc; - if (c_p->flags & F_DISABLE_GC) - return THE_NON_VALUE; + if (c_p->flags & F_DISABLE_GC) + return THE_NON_VALUE; - FLAGS(c_p) |= F_NEED_FULLSWEEP; + FLAGS(c_p) |= F_NEED_FULLSWEEP; - *redsp += erts_garbage_collect_nobump(c_p, 0, c_p->arg_reg, c_p->arity, fcalls); + gc_cost = erts_garbage_collect_nobump(c_p, 0, c_p->arg_reg, c_p->arity, fcalls); + *redsp += gc_cost; - erts_garbage_collect_literals(c_p, (Eterm *) literals, lit_bsize, oh); + erts_garbage_collect_literals(c_p, (Eterm *) literals, lit_bsize, oh); - *redsp += lit_bsize / 64; /* Need, better value... */ + *redsp += lit_bsize / 64; /* Need, better value... */ - return am_ok; + if (hibernated) { + erts_garbage_collect_hibernate(c_p); + *redsp += gc_cost; + } + + return am_ok; + } } static Eterm @@ -1154,6 +1163,8 @@ check_process_code(Process* rp, Module* modp, Uint flags, int *redsp, int fcalls Eterm* sp; int done_gc = 0; int need_gc = 0; + int hibernated = !!(rp->flags & F_HIBERNATED); + int gc_cost = 0; ErtsMessage *msgp; ErlHeapFragment *hfrag; @@ -1288,8 +1299,13 @@ check_process_code(Process* rp, Module* modp, Uint flags, int *redsp, int fcalls while (1) { /* Check heap, stack etc... */ - if (check_mod_funs(rp, &rp->off_heap, mod_start, mod_size)) + if (check_mod_funs(rp, &rp->off_heap, mod_start, mod_size)) { + if (hibernated) { + /* GC wont help; everything on heap is live... */ + return am_true; + } goto try_gc; + } if (any_heap_ref_ptrs(&rp->fvalue, &rp->fvalue+1, literals, lit_bsize)) { rp->freason = EXC_NULL; rp->fvalue = NIL; @@ -1379,7 +1395,9 @@ check_process_code(Process* rp, Module* modp, Uint flags, int *redsp, int fcalls if (need_gc & ERTS_ORDINARY_GC__) { FLAGS(rp) |= F_NEED_FULLSWEEP; - *redsp += erts_garbage_collect_nobump(rp, 0, rp->arg_reg, rp->arity, fcalls); + gc_cost = erts_garbage_collect_nobump(rp, 0, rp->arg_reg, rp->arity, fcalls); + ASSERT(!hibernated || (need_gc & ERTS_LITERAL_GC__)); + *redsp += gc_cost; done_gc |= ERTS_ORDINARY_GC__; } if (need_gc & ERTS_LITERAL_GC__) { @@ -1388,6 +1406,10 @@ check_process_code(Process* rp, Module* modp, Uint flags, int *redsp, int fcalls *redsp += lit_bsize / 64; /* Need, better value... */ erts_garbage_collect_literals(rp, (Eterm*)literals, lit_bsize, oh); done_gc |= ERTS_LITERAL_GC__; + if (hibernated) { + erts_garbage_collect_hibernate(rp); + *redsp += gc_cost; + } } need_gc = 0; } diff --git a/erts/emulator/beam/big.c b/erts/emulator/beam/big.c index 4baee7900b..27064a4fd6 100644 --- a/erts/emulator/beam/big.c +++ b/erts/emulator/beam/big.c @@ -1293,8 +1293,11 @@ static dsize_t I_bxor(ErtsDigit* x, dsize_t xl, short xsgn, *r++ = ~c ^ *y++; x++; } - while(xl--) - *r++ = ~*x++; + while(xl--) { + DSUBb(*x,0,b,c); + *r++ = ~c; + x++; + } } else { ErtsDigit b1, b2; @@ -1312,7 +1315,9 @@ static dsize_t I_bxor(ErtsDigit* x, dsize_t xl, short xsgn, x++; y++; } while(xl--) { - *r++ = *x++; + DSUBb(*x,0,b1,c1); + *r++ = c1; + x++; } } } diff --git a/erts/emulator/beam/erl_bif_info.c b/erts/emulator/beam/erl_bif_info.c index 7bd45916f5..7791231d56 100644 --- a/erts/emulator/beam/erl_bif_info.c +++ b/erts/emulator/beam/erl_bif_info.c @@ -3468,24 +3468,32 @@ BIF_RETTYPE statistics_1(BIF_ALIST_1) res = TUPLE2(hp, b1, b2); BIF_RET(res); } else if (BIF_ARG_1 == am_runtime) { - UWord u1, u2, dummy; + ErtsMonotonicTime u1, u2; Eterm b1, b2; - elapsed_time_both(&u1,&dummy,&u2,&dummy); - b1 = erts_make_integer(u1,BIF_P); - b2 = erts_make_integer(u2,BIF_P); - hp = HAlloc(BIF_P,3); + Uint hsz; + elapsed_time_both(&u1, NULL, &u2, NULL); + hsz = 3; /* 2-tuple */ + (void) erts_bld_monotonic_time(NULL, &hsz, u1); + (void) erts_bld_monotonic_time(NULL, &hsz, u2); + hp = HAlloc(BIF_P, hsz); + b1 = erts_bld_monotonic_time(&hp, NULL, u1); + b2 = erts_bld_monotonic_time(&hp, NULL, u2); res = TUPLE2(hp, b1, b2); BIF_RET(res); } else if (BIF_ARG_1 == am_run_queue) { res = erts_run_queues_len(NULL, 1, 0); BIF_RET(make_small(res)); } else if (BIF_ARG_1 == am_wall_clock) { - UWord w1, w2; + ErtsMonotonicTime w1, w2; Eterm b1, b2; + Uint hsz; wall_clock_elapsed_time_both(&w1, &w2); - b1 = erts_make_integer((Uint) w1,BIF_P); - b2 = erts_make_integer((Uint) w2,BIF_P); - hp = HAlloc(BIF_P,3); + hsz = 3; /* 2-tuple */ + (void) erts_bld_monotonic_time(NULL, &hsz, w1); + (void) erts_bld_monotonic_time(NULL, &hsz, w2); + hp = HAlloc(BIF_P, hsz); + b1 = erts_bld_monotonic_time(&hp, NULL, w1); + b2 = erts_bld_monotonic_time(&hp, NULL, w2); res = TUPLE2(hp, b1, b2); BIF_RET(res); } else if (BIF_ARG_1 == am_io) { diff --git a/erts/emulator/beam/erl_gc.c b/erts/emulator/beam/erl_gc.c index bb36be0848..d2560cfb49 100644 --- a/erts/emulator/beam/erl_gc.c +++ b/erts/emulator/beam/erl_gc.c @@ -764,7 +764,7 @@ do_major_collection: esdp->gc_info.reclaimed += reclaimed_now; } - FLAGS(p) &= ~F_FORCE_GC; + FLAGS(p) &= ~(F_FORCE_GC|F_HIBERNATED); p->live_hf_end = ERTS_INVALID_HFRAG_PTR; ERTS_MSACC_POP_STATE_M(); @@ -929,6 +929,8 @@ erts_garbage_collect_hibernate(Process* p) ErtsGcQuickSanityCheck(p); + p->flags |= F_HIBERNATED; + erts_smp_atomic32_read_band_nob(&p->state, ~ERTS_PSFLG_GC); reds = gc_cost(actual_size, actual_size); @@ -1158,6 +1160,7 @@ erts_garbage_collect_literals(Process* p, Eterm* literals, /* * Restore status. */ + p->flags &= ~F_HIBERNATED; erts_smp_atomic32_read_band_nob(&p->state, ~ERTS_PSFLG_GC); } diff --git a/erts/emulator/beam/erl_port_task.c b/erts/emulator/beam/erl_port_task.c index 3102e44c11..2083a43f69 100644 --- a/erts/emulator/beam/erl_port_task.c +++ b/erts/emulator/beam/erl_port_task.c @@ -852,10 +852,11 @@ schedule_port_task_handle_list_free(ErtsPortTaskHandleList *pthlp) } static ERTS_INLINE void -abort_nosuspend_task(Port *pp, - ErtsPortTaskType type, - ErtsPortTaskTypeData *tdp, - int bpq_data) +abort_signal_task(Port *pp, + int abort_type, + ErtsPortTaskType type, + ErtsPortTaskTypeData *tdp, + int bpq_data) { ASSERT(type == ERTS_PORT_TASK_PROC_SIG); @@ -863,18 +864,28 @@ abort_nosuspend_task(Port *pp, if (!bpq_data) tdp->psig.callback(NULL, ERTS_PORT_SFLG_INVALID, - ERTS_PROC2PORT_SIG_ABORT_NOSUSPEND, + abort_type, &tdp->psig.data); else { ErlDrvSizeT size = erts_proc2port_sig_command_data_size(&tdp->psig.data); tdp->psig.callback(NULL, ERTS_PORT_SFLG_INVALID, - ERTS_PROC2PORT_SIG_ABORT_NOSUSPEND, + abort_type, &tdp->psig.data); aborted_proc2port_data(pp, size); } } + +static ERTS_INLINE void +abort_nosuspend_task(Port *pp, + ErtsPortTaskType type, + ErtsPortTaskTypeData *tdp, + int bpq_data) +{ + abort_signal_task(pp, ERTS_PROC2PORT_SIG_ABORT_NOSUSPEND, type, tdp, bpq_data); +} + static ErtsPortTaskHandleList * get_free_nosuspend_handles(Port *pp) { @@ -1613,8 +1624,9 @@ abort_nosuspend: ASSERT(ns_pthlp); erts_free(ERTS_ALC_T_PT_HNDL_LIST, ns_pthlp); - if (ptp) - port_task_free(ptp); + + ASSERT(ptp); + port_task_free(ptp); return 0; @@ -1625,12 +1637,15 @@ fail: erts_port_dec_refc(pp); #endif + if (ptp) { + abort_signal_task(pp, ERTS_PROC2PORT_SIG_ABORT, + ptp->type, &ptp->u.alive.td, 0); + port_task_free(ptp); + } + if (ns_pthlp) erts_free(ERTS_ALC_T_PT_HNDL_LIST, ns_pthlp); - if (ptp) - port_task_free(ptp); - return -1; } diff --git a/erts/emulator/beam/erl_process.c b/erts/emulator/beam/erl_process.c index 5c0322a7f6..54724fd62d 100644 --- a/erts/emulator/beam/erl_process.c +++ b/erts/emulator/beam/erl_process.c @@ -10476,7 +10476,8 @@ execute_sys_tasks(Process *c_p, erts_aint32_t *statep, int in_reds) reds--; } else { - if (!garbage_collected) { + if (!garbage_collected + && !(c_p->flags & F_HIBERNATED)) { FLAGS(c_p) |= F_NEED_FULLSWEEP; reds -= scheduler_gc_proc(c_p, reds); garbage_collected = 1; diff --git a/erts/emulator/beam/erl_process.h b/erts/emulator/beam/erl_process.h index 68fbb10602..b8755fe948 100644 --- a/erts/emulator/beam/erl_process.h +++ b/erts/emulator/beam/erl_process.h @@ -1395,6 +1395,7 @@ extern int erts_system_profile_ts_type; #define F_HAVE_BLCKD_NMSCHED (1 << 18) /* Process has blocked normal multi-scheduling */ #define F_HIPE_MODE (1 << 19) #define F_DELAYED_DEL_PROC (1 << 20) /* Delay delete process (dirty proc exit case) */ +#define F_HIBERNATED (1 << 21) /* Hibernated */ /* * F_DISABLE_GC and F_DELAY_GC are similar. Both will prevent diff --git a/erts/emulator/beam/erl_sched_spec_pre_alloc.c b/erts/emulator/beam/erl_sched_spec_pre_alloc.c index cab4bd73db..96238318c9 100644 --- a/erts/emulator/beam/erl_sched_spec_pre_alloc.c +++ b/erts/emulator/beam/erl_sched_spec_pre_alloc.c @@ -161,7 +161,7 @@ enqueue_remote_managed_thread(erts_sspa_chunk_header_t *chdr, if ((i & 1) == 0) itmp = itmp2; else { - enq = (erts_sspa_blk_t *) itmp; + enq = (erts_sspa_blk_t *) itmp2; itmp = erts_atomic_read_acqb(&enq->next_atmc); ASSERT(itmp != ERTS_AINT_NULL); } diff --git a/erts/emulator/beam/erl_time_sup.c b/erts/emulator/beam/erl_time_sup.c index 6aa2a7500f..1ef8c1b73a 100644 --- a/erts/emulator/beam/erl_time_sup.c +++ b/erts/emulator/beam/erl_time_sup.c @@ -1289,56 +1289,62 @@ erts_finalize_time_offset(void) /* info functions */ void -elapsed_time_both(UWord *ms_user, UWord *ms_sys, - UWord *ms_user_diff, UWord *ms_sys_diff) +elapsed_time_both(ErtsMonotonicTime *ms_user, ErtsMonotonicTime *ms_sys, + ErtsMonotonicTime *ms_user_diff, ErtsMonotonicTime *ms_sys_diff) { - UWord prev_total_user, prev_total_sys; - UWord total_user, total_sys; + ErtsMonotonicTime prev_total_user, prev_total_sys; + ErtsMonotonicTime total_user, total_sys; SysTimes now; sys_times(&now); - total_user = (now.tms_utime * 1000) / SYS_CLK_TCK; - total_sys = (now.tms_stime * 1000) / SYS_CLK_TCK; + total_user = (ErtsMonotonicTime) ((now.tms_utime * 1000) / SYS_CLK_TCK); + total_sys = (ErtsMonotonicTime) ((now.tms_stime * 1000) / SYS_CLK_TCK); if (ms_user != NULL) *ms_user = total_user; if (ms_sys != NULL) *ms_sys = total_sys; - erts_smp_mtx_lock(&erts_timeofday_mtx); + if (ms_user_diff || ms_sys_diff) { + erts_smp_mtx_lock(&erts_timeofday_mtx); - prev_total_user = (t_start.tms_utime * 1000) / SYS_CLK_TCK; - prev_total_sys = (t_start.tms_stime * 1000) / SYS_CLK_TCK; - t_start = now; + prev_total_user = (ErtsMonotonicTime) ((t_start.tms_utime * 1000) / SYS_CLK_TCK); + prev_total_sys = (ErtsMonotonicTime) ((t_start.tms_stime * 1000) / SYS_CLK_TCK); + t_start = now; - erts_smp_mtx_unlock(&erts_timeofday_mtx); + erts_smp_mtx_unlock(&erts_timeofday_mtx); - if (ms_user_diff != NULL) - *ms_user_diff = total_user - prev_total_user; + if (ms_user_diff != NULL) + *ms_user_diff = total_user - prev_total_user; - if (ms_sys_diff != NULL) - *ms_sys_diff = total_sys - prev_total_sys; + if (ms_sys_diff != NULL) + *ms_sys_diff = total_sys - prev_total_sys; + } } /* wall clock routines */ void -wall_clock_elapsed_time_both(UWord *ms_total, UWord *ms_diff) +wall_clock_elapsed_time_both(ErtsMonotonicTime *ms_total, ErtsMonotonicTime *ms_diff) { ErtsMonotonicTime now, elapsed; - erts_smp_mtx_lock(&erts_timeofday_mtx); - now = time_sup.r.o.get_time(); update_last_mtime(NULL, now); elapsed = ERTS_MONOTONIC_TO_MSEC(now); - *ms_total = (UWord) elapsed; - *ms_diff = (UWord) (elapsed - prev_wall_clock_elapsed); - prev_wall_clock_elapsed = elapsed; - erts_smp_mtx_unlock(&erts_timeofday_mtx); + *ms_total = elapsed; + + if (ms_diff) { + erts_smp_mtx_lock(&erts_timeofday_mtx); + + *ms_diff = elapsed - prev_wall_clock_elapsed; + prev_wall_clock_elapsed = elapsed; + + erts_smp_mtx_unlock(&erts_timeofday_mtx); + } } /* get current time */ diff --git a/erts/emulator/beam/erl_utils.h b/erts/emulator/beam/erl_utils.h index 81800752f0..b0912a346d 100644 --- a/erts/emulator/beam/erl_utils.h +++ b/erts/emulator/beam/erl_utils.h @@ -132,6 +132,7 @@ Eterm erts_bld_uint(Uint **hpp, Uint *szp, Uint ui); Eterm erts_bld_uword(Uint **hpp, Uint *szp, UWord uw); Eterm erts_bld_uint64(Uint **hpp, Uint *szp, Uint64 ui64); Eterm erts_bld_sint64(Uint **hpp, Uint *szp, Sint64 si64); +#define erts_bld_monotonic_time erts_bld_sint64 Eterm erts_bld_cons(Uint **hpp, Uint *szp, Eterm car, Eterm cdr); Eterm erts_bld_tuple(Uint **hpp, Uint *szp, Uint arity, ...); #define erts_bld_tuple2(H,S,E1,E2) erts_bld_tuple(H,S,2,E1,E2) diff --git a/erts/emulator/beam/io.c b/erts/emulator/beam/io.c index c3eb610fdc..caf8bfc294 100644 --- a/erts/emulator/beam/io.c +++ b/erts/emulator/beam/io.c @@ -1968,7 +1968,6 @@ int erts_port_output_async(Port *prt, Eterm from, Eterm list) { - ErtsPortOpResult res; ErtsProc2PortSigData *sigdp; erts_driver_t *drv = prt->drv_ptr; size_t size; @@ -2102,26 +2101,18 @@ erts_port_output_async(Port *prt, Eterm from, Eterm list) sigdp->u.output.size = size; port_sig_callback = port_sig_output; } - sigdp->flags = 0; ns_pthp = NULL; task_flags = 0; - res = erts_schedule_proc2port_signal(NULL, - prt, - ERTS_INVALID_PID, - NULL, - sigdp, - task_flags, - ns_pthp, - port_sig_callback); + erts_schedule_proc2port_signal(NULL, + prt, + ERTS_INVALID_PID, + NULL, + sigdp, + task_flags, + ns_pthp, + port_sig_callback); - if (res != ERTS_PORT_OP_SCHEDULED) { - if (drv->outputv) - cleanup_scheduled_outputv(evp, cbin); - else - cleanup_scheduled_output(buf); - return 1; - } return 1; bad_value: @@ -2554,10 +2545,6 @@ erts_port_output(Process *c_p, port_sig_callback); if (res != ERTS_PORT_OP_SCHEDULED) { - if (drv->outputv) - cleanup_scheduled_outputv(evp, cbin); - else - cleanup_scheduled_output(buf); return res; } @@ -2736,21 +2723,14 @@ erts_port_exit(Process *c_p, &bp->off_heap); } - res = erts_schedule_proc2port_signal(c_p, - prt, - c_p ? c_p->common.id : from, - refp, - sigdp, - 0, - NULL, - port_sig_exit); - - if (res == ERTS_PORT_OP_DROPPED) { - if (bp) - free_message_buffer(bp); - } - - return res; + return erts_schedule_proc2port_signal(c_p, + prt, + c_p ? c_p->common.id : from, + refp, + sigdp, + 0, + NULL, + port_sig_exit); } static ErtsPortOpResult @@ -4932,10 +4912,9 @@ erts_port_control(Process* c_p, 0, NULL, port_sig_control); - if (res != ERTS_PORT_OP_SCHEDULED) { - cleanup_scheduled_control(binp, bufp); + if (res != ERTS_PORT_OP_SCHEDULED) return ERTS_PORT_OP_BADARG; - } + return res; } @@ -5225,10 +5204,9 @@ erts_port_call(Process* c_p, 0, NULL, port_sig_call); - if (res != ERTS_PORT_OP_SCHEDULED) { - cleanup_scheduled_call(bufp); + if (res != ERTS_PORT_OP_SCHEDULED) return ERTS_PORT_OP_BADARG; - } + return res; } diff --git a/erts/emulator/beam/sys.h b/erts/emulator/beam/sys.h index d49edad6dc..950583bbfa 100644 --- a/erts/emulator/beam/sys.h +++ b/erts/emulator/beam/sys.h @@ -481,6 +481,12 @@ extern volatile int erts_break_requested; void erts_do_break_handling(void); #endif +#if !defined(ERTS_SMP) && !defined(__WIN32__) +extern volatile Uint erts_signal_sigterm; +#define ERTS_SIGNAL_SIGTERM erts_signal_sigterm +void erts_handle_signal_sigterm(void); +#endif + #ifdef ERTS_WANT_GOT_SIGUSR1 # ifndef UNIX # define ERTS_GOT_SIGUSR1 0 @@ -784,10 +790,10 @@ Preload* sys_preloaded(void); unsigned char* sys_preload_begin(Preload*); void sys_preload_end(Preload*); int sys_get_key(int); -void elapsed_time_both(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 elapsed_time_both(ErtsMonotonicTime *ms_user, ErtsMonotonicTime *ms_sys, + ErtsMonotonicTime *ms_user_diff, ErtsMonotonicTime *ms_sys_diff); +void wall_clock_elapsed_time_both(ErtsMonotonicTime *ms_total, + ErtsMonotonicTime *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, |