From cd1a07009858ba01a2a095ffb9f863d2225e572c Mon Sep 17 00:00:00 2001 From: Rickard Green Date: Tue, 19 Jan 2010 13:21:37 +0000 Subject: OTP-8342 Processes, and/or ports could get stuck on a blocked scheduler when erlang:system_flag(multi_scheduling, block) was used. Processes, and/or ports could get stuck on an offline scheduler when schedulers online were reduced using erlang:system_flag(schedulers_online, SchedulersOnline). --- erts/emulator/beam/erl_port_task.c | 58 +++++++++++++++++++++++++------------- erts/emulator/beam/erl_process.c | 2 ++ 2 files changed, 41 insertions(+), 19 deletions(-) (limited to 'erts/emulator/beam') diff --git a/erts/emulator/beam/erl_port_task.c b/erts/emulator/beam/erl_port_task.c index 0fb264a53c..3cb5a966ac 100644 --- a/erts/emulator/beam/erl_port_task.c +++ b/erts/emulator/beam/erl_port_task.c @@ -1,19 +1,19 @@ /* * %CopyrightBegin% - * - * Copyright Ericsson AB 2006-2009. All Rights Reserved. - * + * + * Copyright Ericsson AB 2006-2010. All Rights Reserved. + * * The contents of this file are subject to the Erlang Public License, * Version 1.1, (the "License"); you may not use this file except in * compliance with the License. You should have received a copy of the * Erlang Public License along with this software. If not, it can be * retrieved online at http://www.erlang.org/. - * + * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See * the License for the specific language governing rights and limitations * under the License. - * + * * %CopyrightEnd% */ @@ -902,25 +902,45 @@ erts_port_task_execute(ErtsRunQueue *runq, Port **curr_port_pp) *curr_port_pp = NULL; - if (pp->sched.taskq) { +#ifdef ERTS_SMP + ASSERT(runq == (ErtsRunQueue *) erts_smp_atomic_read(&pp->run_queue)); +#endif + + if (!pp->sched.taskq) { + ASSERT(pp->sched.exe_taskq); + pp->sched.exe_taskq = NULL; + } + else { +#ifdef ERTS_SMP + ErtsRunQueue *xrunq; +#endif + ASSERT(!(pp->status & ERTS_PORT_SFLGS_DEAD)); ASSERT(pp->sched.taskq->first); - enqueue_port(runq, pp); - port_was_enqueued = 1; - - /* - erts_smp_notify_inc_runq(); - * No need to notify schedulers about the increase in run - * queue length since at least this thread, which is a - * scheduler, will discover that the port run queue isn't - * empty before trying to go to sleep. - */ +#ifdef ERTS_SMP + xrunq = erts_check_emigration_need(runq, ERTS_PORT_PRIO_LEVEL); + if (!xrunq) { +#endif + enqueue_port(runq, pp); + ASSERT(pp->sched.exe_taskq); + pp->sched.exe_taskq = NULL; + /* No need to notify ourselves about inc in runq. */ +#ifdef ERTS_SMP + } + else { + /* Port emigrated ... */ + erts_smp_atomic_set(&pp->run_queue, (long) xrunq); + enqueue_port(xrunq, pp); + ASSERT(pp->sched.exe_taskq); + pp->sched.exe_taskq = NULL; + erts_smp_notify_inc_runq(xrunq); + erts_smp_runq_unlock(xrunq); + } +#endif + port_was_enqueued = 1; } - ASSERT(pp->sched.exe_taskq); - pp->sched.exe_taskq = NULL; - res = erts_smp_atomic_read(&erts_port_task_outstanding_io_tasks) != (long) 0; ERTS_PT_CHK_PRES_PORTQ(runq, pp); diff --git a/erts/emulator/beam/erl_process.c b/erts/emulator/beam/erl_process.c index 5f512a9982..476e29d96f 100644 --- a/erts/emulator/beam/erl_process.c +++ b/erts/emulator/beam/erl_process.c @@ -5517,6 +5517,8 @@ erts_proc_migrate(Process *p, ErtsProcLocks *plcks, p->run_queue = to_rq; enqueue_process(to_rq, p); + smp_notify_inc_runq(to_rq); + return ERTS_MIGRATE_SUCCESS; } #endif /* ERTS_SMP */ -- cgit v1.2.3