summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorad <ad@NetBSD.org>2008-06-10 11:49:11 +0000
committerad <ad@NetBSD.org>2008-06-10 11:49:11 +0000
commit06da5288fa91d09558de0c6f640c4f8a2e4fc41b (patch)
treed7d70c354355c702f617a83037c06c47dac8114b /sys
parent0964f00a455ed65f151b3f9af9c3fed2d7fdbcde (diff)
There can be existing waiters on a socket's condition variables when we
change socket::so_lock, and they rely on the old lock to synchronize. Wake them up whenever we change so_lock so they can restart their waits.
Diffstat (limited to 'sys')
-rw-r--r--sys/kern/uipc_socket2.c21
-rw-r--r--sys/kern/uipc_usrreq.c10
-rw-r--r--sys/sys/socketvar.h3
3 files changed, 26 insertions, 8 deletions
diff --git a/sys/kern/uipc_socket2.c b/sys/kern/uipc_socket2.c
index 33264b811de..b4a7fc2cab9 100644
--- a/sys/kern/uipc_socket2.c
+++ b/sys/kern/uipc_socket2.c
@@ -1,4 +1,4 @@
-/* $NetBSD: uipc_socket2.c,v 1.94 2008/05/26 17:21:18 ad Exp $ */
+/* $NetBSD: uipc_socket2.c,v 1.95 2008/06/10 11:49:11 ad Exp $ */
/*-
* Copyright (c) 2008 The NetBSD Foundation, Inc.
@@ -58,7 +58,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: uipc_socket2.c,v 1.94 2008/05/26 17:21:18 ad Exp $");
+__KERNEL_RCSID(0, "$NetBSD: uipc_socket2.c,v 1.95 2008/06/10 11:49:11 ad Exp $");
#include "opt_mbuftrace.h"
#include "opt_sb_max.h"
@@ -451,6 +451,23 @@ sowakeup(struct socket *so, struct sockbuf *sb, int code)
}
/*
+ * Reset a socket's lock pointer. Wake all threads waiting on the
+ * socket's condition variables so that they can restart their waits
+ * using the new lock. The existing lock must be held.
+ */
+void
+solockreset(struct socket *so, kmutex_t *lock)
+{
+
+ KASSERT(solocked(so));
+
+ so->so_lock = lock;
+ cv_broadcast(&so->so_snd.sb_cv);
+ cv_broadcast(&so->so_rcv.sb_cv);
+ cv_broadcast(&so->so_cv);
+}
+
+/*
* Socket buffer (struct sockbuf) utility routines.
*
* Each socket contains two socket buffers: one for sending data and
diff --git a/sys/kern/uipc_usrreq.c b/sys/kern/uipc_usrreq.c
index ccdb5dbd51e..e50f93c7594 100644
--- a/sys/kern/uipc_usrreq.c
+++ b/sys/kern/uipc_usrreq.c
@@ -1,4 +1,4 @@
-/* $NetBSD: uipc_usrreq.c,v 1.114 2008/04/28 20:24:05 martin Exp $ */
+/* $NetBSD: uipc_usrreq.c,v 1.115 2008/06/10 11:49:11 ad Exp $ */
/*-
* Copyright (c) 1998, 2000, 2004, 2008 The NetBSD Foundation, Inc.
@@ -96,7 +96,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: uipc_usrreq.c,v 1.114 2008/04/28 20:24:05 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: uipc_usrreq.c,v 1.115 2008/06/10 11:49:11 ad Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -230,8 +230,8 @@ unp_setpeerlocks(struct socket *so, struct socket *so2)
unp->unp_streamlock = NULL;
mutex_obj_hold(lock);
membar_exit();
- so->so_lock = lock;
- so2->so_lock = lock;
+ solockreset(so, lock);
+ solockreset(so2, lock);
}
/*
@@ -254,7 +254,7 @@ unp_resetlock(struct socket *so)
unp->unp_streamlock = olock;
mutex_obj_hold(nlock);
mutex_enter(nlock);
- so->so_lock = nlock;
+ solockreset(so, nlock);
mutex_exit(olock);
}
diff --git a/sys/sys/socketvar.h b/sys/sys/socketvar.h
index 47f1bfad77b..0a1f501fbbe 100644
--- a/sys/sys/socketvar.h
+++ b/sys/sys/socketvar.h
@@ -1,4 +1,4 @@
-/* $NetBSD: socketvar.h,v 1.109 2008/05/26 17:21:18 ad Exp $ */
+/* $NetBSD: socketvar.h,v 1.110 2008/06/10 11:49:11 ad Exp $ */
/*-
* Copyright (c) 2008 The NetBSD Foundation, Inc.
@@ -290,6 +290,7 @@ void sbunlock(struct sockbuf *);
int sowait(struct socket *, int);
void solockretry(struct socket *, kmutex_t *);
void sosetlock(struct socket *);
+void solockreset(struct socket *, kmutex_t *);
int copyout_sockname(struct sockaddr *, unsigned int *, int, struct mbuf *);
int copyout_msg_control(struct lwp *, struct msghdr *, struct mbuf *);