From owner-svn-src-head@freebsd.org Thu Dec 12 02:43:25 2019 Return-Path: Delivered-To: svn-src-head@mailman.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.nyi.freebsd.org (Postfix) with ESMTP id 5CFB11E8E86; Thu, 12 Dec 2019 02:43:25 +0000 (UTC) (envelope-from markj@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) server-signature RSA-PSS (4096 bits) client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 47YJ591qTbz4054; Thu, 12 Dec 2019 02:43:25 +0000 (UTC) (envelope-from markj@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 399361D1FA; Thu, 12 Dec 2019 02:43:25 +0000 (UTC) (envelope-from markj@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id xBC2hPx7004057; Thu, 12 Dec 2019 02:43:25 GMT (envelope-from markj@FreeBSD.org) Received: (from markj@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id xBC2hPs6004056; Thu, 12 Dec 2019 02:43:25 GMT (envelope-from markj@FreeBSD.org) Message-Id: <201912120243.xBC2hPs6004056@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: markj set sender to markj@FreeBSD.org using -f From: Mark Johnston Date: Thu, 12 Dec 2019 02:43:25 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r355644 - head/sys/kern X-SVN-Group: head X-SVN-Commit-Author: markj X-SVN-Commit-Paths: head/sys/kern X-SVN-Commit-Revision: 355644 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 12 Dec 2019 02:43:25 -0000 Author: markj Date: Thu Dec 12 02:43:24 2019 New Revision: 355644 URL: https://svnweb.freebsd.org/changeset/base/355644 Log: Rename tdq_ipipending and clear it in sched_switch(). This fixes a regression after r355311. Specifically, sched_preempt() may trigger a context switch by calling thread_lock(), since thread_lock() calls critical_exit() in its slow path and the interrupted thread may have already been marked for preemption. This would happen before tdq_ipipending is cleared, blocking further preemption IPIs. The CPU can be left in this state indefinitely if the interrupted thread migrates. Rename tdq_ipipending to tdq_owepreempt. Any switch satisfies a remote preemption request, so clear tdq_owepreempt in sched_switch() instead of sched_preempt() to avoid subtle problems of the sort described above. Reviewed by: jeff, kib Sponsored by: The FreeBSD Foundation Differential Revision: https://reviews.freebsd.org/D22758 Modified: head/sys/kern/sched_ule.c Modified: head/sys/kern/sched_ule.c ============================================================================== --- head/sys/kern/sched_ule.c Thu Dec 12 02:42:27 2019 (r355643) +++ head/sys/kern/sched_ule.c Thu Dec 12 02:43:24 2019 (r355644) @@ -244,7 +244,7 @@ struct tdq { volatile short tdq_switchcnt; /* Switches this tick. */ volatile short tdq_oldswitchcnt; /* Switches last tick. */ u_char tdq_lowpri; /* Lowest priority thread. */ - u_char tdq_ipipending; /* IPI pending. */ + u_char tdq_owepreempt; /* Remote preemption pending. */ u_char tdq_idx; /* Current insert index. */ u_char tdq_ridx; /* Current removal index. */ int tdq_id; /* cpuid. */ @@ -1073,7 +1073,7 @@ tdq_notify(struct tdq *tdq, struct thread *td) int pri; int cpu; - if (tdq->tdq_ipipending) + if (tdq->tdq_owepreempt) return; cpu = td_get_sched(td)->ts_cpu; pri = td->td_priority; @@ -1096,7 +1096,12 @@ tdq_notify(struct tdq *tdq, struct thread *td) if (!tdq->tdq_cpu_idle || cpu_idle_wakeup(cpu)) return; } - tdq->tdq_ipipending = 1; + + /* + * The run queues have been updated, so any switch on the remote CPU + * will satisfy the preemption request. + */ + tdq->tdq_owepreempt = 1; ipi_cpu(cpu, IPI_PREEMPT); } @@ -2079,8 +2084,10 @@ sched_switch(struct thread *td, struct thread *newtd, (flags & SW_PREEMPT) != 0; td->td_flags &= ~(TDF_NEEDRESCHED | TDF_SLICEEND); td->td_owepreempt = 0; + tdq->tdq_owepreempt = 0; if (!TD_IS_IDLETHREAD(td)) tdq->tdq_switchcnt++; + /* * The lock pointer in an idle thread should never change. Reset it * to CAN_RUN as well. @@ -2386,7 +2393,6 @@ sched_preempt(struct thread *td) thread_lock(td); tdq = TDQ_SELF(); TDQ_LOCK_ASSERT(tdq, MA_OWNED); - tdq->tdq_ipipending = 0; if (td->td_priority > tdq->tdq_lowpri) { int flags; @@ -2397,6 +2403,8 @@ sched_preempt(struct thread *td) mi_switch(flags | SWT_REMOTEWAKEIDLE, NULL); else mi_switch(flags | SWT_REMOTEPREEMPT, NULL); + } else { + tdq->tdq_owepreempt = 0; } thread_unlock(td); }