-/* $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 $ */
/*
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)) {
* 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
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);
-/* $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 $ */
/*-
#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_
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 */
* 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) { \