diff options
author | Robert Watson <rwatson@FreeBSD.org> | 2004-08-25 21:24:36 +0000 |
---|---|---|
committer | Robert Watson <rwatson@FreeBSD.org> | 2004-08-25 21:24:36 +0000 |
commit | 161a0c7cff3b3c52f98c46200e915f97d56c45d8 (patch) | |
tree | 46e531de34c3949576a76f8cd43a290672d5b80b /sys/kern/uipc_usrreq.c | |
parent | b0e7e61135e767b0cadee9f7cba4c91d0963d407 (diff) | |
download | src-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.c | 23 |
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 |