summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authortedu <tedu@openbsd.org>2016-06-28 14:47:00 +0000
committertedu <tedu@openbsd.org>2016-06-28 14:47:00 +0000
commit7990f0c4de193054c7a1db98f35f0936009632a9 (patch)
tree2928e5a5dcd96db490a3870f090e987558c1a7d3
parentIPV6_MINHOPCOUNT now supports UDP (unicast and multicast) (diff)
downloadwireguard-openbsd-7990f0c4de193054c7a1db98f35f0936009632a9.tar.xz
wireguard-openbsd-7990f0c4de193054c7a1db98f35f0936009632a9.zip
introduce rwlock for socketbuf instead of the old flag and tsleep dance.
ok mikeb bluhm
-rw-r--r--sys/kern/uipc_socket2.c33
-rw-r--r--sys/sys/socketvar.h18
2 files changed, 25 insertions, 26 deletions
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 <sys/selinfo.h> /* for struct selinfo */
#include <sys/queue.h>
#include <sys/timeout.h>
+#include <sys/rwlock.h>
#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) { \