diff options
-rw-r--r-- | sys/kern/uipc_sockbuf.c | 3 | ||||
-rw-r--r-- | sys/kern/uipc_socket.c | 24 | ||||
-rw-r--r-- | sys/sys/socketvar.h | 1 |
3 files changed, 14 insertions, 14 deletions
diff --git a/sys/kern/uipc_sockbuf.c b/sys/kern/uipc_sockbuf.c index 16923cf..9e89826 100644 --- a/sys/kern/uipc_sockbuf.c +++ b/sys/kern/uipc_sockbuf.c @@ -67,7 +67,6 @@ static u_long sb_efficiency = 8; /* parameter for sbreserve() */ static void sbdrop_internal(struct sockbuf *sb, int len); static void sbflush_internal(struct sockbuf *sb); -static void sbrelease_internal(struct sockbuf *sb, struct socket *so); /* * Socantsendmore indicates that no more data will be sent on the socket; it @@ -322,7 +321,7 @@ sbreserve(struct sockbuf *sb, u_long cc, struct socket *so, /* * Free mbufs held by a socket, and reserved mbuf space. */ -static void +void sbrelease_internal(struct sockbuf *sb, struct socket *so) { diff --git a/sys/kern/uipc_socket.c b/sys/kern/uipc_socket.c index 0de6d29..bbb4f89 100644 --- a/sys/kern/uipc_socket.c +++ b/sys/kern/uipc_socket.c @@ -1877,15 +1877,13 @@ sorflush(struct socket *so) struct sockbuf asb; /* - * XXXRW: This is quite ugly. Previously, this code made a copy of - * the socket buffer, then zero'd the original to clear the buffer - * fields. However, with mutexes in the socket buffer, this causes - * problems. We only clear the zeroable bits of the original; - * however, we have to initialize and destroy the mutex in the copy - * so that dom_dispose() and sbrelease() can lock t as needed. - */ - - /* + * In order to avoid calling dom_dispose with the socket buffer mutex + * held, and in order to generally avoid holding the lock for a long + * time, we make a copy of the socket buffer and clear the original + * (except locks, state). The new socket buffer copy won't have + * initialized locks so we can only call routines that won't use or + * assert those locks. + * * Dislodge threads currently blocked in receive and wait to acquire * a lock against other simultaneous readers before clearing the * socket buffer. Don't let our acquire be interrupted by a signal @@ -1907,11 +1905,13 @@ sorflush(struct socket *so) SOCKBUF_UNLOCK(sb); sbunlock(sb); - SOCKBUF_LOCK_INIT(&asb, "so_rcv"); + /* + * Dispose of special rights and flush the socket buffer. Don't call + * any unsafe routines (that rely on locks being initialized) on asb. + */ if (pr->pr_flags & PR_RIGHTS && pr->pr_domain->dom_dispose != NULL) (*pr->pr_domain->dom_dispose)(asb.sb_mb); - sbrelease(&asb, so); - SOCKBUF_LOCK_DESTROY(&asb); + sbrelease_internal(&asb, so); } /* diff --git a/sys/sys/socketvar.h b/sys/sys/socketvar.h index 09e58ab..40f3dd9 100644 --- a/sys/sys/socketvar.h +++ b/sys/sys/socketvar.h @@ -483,6 +483,7 @@ void sbdroprecord_locked(struct sockbuf *sb); void sbflush(struct sockbuf *sb); void sbflush_locked(struct sockbuf *sb); void sbrelease(struct sockbuf *sb, struct socket *so); +void sbrelease_internal(struct sockbuf *sb, struct socket *so); void sbrelease_locked(struct sockbuf *sb, struct socket *so); int sbreserve(struct sockbuf *sb, u_long cc, struct socket *so, struct thread *td); |