From: tedu Date: Tue, 28 Jun 2016 14:47:00 +0000 (+0000) Subject: introduce rwlock for socketbuf instead of the old flag and tsleep dance. X-Git-Url: http://artulab.com/gitweb/?a=commitdiff_plain;h=7990f0c4de193054c7a1db98f35f0936009632a9;p=openbsd introduce rwlock for socketbuf instead of the old flag and tsleep dance. ok mikeb bluhm --- diff --git a/sys/kern/uipc_socket2.c b/sys/kern/uipc_socket2.c index dc8f23c9b2b..f86e3546b0c 100644 --- a/sys/kern/uipc_socket2.c +++ b/sys/kern/uipc_socket2.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uipc_socket2.c,v 1.63 2015/10/06 14:38:32 claudio Exp $ */ +/* $OpenBSD: uipc_socket2.c,v 1.64 2016/06/28 14:47:00 tedu Exp $ */ /* $NetBSD: uipc_socket2.c,v 1.11 1996/02/04 02:17:55 christos Exp $ */ /* @@ -185,6 +185,9 @@ sonewconn(struct socket *head, int connstatus) so->so_rcv.sb_lowat = head->so_rcv.sb_lowat; so->so_rcv.sb_timeo = head->so_rcv.sb_timeo; + rw_init(&so->so_rcv.sb_lock, "sbsndl"); + rw_init(&so->so_snd.sb_lock, "sbrcvl"); + soqinsque(head, so, soqueue); if ((*so->so_proto->pr_usrreq)(so, PRU_ATTACH, NULL, NULL, NULL, curproc)) { @@ -286,22 +289,26 @@ sbwait(struct sockbuf *sb) * return any error returned from sleep (EINTR). */ int -sb_lock(struct sockbuf *sb) +sblock(struct sockbuf *sb, int wf) { int error; - while (sb->sb_flags & SB_LOCK) { - sb->sb_flags |= SB_WANT; - error = tsleep(&sb->sb_flags, - (sb->sb_flags & SB_NOINTR) ? - PSOCK : PSOCK|PCATCH, "netlck", 0); - if (error) - return (error); - } - sb->sb_flags |= SB_LOCK; - return (0); + error = rw_enter(&sb->sb_lock, RW_WRITE | + (sb->sb_flags & SB_NOINTR ? 0 : RW_INTR) | + (wf == M_WAITOK ? 0 : RW_NOSLEEP)); + + if (error == EBUSY) + error = EWOULDBLOCK; + return (error); } +void +sbunlock(struct sockbuf *sb) +{ + rw_exit(&sb->sb_lock); +} + + /* * Wakeup processes waiting on a socket buffer. * Do asynchronous notification via SIGIO @@ -827,7 +834,7 @@ void sbflush(struct sockbuf *sb) { - KASSERT((sb->sb_flags & SB_LOCK) == 0); + rw_assert_unlocked(&sb->sb_lock); while (sb->sb_mbcnt) sbdrop(sb, (int)sb->sb_cc); diff --git a/sys/sys/socketvar.h b/sys/sys/socketvar.h index bfded719ff6..d0708f362ce 100644 --- a/sys/sys/socketvar.h +++ b/sys/sys/socketvar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: socketvar.h,v 1.60 2016/02/25 07:39:09 semarie Exp $ */ +/* $OpenBSD: socketvar.h,v 1.61 2016/06/28 14:47:00 tedu Exp $ */ /* $NetBSD: socketvar.h,v 1.18 1996/02/09 18:25:38 christos Exp $ */ /*- @@ -35,6 +35,7 @@ #include /* for struct selinfo */ #include #include +#include #ifndef _SOCKLEN_T_DEFINED_ #define _SOCKLEN_T_DEFINED_ @@ -108,13 +109,12 @@ struct socket { struct mbuf *sb_lastrecord;/* first mbuf of last record in socket buffer */ struct selinfo sb_sel; /* process selecting read/write */ + struct rwlock sb_lock; /* exclusive access from process */ int sb_flagsintr; /* flags, changed during interrupt */ short sb_flags; /* flags, see below */ u_short sb_timeo; /* timeout for read/write */ } so_rcv, so_snd; #define SB_MAX (256*1024) /* default for max chars in sockbuf */ -#define SB_LOCK 0x01 /* lock on data queue */ -#define SB_WANT 0x02 /* someone is waiting to lock */ #define SB_WAIT 0x04 /* someone is waiting for data/space */ #define SB_SEL 0x08 /* someone is selecting */ #define SB_ASYNC 0x10 /* ASYNC I/O, need signals */ @@ -218,18 +218,10 @@ struct socket { * Unless SB_NOINTR is set on sockbuf, sleep is interruptible. * Returns error without lock if sleep is interrupted. */ -#define sblock(sb, wf) ((sb)->sb_flags & SB_LOCK ? \ - (((wf) == M_WAITOK) ? sb_lock(sb) : EWOULDBLOCK) : \ - ((sb)->sb_flags |= SB_LOCK, 0)) +int sblock(struct sockbuf *sb, int wf); /* release lock on sockbuf sb */ -#define sbunlock(sb) do { \ - (sb)->sb_flags &= ~SB_LOCK; \ - if ((sb)->sb_flags & SB_WANT) { \ - (sb)->sb_flags &= ~SB_WANT; \ - wakeup((caddr_t)&(sb)->sb_flags); \ - } \ -} while (/* CONSTCOND */ 0) +void sbunlock(struct sockbuf *sb); #define SB_EMPTY_FIXUP(sb) do { \ if ((sb)->sb_mb == NULL) { \