diff options
author | Rickard Green <[email protected]> | 2015-11-19 17:07:06 +0100 |
---|---|---|
committer | Rickard Green <[email protected]> | 2015-12-08 14:47:46 +0100 |
commit | a5dd6499d53ed596e2f8aa17ee35ff87cd32fe60 (patch) | |
tree | 26d671ac23cc2934706981318b0f7d6fee5affd4 | |
parent | cc3cc025f43a00281d2f836e12c2e1627cd50145 (diff) | |
download | otp-a5dd6499d53ed596e2f8aa17ee35ff87cd32fe60.tar.gz otp-a5dd6499d53ed596e2f8aa17ee35ff87cd32fe60.tar.bz2 otp-a5dd6499d53ed596e2f8aa17ee35ff87cd32fe60.zip |
Distinguish between GC disabled by BIFs and other disabled GC
Processes remember heap fragments that are known to be fully
live due to creation in a just called BIF that yields in the
live_hf_end field. This field must not be used if we have not
disabled GC in a BIF. F_DELAY_GC has been introduced in order
to distinguish between to two different scenarios.
- F_DISABLE_GC should *only* be used by BIFs. This when
the BIF needs to yield while preventig a GC.
- F_DELAY_GC should only be used when GC is temporarily
disabled while the process is scheduled. A process must
not be scheduled out while F_DELAY_GC is set.
-rw-r--r-- | erts/emulator/beam/beam_emu.c | 14 | ||||
-rw-r--r-- | erts/emulator/beam/erl_gc.c | 15 | ||||
-rw-r--r-- | erts/emulator/beam/erl_process.c | 2 | ||||
-rw-r--r-- | erts/emulator/beam/erl_process.h | 14 | ||||
-rw-r--r-- | erts/emulator/hipe/hipe_native_bif.c | 6 |
5 files changed, 37 insertions, 14 deletions
diff --git a/erts/emulator/beam/beam_emu.c b/erts/emulator/beam/beam_emu.c index 208a16dfd0..95a22e6c54 100644 --- a/erts/emulator/beam/beam_emu.c +++ b/erts/emulator/beam/beam_emu.c @@ -1843,8 +1843,8 @@ void process_main(void) * in the queue. This since messages with data outside * the heap will be corrupted by a GC. */ - ASSERT(!(c_p->flags & F_DISABLE_GC)); - c_p->flags |= F_DISABLE_GC; + ASSERT(!(c_p->flags & F_DELAY_GC)); + c_p->flags |= F_DELAY_GC; loop_rec__: PROCESS_MAIN_CHK_LOCKS(c_p); @@ -1858,7 +1858,7 @@ void process_main(void) if (ERTS_PROC_PENDING_EXIT(c_p)) { erts_smp_proc_unlock(c_p, ERTS_PROC_LOCKS_MSG_RECEIVE); SWAPOUT; - c_p->flags &= ~F_DISABLE_GC; + c_p->flags &= ~F_DELAY_GC; goto do_schedule; /* Will be rescheduled for exit */ } ERTS_SMP_MSGQ_MV_INQ2PRIVQ(c_p); @@ -1868,7 +1868,7 @@ void process_main(void) else #endif { - c_p->flags &= ~F_DISABLE_GC; + c_p->flags &= ~F_DELAY_GC; SET_I((BeamInstr *) Arg(0)); Goto(*I); /* Jump to a wait or wait_timeout instruction */ } @@ -1997,7 +1997,7 @@ void process_main(void) CANCEL_TIMER(c_p); erts_save_message_in_proc(c_p, msgp); - c_p->flags &= ~F_DISABLE_GC; + c_p->flags &= ~F_DELAY_GC; if (ERTS_IS_GC_DESIRED_INTERNAL(c_p, HTOP, E)) { /* @@ -2019,7 +2019,7 @@ void process_main(void) */ OpCase(loop_rec_end_f): { - ASSERT(c_p->flags & F_DISABLE_GC); + ASSERT(c_p->flags & F_DELAY_GC); SET_I((BeamInstr *) Arg(0)); SAVE_MESSAGE(c_p); @@ -2028,7 +2028,7 @@ void process_main(void) goto loop_rec__; } - c_p->flags &= ~F_DISABLE_GC; + c_p->flags &= ~F_DELAY_GC; c_p->i = I; SWAPOUT; c_p->arity = 0; diff --git a/erts/emulator/beam/erl_gc.c b/erts/emulator/beam/erl_gc.c index 3bb1f601aa..3784367195 100644 --- a/erts/emulator/beam/erl_gc.c +++ b/erts/emulator/beam/erl_gc.c @@ -440,8 +440,15 @@ delay_garbage_collection(Process *p, ErlHeapFragment *live_hf_end, int need) ERTS_HOLE_CHECK(p); - if (p->live_hf_end == ERTS_INVALID_HFRAG_PTR) + if ((p->flags & F_DISABLE_GC) + && p->live_hf_end == ERTS_INVALID_HFRAG_PTR) { + /* + * A BIF yielded with disabled GC. Remember + * heap fragments created by the BIF until we + * do next GC. + */ p->live_hf_end = live_hf_end; + } if (need == 0) return 1; @@ -564,10 +571,12 @@ garbage_collect(Process* p, ErlHeapFragment *live_hf_end, DTRACE_CHARBUF(pidbuf, DTRACE_TERM_BUF_SIZE); #endif - if (p->flags & F_DISABLE_GC) + if (p->flags & (F_DISABLE_GC|F_DELAY_GC)) return delay_garbage_collection(p, live_hf_end, need); - if (p->live_hf_end != ERTS_INVALID_HFRAG_PTR) + if (p->abandoned_heap) + live_hf_end = ERTS_INVALID_HFRAG_PTR; + else if (p->live_hf_end != ERTS_INVALID_HFRAG_PTR) live_hf_end = p->live_hf_end; esdp = erts_get_scheduler_data(); diff --git a/erts/emulator/beam/erl_process.c b/erts/emulator/beam/erl_process.c index ebe9361b8d..d17355207b 100644 --- a/erts/emulator/beam/erl_process.c +++ b/erts/emulator/beam/erl_process.c @@ -9262,6 +9262,8 @@ Process *schedule(Process *p, int calls) } else { sched_out_proc: + ASSERT(!(p->flags & F_DELAY_GC)); + #ifdef ERTS_SMP ERTS_SMP_CHK_HAVE_ONLY_MAIN_PROC_LOCK(p); esdp = p->scheduler_data; diff --git a/erts/emulator/beam/erl_process.h b/erts/emulator/beam/erl_process.h index b80aa12872..41b367435d 100644 --- a/erts/emulator/beam/erl_process.h +++ b/erts/emulator/beam/erl_process.h @@ -1288,10 +1288,22 @@ extern struct erts_system_profile_flags_t erts_system_profile_flags; #define F_HAVE_BLCKD_MSCHED (1 << 8) /* Process has blocked multi-scheduling */ #define F_P2PNR_RESCHED (1 << 9) /* Process has been rescheduled via erts_pid2proc_not_running() */ #define F_FORCE_GC (1 << 10) /* Force gc at process in-scheduling */ -#define F_DISABLE_GC (1 << 11) /* Disable GC */ +#define F_DISABLE_GC (1 << 11) /* Disable GC (see below) */ #define F_OFF_HEAP_MSGQ (1 << 12) /* Off heap msg queue */ #define F_OFF_HEAP_MSGQ_CHNG (1 << 13) /* Off heap msg queue changing */ #define F_ABANDONED_HEAP_USE (1 << 14) /* Have usage of abandoned heap */ +#define F_DELAY_GC (1 << 15) /* Similar to disable GC (see below) */ + +/* + * F_DISABLE_GC and F_DELAY_GC are similar. Both will prevent + * GC of the process, but it is important to use the right + * one: + * - F_DISABLE_GC should *only* be used by BIFs. This when + * the BIF needs to yield while preventig a GC. + * - F_DELAY_GC should only be used when GC is temporarily + * disabled while the process is scheduled. A process must + * not be scheduled out while F_DELAY_GC is set. + */ /* process trace_flags */ #define F_SENSITIVE (1 << 0) diff --git a/erts/emulator/hipe/hipe_native_bif.c b/erts/emulator/hipe/hipe_native_bif.c index ad8fb685e5..1bfee94e9e 100644 --- a/erts/emulator/hipe/hipe_native_bif.c +++ b/erts/emulator/hipe/hipe_native_bif.c @@ -164,7 +164,7 @@ void hipe_select_msg(Process *p) JOIN_MESSAGE(p); CANCEL_TIMER(p); /* calls erts_cancel_proc_timer() */ erts_save_message_in_proc(p, msgp); - p->flags &= ~F_DISABLE_GC; + p->flags &= ~F_DELAY_GC; if (ERTS_IS_GC_DESIRED(p)) { /* * We want to GC soon but we leave a few @@ -519,7 +519,7 @@ Eterm hipe_check_get_msg(Process *c_p) { ErtsMessage *msgp; - c_p->flags |= F_DISABLE_GC; + c_p->flags |= F_DELAY_GC; next_message: @@ -541,7 +541,7 @@ Eterm hipe_check_get_msg(Process *c_p) /* XXX: BEAM doesn't need this */ c_p->hipe_smp.have_receive_locks = 1; #endif - c_p->flags &= ~F_DISABLE_GC; + c_p->flags &= ~F_DELAY_GC; return THE_NON_VALUE; #ifdef ERTS_SMP } |