Further clean up sorflush:
- Expose sbrelease_internal(), a variant of sbrelease() with no expectations about the validity of locks in the socket buffer. - Use sbrelease_internel() in sorflush(), and as a result avoid intializing and destroying a socket buffer lock for the temporary stack copy of the actual buffer, asb. - Add a comment indicating why we do what we do, and remove an XXX since things have gotten less ugly in sorflush() lately. This makes socket close cleaner, and possibly also marginally faster. MFC after: 3 weeks
This commit is contained in:
parent
ce24cd825a
commit
f23198af5c
@ -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)
|
||||
{
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user