svn commit: r313814 - head/sys/kern

Ryan Stone rysto32 at gmail.com
Thu Feb 16 20:37:56 UTC 2017


Sorry about that.  It's fixed in r313816.

On Thu, Feb 16, 2017 at 3:31 PM, Cy Schubert <Cy.Schubert at komquats.com>
wrote:

> In message <201702161941.v1GJfDoP087457 at repo.freebsd.org>, Ryan Stone
> writes:
> > Author: rstone
> > Date: Thu Feb 16 19:41:13 2017
> > New Revision: 313814
> > URL: https://svnweb.freebsd.org/changeset/base/313814
> >
> > Log:
> >   Check for preemption after lowering a thread's priority
> >
> >   When a high-priority thread is waiting for a mutex held by a
> >   low-priority thread, it temporarily lends its priority to the
> >   low-priority thread to prevent priority inversion.  When the mutex
> >   is released, the lent priority is revoked and the low-priority
> >   thread goes back to its original priority.
> >
> >   When the priority of that thread is lowered (through a call to
> >   sched_priority()), the schedule was not checking whether
> >   there is now a high-priority thread in the run queue.  This can
> >   cause threads with real-time priority to be starved in the run
> >   queue while the low-priority thread finishes its quantum.
> >
> >   Fix this by explicitly checking whether preemption is necessary
> >   when a thread's priority is lowered.
> >
> >   Sponsored by: Dell EMC Isilon
> >   Obtained from: Sandvine Inc
> >   Differential Revision:      https://reviews.freebsd.org/D9518
> >   Reviewed by: Jeff Roberson (ule)
> >   MFC after: 1 month
> >
> > Modified:
> >   head/sys/kern/sched_4bsd.c
> >   head/sys/kern/sched_ule.c
> >
> > Modified: head/sys/kern/sched_4bsd.c
> > ============================================================
> =================
> > =
> > --- head/sys/kern/sched_4bsd.c        Thu Feb 16 19:00:09 2017
> (r31381
> > 3)
> > +++ head/sys/kern/sched_4bsd.c        Thu Feb 16 19:41:13 2017
> (r31381
> > 4)
> > @@ -816,7 +816,12 @@ sched_class(struct thread *td, int class
> >  static void
> >  sched_priority(struct thread *td, u_char prio)
> >  {
> > -
> > +     struct thread *newtd;
> > +     struct runq *rq;
> > +     u_char orig_pri;
> > +#ifdef SMP
> > +     struct thread *cputd;
> > +#endif
> >
> >       KTR_POINT3(KTR_SCHED, "thread", sched_tdname(td), "priority
> change",
> >           "prio:%d", td->td_priority, "new prio:%d", prio,
> KTR_ATTR_LINKED,
> > @@ -832,10 +837,43 @@ sched_priority(struct thread *td, u_char
> >       THREAD_LOCK_ASSERT(td, MA_OWNED);
> >       if (td->td_priority == prio)
> >               return;
> > +     orig_pri = td->td_priority;
> >       td->td_priority = prio;
> >       if (TD_ON_RUNQ(td) && td->td_rqindex != (prio / RQ_PPQ)) {
> >               sched_rem(td);
> >               sched_add(td, SRQ_BORING);
> > +     } else if (orig_pri < prio && TD_IS_RUNNING(td)) {
> > +             /*
> > +              * If we have decreased the priority of a running thread,
> we
> > +              * have to check if it should be preempted.
> > +              */
> > +             rq = &runq;
> > +             newtd = runq_choose(&runq);
> > +#ifdef SMP
> > +             cputd = runq_choose(&runq_pcpu[td->td_oncpu]);
> > +             if (newtd == NULL ||
> > +                 (cputd != NULL && cputd->td_priority <
> td->td_priority))
> > +                     newtd = cputd;
> > +#endif
> > +
> > +             if (newtd != NULL && newtd->td_priority < prio
> > +#ifndef FULL_PREEMPTION
> > +                 && (newtd->td_priority <= PRI_MAX_ITHD ||
> > +                     prio >= PRI_MIN_IDLE))
> > +#endif
> > +             ) {
> > +                     if (td == curthread)
> > +                             /*
> > +                              * Don't reschedule the thread here as it
> may
> > +                              * be losing priority because it has
> released a
> > +                              * mutex, and in that case we need it to
> finish
> > +                              * releasing the lock before it gets
> preempted.
> > +                              */
> > +                             td->td_owepreempt = 1;
> > +                     else
> > +                             kick_other_cpu(newtd->td_priority,
> > +                                 td->td_oncpu);
> > +             }
> >       }
> >  }
> >
> >
> > Modified: head/sys/kern/sched_ule.c
> > ============================================================
> =================
> > =
> > --- head/sys/kern/sched_ule.c Thu Feb 16 19:00:09 2017        (r313813)
> > +++ head/sys/kern/sched_ule.c Thu Feb 16 19:41:13 2017        (r313814)
> > @@ -319,7 +319,7 @@ static void tdq_add(struct tdq *, struct
> >  #ifdef SMP
> >  static int tdq_move(struct tdq *, struct tdq *);
> >  static int tdq_idled(struct tdq *);
> > -static void tdq_notify(struct tdq *, struct thread *);
> > +static void tdq_notify(struct tdq *, int);
> >  static struct thread *tdq_steal(struct tdq *, int);
> >  static struct thread *runq_steal(struct runq *, int);
> >  static int sched_pickcpu(struct thread *, int);
> > @@ -1040,16 +1040,14 @@ tdq_idled(struct tdq *tdq)
> >   * Notify a remote cpu of new work.  Sends an IPI if criteria are met.
> >   */
> >  static void
> > -tdq_notify(struct tdq *tdq, struct thread *td)
> > +tdq_notify(struct tdq *tdq, int pri)
> >  {
> >       struct thread *ctd;
> > -     int pri;
> >       int cpu;
> >
> >       if (tdq->tdq_ipipending)
> >               return;
> > -     cpu = td_get_sched(td)->ts_cpu;
> > -     pri = td->td_priority;
> > +     cpu = TD_ID(tdq);
>
> Just my luck. The day I svn up and rebuild.
>
> --- sched_ule.o ---
> /opt/src/svn-current/sys/kern/sched_ule.c:1050:8: error: implicit
> declaration of function 'TD_ID' is invalid in C99
> [-Werror,-Wimplicit-functi
> on-declaration]
>         cpu = TD_ID(tdq);
>               ^
> --
> Cheers,
> Cy Schubert <Cy.Schubert at cschubert.com>
> FreeBSD UNIX:  <cy at FreeBSD.org>   Web:  http://www.FreeBSD.org
>
>         The need of the many outweighs the greed of the few.
>
>
> >       ctd = pcpu_find(cpu)->pc_curthread;
> >       if (!sched_shouldpreempt(pri, ctd->td_priority, 1))
> >               return;
> > @@ -1675,6 +1673,22 @@ sched_pctcpu_update(struct td_sched *ts,
> >       ts->ts_ltick = t;
> >  }
> >
> > +static void
> > +sched_check_preempt(struct tdq *tdq, struct thread *td)
> > +{
> > +
> > +     KASSERT(TD_IS_RUNNING(td), ("thread is not running"));
> > +     TDQ_LOCK_ASSERT(tdq, MA_OWNED);
> > +     KASSERT(tdq == TDQ_CPU(td->td_sched->ts_cpu),
> > +         ("tdq does not contain td"));
> > +
> > +     if (tdq == TDQ_SELF()) {
> > +             if (sched_shouldpreempt(tdq->tdq_lowpri, td->td_priority,
> 0))
> > +                     td->td_owepreempt = 1;
> > +     } else
> > +             tdq_notify(tdq, tdq->tdq_lowpri);
> > +}
> > +
> >  /*
> >   * Adjust the priority of a thread.  Move it to the appropriate
> run-queue
> >   * if necessary.  This is the back-end for several priority related
> > @@ -1726,6 +1740,9 @@ sched_thread_priority(struct thread *td,
> >                       tdq->tdq_lowpri = prio;
> >               else if (tdq->tdq_lowpri == oldpri)
> >                       tdq_setlowpri(tdq, td);
> > +
> > +             if (oldpri < prio)
> > +                     sched_check_preempt(tdq, td);
> >               return;
> >       }
> >       td->td_priority = prio;
> > @@ -1854,7 +1871,7 @@ sched_switch_migrate(struct tdq *tdq, st
> >        */
> >       tdq_lock_pair(tdn, tdq);
> >       tdq_add(tdn, td, flags);
> > -     tdq_notify(tdn, td);
> > +     tdq_notify(tdn, td->td_priority);
> >       TDQ_UNLOCK(tdn);
> >       spinlock_exit();
> >  #endif
> > @@ -2429,7 +2446,7 @@ sched_add(struct thread *td, int flags)
> >       tdq = sched_setcpu(td, cpu, flags);
> >       tdq_add(tdq, td, flags);
> >       if (cpu != PCPU_GET(cpuid)) {
> > -             tdq_notify(tdq, td);
> > +             tdq_notify(tdq, td->td_priority);
> >               return;
> >       }
> >  #else
> >
> >
>
>
>


More information about the svn-src-all mailing list