Page MenuHomeFreeBSD

D8668.diff
No OneTemporary

D8668.diff

Index: sys/kern/sys_generic.c
===================================================================
--- sys/kern/sys_generic.c
+++ sys/kern/sys_generic.c
@@ -160,6 +160,8 @@
static uma_zone_t selfd_zone;
static struct mtx_pool *mtxpool_select;
+static struct mtx seldeferred_mtx;
+static struct selfdlist global_deferred;
#ifdef __LP64__
size_t
@@ -1688,12 +1690,12 @@
{
STAILQ_REMOVE(&stp->st_selq, sfp, selfd, sf_link);
if (sfp->sf_si != NULL) {
- mtx_lock(sfp->sf_mtx);
+ mtx_lock_spin(sfp->sf_mtx);
if (sfp->sf_si != NULL) {
TAILQ_REMOVE(&sfp->sf_si->si_tdlist, sfp, sf_threads);
refcount_release(&sfp->sf_refs);
}
- mtx_unlock(sfp->sf_mtx);
+ mtx_unlock_spin(sfp->sf_mtx);
}
if (refcount_release(&sfp->sf_refs))
uma_zfree(selfd_zone, sfp);
@@ -1701,8 +1703,7 @@
/* Drain the waiters tied to all the selfd belonging the specified selinfo. */
void
-seldrain(sip)
- struct selinfo *sip;
+seldrain(struct selinfo *sip)
{
/*
@@ -1720,13 +1721,12 @@
* Record a select request.
*/
void
-selrecord(selector, sip)
- struct thread *selector;
- struct selinfo *sip;
+selrecord(struct thread *selector, struct selinfo *sip)
{
struct selfd *sfp;
struct seltd *stp;
struct mtx *mtxp;
+ struct selfdlist trash;
stp = selector->td_sel;
/*
@@ -1734,6 +1734,7 @@
*/
if (stp->st_flags & SELTD_RESCAN)
return;
+
/*
* Grab one of the preallocated descriptors.
*/
@@ -1757,7 +1758,7 @@
/*
* Now that we've locked the sip, check for initialization.
*/
- mtx_lock(mtxp);
+ mtx_lock_spin(mtxp);
if (sip->si_mtx == NULL) {
sip->si_mtx = mtxp;
TAILQ_INIT(&sip->si_tdlist);
@@ -1766,22 +1767,30 @@
* Add this thread to the list of selfds listening on this selinfo.
*/
TAILQ_INSERT_TAIL(&sip->si_tdlist, sfp, sf_threads);
- mtx_unlock(sip->si_mtx);
+ mtx_unlock_spin(sip->si_mtx);
+
+ if (!TAILQ_EMPTY(&global_deferred)) {
+ TAILQ_INIT(&trash);
+ mtx_lock_spin(&seldeferred_mtx);
+ TAILQ_CONCAT(&trash, &global_deferred, sf_threads);
+ mtx_unlock_spin(&seldeferred_mtx);
+ while ((sfp = TAILQ_FIRST(&trash)) != NULL) {
+ TAILQ_REMOVE(&trash, sfp, sf_threads);
+ uma_zfree(selfd_zone, sfp);
+ }
+ }
}
/* Wake up a selecting thread. */
void
-selwakeup(sip)
- struct selinfo *sip;
+selwakeup(struct selinfo *sip)
{
doselwakeup(sip, -1);
}
/* Wake up a selecting thread, and set its priority. */
void
-selwakeuppri(sip, pri)
- struct selinfo *sip;
- int pri;
+selwakeuppri(struct selinfo *sip, int pri)
{
doselwakeup(sip, pri);
}
@@ -1790,21 +1799,23 @@
* Do a wakeup when a selectable event occurs.
*/
static void
-doselwakeup(sip, pri)
- struct selinfo *sip;
- int pri;
+doselwakeup(struct selinfo *sip, int pri)
{
struct selfd *sfp;
struct selfd *sfn;
struct seltd *stp;
+ struct thread *td;
+ struct selfdlist trash;
/* If it's not initialized there can't be any waiters. */
if (sip->si_mtx == NULL)
return;
+ TAILQ_INIT(&trash);
+ td = curthread;
/*
* Locking the selinfo locks all selfds associated with it.
*/
- mtx_lock(sip->si_mtx);
+ mtx_lock_spin(sip->si_mtx);
TAILQ_FOREACH_SAFE(sfp, &sip->si_tdlist, sf_threads, sfn) {
/*
* Once we remove this sfp from the list and clear the
@@ -1813,14 +1824,24 @@
TAILQ_REMOVE(&sip->si_tdlist, sfp, sf_threads);
sfp->sf_si = NULL;
stp = sfp->sf_td;
- mtx_lock(&stp->st_mtx);
+ mtx_lock_spin(&stp->st_mtx);
stp->st_flags |= SELTD_PENDING;
cv_broadcastpri(&stp->st_wait, pri);
- mtx_unlock(&stp->st_mtx);
+ mtx_unlock_spin(&stp->st_mtx);
if (refcount_release(&sfp->sf_refs))
- uma_zfree(selfd_zone, sfp);
+ TAILQ_INSERT_HEAD(&trash, sfp, sf_threads);
+ }
+ mtx_unlock_spin(sip->si_mtx);
+ if (td->td_critnest || td->td_intr_nesting_level) {
+ mtx_lock_spin(&seldeferred_mtx);
+ TAILQ_CONCAT(&global_deferred, &trash, sf_threads);
+ mtx_unlock_spin(&seldeferred_mtx);
+ return;
+ }
+ while ((sfp = TAILQ_FIRST(&trash)) != NULL) {
+ TAILQ_REMOVE(&trash, sfp, sf_threads);
+ uma_zfree(selfd_zone, sfp);
}
- mtx_unlock(sip->si_mtx);
}
static void
@@ -1831,7 +1852,7 @@
if ((stp = td->td_sel) != NULL)
goto out;
td->td_sel = stp = malloc(sizeof(*stp), M_SELECT, M_WAITOK|M_ZERO);
- mtx_init(&stp->st_mtx, "sellck", NULL, MTX_DEF);
+ mtx_init(&stp->st_mtx, "sellck", NULL, MTX_SPIN);
cv_init(&stp->st_wait, "select");
out:
stp->st_flags = 0;
@@ -1849,13 +1870,13 @@
* An event of interest may occur while we do not hold the seltd
* locked so check the pending flag before we sleep.
*/
- mtx_lock(&stp->st_mtx);
+ mtx_lock_spin(&stp->st_mtx);
/*
* Any further calls to selrecord will be a rescan.
*/
stp->st_flags |= SELTD_RESCAN;
if (stp->st_flags & SELTD_PENDING) {
- mtx_unlock(&stp->st_mtx);
+ mtx_unlock_spin(&stp->st_mtx);
return (0);
}
if (sbt == 0)
@@ -1865,7 +1886,7 @@
sbt, precision, C_ABSOLUTE);
else
error = cv_wait_sig(&stp->st_wait, &stp->st_mtx);
- mtx_unlock(&stp->st_mtx);
+ mtx_unlock_spin(&stp->st_mtx);
return (error);
}
@@ -1911,7 +1932,9 @@
selfd_zone = uma_zcreate("selfd", sizeof(struct selfd), NULL, NULL,
NULL, NULL, UMA_ALIGN_PTR, 0);
- mtxpool_select = mtx_pool_create("select mtxpool", 128, MTX_DEF);
+ mtxpool_select = mtx_pool_create("select mtxpool", 128, MTX_SPIN);
+ TAILQ_INIT(&global_deferred);
+ mtx_init(&seldeferred_mtx, "seltrash", NULL, MTX_SPIN);
}
/*

File Metadata

Mime Type
text/plain
Expires
Thu, Apr 9, 11:18 PM (11 h, 39 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
31160197
Default Alt Text
D8668.diff (5 KB)

Event Timeline