svn commit: r313814 - head/sys/kern

Cy Schubert Cy.Schubert at komquats.com
Thu Feb 16 20:44:43 UTC 2017


No prob. Thanks.


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


In message <CAFMmRNyuLTZ54TskavnJkssKwN94M-Sfb2VdGqj-2Zgs9tc=2g at mail.gmail.c
om>
, Ryan Stone writes:
> --001a113fd05697fd560548abc53e
> Content-Type: text/plain; charset=UTF-8
> 
> 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