aboutsummaryrefslogtreecommitdiff
path: root/sys/kern/uipc_usrreq.c
diff options
context:
space:
mode:
authorRobert Watson <rwatson@FreeBSD.org>2004-08-25 21:24:36 +0000
committerRobert Watson <rwatson@FreeBSD.org>2004-08-25 21:24:36 +0000
commit161a0c7cff3b3c52f98c46200e915f97d56c45d8 (patch)
tree46e531de34c3949576a76f8cd43a290672d5b80b /sys/kern/uipc_usrreq.c
parentb0e7e61135e767b0cadee9f7cba4c91d0963d407 (diff)
downloadsrc-161a0c7cff3b3c52f98c46200e915f97d56c45d8.tar.gz
src-161a0c7cff3b3c52f98c46200e915f97d56c45d8.zip
Don't hold the UNIX domain socket subsystem lock over the body of the
UNIX domain socket garbage collection implementation, as that risks holding the mutex over potentially sleeping operations (as well as introducing some nasty lock order issues, etc). unp_gc() will hold the lock long enough to do necessary deferal checks and set that it's running, but then release it until it needs to reset the gc state. RELENG_5 candidate. Discussed with: alfred
Notes
Notes: svn path=/head/; revision=134310
Diffstat (limited to 'sys/kern/uipc_usrreq.c')
-rw-r--r--sys/kern/uipc_usrreq.c23
1 files changed, 15 insertions, 8 deletions
diff --git a/sys/kern/uipc_usrreq.c b/sys/kern/uipc_usrreq.c
index 9f41320773e9..07cdbc7a9f7a 100644
--- a/sys/kern/uipc_usrreq.c
+++ b/sys/kern/uipc_usrreq.c
@@ -737,9 +737,10 @@ unp_detach(unp)
* gets them (resulting in a "panic: closef: count < 0").
*/
sorflush(unp->unp_socket);
- unp_gc();
- }
- UNP_UNLOCK();
+ unp_gc(); /* Will unlock UNP. */
+ } else
+ UNP_UNLOCK();
+ UNP_UNLOCK_ASSERT();
if (unp->unp_addr != NULL)
FREE(unp->unp_addr, M_SONAME);
uma_zfree(unp_zone, unp);
@@ -1491,6 +1492,11 @@ out:
return (error);
}
+/*
+ * unp_defer is thread-local during garbage collection, and does not require
+ * explicit synchronization. unp_gcing prevents other threads from entering
+ * garbage collection, and perhaps should be an sx lock instead.
+ */
static int unp_defer, unp_gcing;
static void
@@ -1505,18 +1511,17 @@ unp_gc()
UNP_LOCK_ASSERT();
- if (unp_gcing)
+ if (unp_gcing) {
+ UNP_UNLOCK();
return;
+ }
unp_gcing = 1;
unp_defer = 0;
+ UNP_UNLOCK();
/*
* before going through all this, set all FDs to
* be NOT defered and NOT externally accessible
*/
- /*
- * XXXRW: Acquiring a sleep lock while holding UNP
- * mutex cannot be a good thing.
- */
sx_slock(&filelist_lock);
LIST_FOREACH(fp, &filehead, f_list)
fp->f_gcflag &= ~(FMARK|FDEFER);
@@ -1698,6 +1703,8 @@ again:
closef(*fpp, (struct thread *) NULL);
free(extra_ref, M_TEMP);
unp_gcing = 0;
+
+ UNP_UNLOCK_ASSERT();
}
void