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
This commit is contained in:
Robert Watson 2004-08-25 21:24:36 +00:00
parent b0e7e61135
commit 161a0c7cff

View File

@ -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