aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSverker Eriksson <[email protected]>2014-03-27 20:59:01 +0100
committerSverker Eriksson <[email protected]>2014-03-27 20:59:01 +0100
commit56018ef95e70c5630c1c6fe16d22b54f8ecd0791 (patch)
tree8504196098cc4bb9d32f43e283b7476044206fee
parenta74e66a68f3b4ed590f928b4fd4f0808c6287a32 (diff)
downloadotp-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)));
-rw-r--r--erts/emulator/beam/erl_process.c15
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) {