summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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 9f41320..07cdbc7 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
OpenPOWER on IntegriCloud