diff options
author | Erlang/OTP <otp@erlang.org> | 2021-06-24 13:30:30 +0200 |
---|---|---|
committer | Erlang/OTP <otp@erlang.org> | 2021-06-24 13:30:30 +0200 |
commit | dcb551aa5a44780a8fe0d103fd1b9c4b8f4e2428 (patch) | |
tree | fde303b2d0a4841f02106248a61e71e732420dcf /erts/emulator/beam/erl_process.c | |
parent | 624f3a924abbce4bed67ca522d0b5c4d98dbb18b (diff) | |
parent | ee2dc019cc2bf78cacc15b3be02b8f7100414a61 (diff) | |
download | erlang-dcb551aa5a44780a8fe0d103fd1b9c4b8f4e2428.tar.gz |
Merge branch 'rickard/schedulers-online-fix/GH-4809/OTP-17500' into maint-24
* rickard/schedulers-online-fix/GH-4809/OTP-17500:
Fix erlang:system_flag(schedulers_online, _)
Diffstat (limited to 'erts/emulator/beam/erl_process.c')
-rw-r--r-- | erts/emulator/beam/erl_process.c | 43 |
1 files changed, 30 insertions, 13 deletions
diff --git a/erts/emulator/beam/erl_process.c b/erts/emulator/beam/erl_process.c index b798754764..76a9232159 100644 --- a/erts/emulator/beam/erl_process.c +++ b/erts/emulator/beam/erl_process.c @@ -7956,6 +7956,7 @@ erts_set_schedulers_online(Process *p, int online, increase; ErtsProcList *plp; int dirty_no, change_dirty, dirty_online; + Eterm resume_next = NIL; if (new_no < 1) return ERTS_SCHDLR_SSPND_EINVAL; @@ -7966,8 +7967,7 @@ erts_set_schedulers_online(Process *p, if (dirty_only) resume_proc = 0; - else - { + else { resume_proc = 1; /* * If we suspend current process we need to suspend before @@ -7987,8 +7987,7 @@ erts_set_schedulers_online(Process *p, have_unlocked_plocks = 0; no = (int) new_no; - if (!dirty_only) - { + if (!dirty_only) { changing = erts_atomic32_read_nob(&schdlr_sspnd.changing); if (changing & ERTS_SCHDLR_SSPND_CHNG_ONLN) { enqueue_wait: @@ -7997,7 +7996,7 @@ erts_set_schedulers_online(Process *p, erts_proclist_store_last(&schdlr_sspnd.chngq, plp); resume_proc = 0; res = ERTS_SCHDLR_SSPND_YIELD_RESTART; - goto done; + goto return_wait; } plp = erts_proclist_peek_first(schdlr_sspnd.chngq); if (!plp) { @@ -8007,6 +8006,7 @@ erts_set_schedulers_online(Process *p, ASSERT(schdlr_sspnd.changer == am_true); if (!erts_proclist_same(plp, p)) goto enqueue_wait; + schdlr_sspnd.changer = am_false; p->flags &= ~F_SCHDLR_ONLN_WAITQ; erts_proclist_remove(&schdlr_sspnd.chngq, plp); proclist_destroy(plp); @@ -8065,8 +8065,7 @@ erts_set_schedulers_online(Process *p, if (dirty_only) increase = (dirty_no > dirty_online); - else - { + else { change_flags |= ERTS_SCHDLR_SSPND_CHNG_ONLN; schdlr_sspnd_set_nscheds(&schdlr_sspnd.online, ERTS_SCHED_NORMAL, @@ -8091,8 +8090,7 @@ erts_set_schedulers_online(Process *p, dcpu_sched_ix_resume_wake(ix); } } - if (!dirty_only) - { + if (!dirty_only) { if (schdlr_sspnd.msb.ongoing|schdlr_sspnd.nmsb.ongoing) { for (ix = online; ix < no; ix++) erts_sched_poke(ERTS_SCHED_SLEEP_INFO_IX(ix)); @@ -8129,8 +8127,7 @@ erts_set_schedulers_online(Process *p, dcpu_sched_ix_wake(0); } } - if (!dirty_only) - { + if (!dirty_only) { if (schdlr_sspnd.msb.ongoing|schdlr_sspnd.nmsb.ongoing) { for (ix = no; ix < online; ix++) erts_sched_poke(ERTS_SCHED_SLEEP_INFO_IX(ix)); @@ -8155,13 +8152,24 @@ erts_set_schedulers_online(Process *p, if (change_flags & ERTS_SCHDLR_SSPND_CHNG_ONLN) { /* Suspend and wait for requested change to complete... */ + ASSERT(schdlr_sspnd.changer == am_false); schdlr_sspnd.changer = p->common.id; resume_proc = 0; res = ERTS_SCHDLR_SSPND_YIELD_DONE; } - + else { done: - + ASSERT(schdlr_sspnd.changer == am_false); + /* We're done; we may need to wake up a queued process... */ + plp = erts_proclist_peek_first(schdlr_sspnd.chngq); + if (plp) { + schdlr_sspnd.changer = am_true; /* change right in transit */ + /* resume process that is queued for next change... */ + resume_next = plp->u.pid; + ASSERT(is_internal_pid(resume_next)); + } + } +return_wait: ASSERT(schdlr_sspnd_get_nscheds(&schdlr_sspnd.online, ERTS_SCHED_DIRTY_CPU) <= schdlr_sspnd_get_nscheds(&schdlr_sspnd.online, @@ -8180,6 +8188,15 @@ done: erts_proc_unlock(p, ERTS_PROC_LOCK_STATUS); } + if (is_internal_pid(resume_next)) { + Process *rp = erts_proc_lookup(resume_next); + if (rp) { + erts_proc_lock(rp, ERTS_PROC_LOCK_STATUS); + resume_process(rp, ERTS_PROC_LOCK_STATUS); + erts_proc_unlock(rp, ERTS_PROC_LOCK_STATUS); + } + } + return res; } |