diff options
| author | ad <ad@NetBSD.org> | 2008-06-10 11:49:11 +0000 |
|---|---|---|
| committer | ad <ad@NetBSD.org> | 2008-06-10 11:49:11 +0000 |
| commit | 06da5288fa91d09558de0c6f640c4f8a2e4fc41b (patch) | |
| tree | d7d70c354355c702f617a83037c06c47dac8114b /sys | |
| parent | 0964f00a455ed65f151b3f9af9c3fed2d7fdbcde (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.c | 21 | ||||
| -rw-r--r-- | sys/kern/uipc_usrreq.c | 10 | ||||
| -rw-r--r-- | sys/sys/socketvar.h | 3 |
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 *); |
