Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F151515511
D8668.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
5 KB
Referenced Files
None
Subscribers
None
D8668.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D8668: allow selwakeup to be called from interrupt filter context.
Attached
Detach File
Event Timeline
Log In to Comment