From owner-freebsd-net@FreeBSD.ORG Tue Sep 30 18:01:02 2014 Return-Path: Delivered-To: net@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id BFBFBBD1; Tue, 30 Sep 2014 18:01:02 +0000 (UTC) Received: from bigwig.baldwin.cx (bigwig.baldwin.cx [IPv6:2001:470:1f11:75::1]) (using TLSv1 with cipher DHE-RSA-CAMELLIA256-SHA (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 9B5981DD; Tue, 30 Sep 2014 18:01:02 +0000 (UTC) Received: from jhbbsd.localnet (unknown [209.249.190.124]) by bigwig.baldwin.cx (Postfix) with ESMTPSA id 5622EB9CF; Tue, 30 Sep 2014 14:01:01 -0400 (EDT) From: John Baldwin To: net@freebsd.org Subject: [PATCH] Only lock send buffer in sopoll() if needed Date: Tue, 30 Sep 2014 14:00:09 -0400 User-Agent: KMail/1.13.5 (FreeBSD/8.4-CBSD-20140415; KDE/4.5.5; amd64; ; ) MIME-Version: 1.0 Content-Type: Text/Plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Message-Id: <201409301400.09999.jhb@freebsd.org> X-Greylist: Sender succeeded SMTP AUTH, not delayed by milter-greylist-4.2.7 (bigwig.baldwin.cx); Tue, 30 Sep 2014 14:01:01 -0400 (EDT) Cc: Robert Watson X-BeenThere: freebsd-net@freebsd.org X-Mailman-Version: 2.1.18-1 Precedence: list List-Id: Networking and TCP/IP with FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 30 Sep 2014 18:01:02 -0000 Right now sopoll() always locks both socket buffers. The receive socket buffer lock is always needed, but the send socket buffer lock is only needed while polling for writing (there is a potential test of SBS_CANTSENDMORE without the lock, but I think this might be ok). What do folks think? Index: uipc_socket.c =================================================================== --- uipc_socket.c (revision 272305) +++ uipc_socket.c (working copy) @@ -3003,7 +3003,12 @@ sopoll_generic(struct socket *so, int events, stru { int revents = 0; - SOCKBUF_LOCK(&so->so_snd); + if (events & (POLLOUT | POLLWRNORM)) + SOCKBUF_LOCK(&so->so_snd); + /* + * The so_rcv lock doubles as SOCK_LOCK so it it is needed for + * all requests. + */ SOCKBUF_LOCK(&so->so_rcv); if (events & (POLLIN | POLLRDNORM)) if (soreadabledata(so)) @@ -3038,7 +3043,8 @@ sopoll_generic(struct socket *so, int events, stru } SOCKBUF_UNLOCK(&so->so_rcv); - SOCKBUF_UNLOCK(&so->so_snd); + if (events & (POLLOUT | POLLWRNORM)) + SOCKBUF_UNLOCK(&so->so_snd); return (revents); } -- John Baldwin