diff options
author | Erlang/OTP <[email protected]> | 2017-06-07 15:19:26 +0200 |
---|---|---|
committer | Erlang/OTP <[email protected]> | 2017-06-07 15:19:26 +0200 |
commit | c64686a632a550b7c227307ec9af43857c2fd6d9 (patch) | |
tree | 5c0972d701fb19f85d6cc567bb4d04e0001cd90c /erts/emulator/beam | |
parent | 4310a9d387999ada6135082961350b6f4324dcb7 (diff) | |
parent | 39a41b0472f275e71ae9bb6abf3bb8b3c995b8e3 (diff) | |
download | otp-c64686a632a550b7c227307ec9af43857c2fd6d9.tar.gz otp-c64686a632a550b7c227307ec9af43857c2fd6d9.tar.bz2 otp-c64686a632a550b7c227307ec9af43857c2fd6d9.zip |
Merge branch 'rickard/purge-hibernated-19/ERIERL-24/OTP-14444' into maint-19
* rickard/purge-hibernated-19/ERIERL-24/OTP-14444:
Update testcase to check that purge handle hibernated process correct
Do not GC hibernated process from other processes
Fix check_process_code() on hibernated process
Diffstat (limited to 'erts/emulator/beam')
-rw-r--r-- | erts/emulator/beam/beam_bif_load.c | 46 | ||||
-rw-r--r-- | erts/emulator/beam/erl_gc.c | 5 | ||||
-rw-r--r-- | erts/emulator/beam/erl_process.c | 3 | ||||
-rw-r--r-- | erts/emulator/beam/erl_process.h | 1 |
4 files changed, 41 insertions, 14 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/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_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 |