diff options
author | Sverker Eriksson <[email protected]> | 2014-03-27 20:59:01 +0100 |
---|---|---|
committer | Sverker Eriksson <[email protected]> | 2014-03-27 20:59:01 +0100 |
commit | 56018ef95e70c5630c1c6fe16d22b54f8ecd0791 (patch) | |
tree | 8504196098cc4bb9d32f43e283b7476044206fee /erts/emulator/beam/erl_process.c | |
parent | a74e66a68f3b4ed590f928b4fd4f0808c6287a32 (diff) | |
download | otp-56018ef95e70c5630c1c6fe16d22b54f8ecd0791.tar.gz otp-56018ef95e70c5630c1c6fe16d22b54f8ecd0791.tar.bz2 otp-56018ef95e70c5630c1c6fe16d22b54f8ecd0791.zip |
erts: Fix bug of scheduling a suspended process
This is a race that can cause RUNNING (instead of RUNNING_SYS)
set on a SUSPENDED process. The effect of this race happening is probably
quite benign.
The bug was discovered by process_SUITE:processes_gc_trap on debug VM
crashing on last assert in schedule():
/* Never run a suspended process */
ASSERT(!(ERTS_PSFLG_SUSPENDED & erts_smp_atomic32_read_nob(&p->state)));
Diffstat (limited to 'erts/emulator/beam/erl_process.c')
-rw-r--r-- | erts/emulator/beam/erl_process.c | 15 |
1 files changed, 6 insertions, 9 deletions
diff --git a/erts/emulator/beam/erl_process.c b/erts/emulator/beam/erl_process.c index 37e1d07107..bc69d5ad91 100644 --- a/erts/emulator/beam/erl_process.c +++ b/erts/emulator/beam/erl_process.c @@ -9207,7 +9207,6 @@ Process *schedule(Process *p, int calls) */ pick_next_process: { erts_aint32_t psflg_band_mask; - erts_aint32_t running_flag; int prio_q; int qmask; @@ -9269,12 +9268,6 @@ Process *schedule(Process *p, int calls) state = erts_smp_atomic32_read_nob(&p->state); } - - if (state & ERTS_PSFLG_ACTIVE_SYS) - running_flag = ERTS_PSFLG_RUNNING_SYS; - else - running_flag = ERTS_PSFLG_RUNNING; - while (1) { erts_aint32_t exp, new, tmp; tmp = new = exp = state; @@ -9284,8 +9277,12 @@ Process *schedule(Process *p, int calls) tmp = state & (ERTS_PSFLG_SUSPENDED | ERTS_PSFLG_PENDING_EXIT | ERTS_PSFLG_ACTIVE_SYS); - if (tmp != ERTS_PSFLG_SUSPENDED) - new |= running_flag; + if (tmp != ERTS_PSFLG_SUSPENDED) { + if (state & ERTS_PSFLG_ACTIVE_SYS) + new |= ERTS_PSFLG_RUNNING_SYS; + else + new |= ERTS_PSFLG_RUNNING; + } } state = erts_smp_atomic32_cmpxchg_relb(&p->state, new, exp); if (state == exp) { |