From 721d1b44912f0e82ee8f8e104e43b5f321268de2 Mon Sep 17 00:00:00 2001 From: Matthew Dillon Date: Sat, 14 Sep 2013 02:08:18 -0700 Subject: [PATCH] kernel - Fix issue revealed by new yield code * Make sure the current lwp is released from the scheduler in all cases. There were a few race cases where it would not be released. * Reorder the yield code a little. --- sys/kern/kern_exit.c | 12 ++++++------ sys/kern/usched_dfly.c | 14 ++++++-------- 2 files changed, 12 insertions(+), 14 deletions(-) diff --git a/sys/kern/kern_exit.c b/sys/kern/kern_exit.c index bd9d7c6efc..cd1b48be1d 100644 --- a/sys/kern/kern_exit.c +++ b/sys/kern/kern_exit.c @@ -556,12 +556,6 @@ exit1(int rv) */ plimit_free(p); - /* - * Release the current user process designation on the process so - * the userland scheduler can work in someone else. - */ - p->p_usched->release_curproc(lp); - /* * Finally, call machine-dependent code to release as many of the * lwp's resources as we can and halt execution of this thread. @@ -582,6 +576,12 @@ lwp_exit(int masterexit) struct proc *p = lp->lwp_proc; int dowake = 0; + /* + * Release the current user process designation on the process so + * the userland scheduler can work in someone else. + */ + p->p_usched->release_curproc(lp); + /* * lwp_exit() may be called without setting LWP_MP_WEXIT, so * make sure it is set here. diff --git a/sys/kern/usched_dfly.c b/sys/kern/usched_dfly.c index e917fcf513..d09105252d 100644 --- a/sys/kern/usched_dfly.c +++ b/sys/kern/usched_dfly.c @@ -384,9 +384,6 @@ dfly_acquire_curproc(struct lwp *lp) if (lp->lwp_thread->td_mpflags & TDF_MP_DIDYIELD) { u_int32_t tsqbits; - atomic_clear_int(&lp->lwp_thread->td_mpflags, - TDF_MP_DIDYIELD); - switch(lp->lwp_rqtype) { case RTP_PRIO_NORMAL: tsqbits = dd->queuebits; @@ -402,6 +399,8 @@ dfly_acquire_curproc(struct lwp *lp) } lwkt_deschedule(lp->lwp_thread); dfly_setrunqueue_dd(dd, lp); + atomic_clear_int(&lp->lwp_thread->td_mpflags, + TDF_MP_DIDYIELD); lwkt_switch(); gd = mycpu; dd = &dfly_pcpu[gd->gd_cpuid]; @@ -721,15 +720,14 @@ dfly_setrunqueue_dd(dfly_pcpu_t rdd, struct lwp *lp) } else if (rgd == mycpu) { /* * We should interrupt the currently running thread, which - * is on the current cpu. + * is on the current cpu. However, if DIDYIELD is set we + * round-robin unconditionally and do not interrupt it. */ spin_unlock(&rdd->spin); - if (rdd->uschedcp == NULL) { + if (rdd->uschedcp == NULL) wakeup_mycpu(&rdd->helper_thread); /* XXX */ + if ((lp->lwp_thread->td_mpflags & TDF_MP_DIDYIELD) == 0) need_user_resched(); - } else { - need_user_resched(); - } } else { /* * We should interrupt the currently running thread, which -- 2.41.0