From nobody Tue Jun 14 16:01:10 2022 X-Original-To: dev-commits-src-main@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id DAE2F831DA1; Tue, 14 Jun 2022 16:01:10 +0000 (UTC) (envelope-from git@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) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4LMtTL5Lt4z4vM7; Tue, 14 Jun 2022 16:01:10 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1655222470; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=WQwPM2zqv3oH2ZYhdgFgLD6qnP+tM425wp1ORGpkf60=; b=Pqr2IcpOU0wUkAVPEckOjOV5dxVH3oB/xW7YY78hcyuWCZI9di9hEui21LdOOqRsvXCNSR x1/pBKUwnqb6P1PuQwtecPKMHfvmB8+Jtzai2jTTEl6NDsdXjy9zRvasjpkmFnZq082SwY NUFG2qjgKaUpqoDcLlyuO8fmGuEOf3pqo22rGQUBqs5J3QEbFpIOxc0DTSUiJ4TjsyArRW fxvoMhODl8dLHdTzp2DL3d2X6JlPdbs1KZqSspUVeTSE0Leg72sKKt2+JwoILjmXr4Agk0 9d5+aBbJvZUJ7fblUJsXFkGz7Cbf4ur3xwy1OUwRGZ7eUfQiAsBZvqGKcuy9VQ== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 8D4CF505D; Tue, 14 Jun 2022 16:01:10 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.16.1/8.16.1) with ESMTP id 25EG1AvN082553; Tue, 14 Jun 2022 16:01:10 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 25EG1APA082552; Tue, 14 Jun 2022 16:01:10 GMT (envelope-from git) Date: Tue, 14 Jun 2022 16:01:10 GMT Message-Id: <202206141601.25EG1APA082552@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Mark Johnston Subject: git: e8955bd643ee - main - pipe: Use a distinct wait channel for I/O serialization List-Id: Commit messages for the main branch of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-main List-Help: List-Post: List-Subscribe: List-Unsubscribe: Sender: owner-dev-commits-src-main@freebsd.org X-BeenThere: dev-commits-src-main@freebsd.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: markj X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: e8955bd643ee852d70a0b065f2a0d1bb3fa99df2 Auto-Submitted: auto-generated ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1655222470; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=WQwPM2zqv3oH2ZYhdgFgLD6qnP+tM425wp1ORGpkf60=; b=G4XkUdmk6g3nA7xSoOOUlc3UUuR6tb/G+j98eUiVDalk3qHc5R/owy9nGNRTbcXQ9MN1DL QktMh0SyLdj0GBOh/KZosanbEkDplFgN3HlPKrDqnkY1sN7tT3FC946BM65UaKaSgDqX1q LgjDhKvmDUEEqdrSTu2AHijdc2Pv5e1D52qSeDxrGahdE3rRvphd6nsIFJaqgZCDEyOv0w 0ne1Go7m+SZSmx376RH86HAmkxosfFQ+w6UwEwapLamN+8TwD6jAPLvnl2L6CDdK+xad1Z W1k9/5gloJyVnlOLedMwIDIiuE9OHi2U7kic5qFjAOKgefjJ6Jsqu24qHHalow== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1655222470; a=rsa-sha256; cv=none; b=ZmM/3QIxOvtfiaKIbu6gI5xrRNS6NV0w2WpxQtpHxIecQDrBuINukTJIrhIwsrWfjQ0Gs6 o63no041UW9wMiRZYDxlFiBgC78i22adzNVUIfZRrqyv98vR//sWQNtY0pYreIP1L9uRMa VexlfuoXdxAgguAGsCXy+nk7mrZQisWKO5tcsGXWM3gYvZxvr/w77RHzQBhRBq5paYhz69 u4RfiT/gL0UrRIt10luAU9qHQNCCXKl3bxEP8KJOFvO8usnkh3sZ/rUZAjzQRfnFeorqRS FqKCP1A97HqMYf+5D8vlijpK0PF+a9RWRnGt4n9hntsg+jcF8ohUzoc19ksXlA== ARC-Authentication-Results: i=1; mx1.freebsd.org; none X-ThisMailContainsUnwantedMimeParts: N The branch main has been updated by markj: URL: https://cgit.FreeBSD.org/src/commit/?id=e8955bd643ee852d70a0b065f2a0d1bb3fa99df2 commit e8955bd643ee852d70a0b065f2a0d1bb3fa99df2 Author: Mark Johnston AuthorDate: 2022-06-14 14:52:03 +0000 Commit: Mark Johnston CommitDate: 2022-06-14 16:00:59 +0000 pipe: Use a distinct wait channel for I/O serialization Suppose a thread tries to read from an empty pipe. pipe_read() does the following: 1. pipelock(), possibly sleeping 2. check for buffered data 3. pipeunlock() 4. set PIPE_WANTR and sleep 5. goto 1 pipelock() is an open-coded mutex; if a thread blocks in pipelock(), it sleeps until the lock holder calls pipeunlock(). Both sleeps use the same wait channel. So if there are multiple threads in pipe_read(), a thread T1 in step 3 can wake up a thread T2 sleeping in step 4. Then T1 goes to sleep in step 4, and T2 acquires and releases the pipelock, waking up T1 again. This can go on indefinitely, livelocking the process (and potentially starving a would-be writer). Fix the problem by using a separate wait channel for pipelock(). Reported by: Paul Floyd Reviewed by: mjg, kib PR: 264441 MFC after: 1 month Sponsored by: The FreeBSD Foundation Differential Revision: https://reviews.freebsd.org/D35415 --- sys/kern/sys_pipe.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/sys/kern/sys_pipe.c b/sys/kern/sys_pipe.c index 32ed17c0fe23..ed93a2b7f094 100644 --- a/sys/kern/sys_pipe.c +++ b/sys/kern/sys_pipe.c @@ -651,8 +651,8 @@ pipelock(struct pipe *cpipe, int catch) ("%s: bad waiter count %d", __func__, cpipe->pipe_waiters)); cpipe->pipe_waiters++; - error = msleep(cpipe, PIPE_MTX(cpipe), - prio, "pipelk", 0); + error = msleep(&cpipe->pipe_waiters, PIPE_MTX(cpipe), prio, + "pipelk", 0); cpipe->pipe_waiters--; if (error != 0) return (error); @@ -675,9 +675,8 @@ pipeunlock(struct pipe *cpipe) ("%s: bad waiter count %d", __func__, cpipe->pipe_waiters)); cpipe->pipe_state &= ~PIPE_LOCKFL; - if (cpipe->pipe_waiters > 0) { - wakeup_one(cpipe); - } + if (cpipe->pipe_waiters > 0) + wakeup_one(&cpipe->pipe_waiters); } void