svn commit: r367852 - in head/sys: kern sys

Mateusz Guzik mjg at FreeBSD.org
Thu Nov 19 19:25:48 UTC 2020


Author: mjg
Date: Thu Nov 19 19:25:47 2020
New Revision: 367852
URL: https://svnweb.freebsd.org/changeset/base/367852

Log:
  pipe: thundering herd problem in pipelock
  
  All reads and writes are serialized with a hand-rolled lock, but unlocking it
  always wakes up all waiters. Existing flag fields get resized to make room for
  introduction of waiter counter without growing the struct.
  
  Reviewed by:	kib
  Differential Revision:	https://reviews.freebsd.org/D27273

Modified:
  head/sys/kern/sys_pipe.c
  head/sys/sys/pipe.h

Modified: head/sys/kern/sys_pipe.c
==============================================================================
--- head/sys/kern/sys_pipe.c	Thu Nov 19 19:05:16 2020	(r367851)
+++ head/sys/kern/sys_pipe.c	Thu Nov 19 19:25:47 2020	(r367852)
@@ -622,9 +622,13 @@ pipelock(struct pipe *cpipe, int catch)
 	if (catch)
 		prio |= PCATCH;
 	while (cpipe->pipe_state & PIPE_LOCKFL) {
-		cpipe->pipe_state |= PIPE_LWANT;
+		KASSERT(cpipe->pipe_waiters >= 0,
+		    ("%s: bad waiter count %d", __func__,
+		    cpipe->pipe_waiters));
+		cpipe->pipe_waiters++;
 		error = msleep(cpipe, PIPE_MTX(cpipe),
 		    prio, "pipelk", 0);
+		cpipe->pipe_waiters--;
 		if (error != 0)
 			return (error);
 	}
@@ -642,10 +646,12 @@ pipeunlock(struct pipe *cpipe)
 	PIPE_LOCK_ASSERT(cpipe, MA_OWNED);
 	KASSERT(cpipe->pipe_state & PIPE_LOCKFL,
 		("Unlocked pipe passed to pipeunlock"));
+	KASSERT(cpipe->pipe_waiters >= 0,
+	    ("%s: bad waiter count %d", __func__,
+	    cpipe->pipe_waiters));
 	cpipe->pipe_state &= ~PIPE_LOCKFL;
-	if (cpipe->pipe_state & PIPE_LWANT) {
-		cpipe->pipe_state &= ~PIPE_LWANT;
-		wakeup(cpipe);
+	if (cpipe->pipe_waiters > 0) {
+		wakeup_one(cpipe);
 	}
 }
 

Modified: head/sys/sys/pipe.h
==============================================================================
--- head/sys/sys/pipe.h	Thu Nov 19 19:05:16 2020	(r367851)
+++ head/sys/sys/pipe.h	Thu Nov 19 19:25:47 2020	(r367852)
@@ -116,9 +116,10 @@ struct pipe {
 	struct	pipe *pipe_peer;	/* link with other direction */
 	struct	pipepair *pipe_pair;	/* container structure pointer */
 	u_short	pipe_state;		/* pipe status info */
-	u_short	pipe_type;		/* pipe type info */
+	u_char	pipe_type;		/* pipe type info */
+	u_char	pipe_present;		/* still present? */
+	int	pipe_waiters;		/* pipelock waiters */
 	int	pipe_busy;		/* busy flag, mostly to handle rundown sanely */
-	int	pipe_present;		/* still present? */
 	int	pipe_wgen;		/* writer generation for named pipe */
 	ino_t	pipe_ino;		/* fake inode for stat(2) */
 };


More information about the svn-src-head mailing list