sched: define TIF_ALLOW_RESCHED

BugLink: https://bugs.launchpad.net/bugs/2060704

On Fri, Sep 22 2023 at 00:55, Thomas Gleixner wrote:
> On Thu, Sep 21 2023 at 09:00, Linus Torvalds wrote:
>> That said - I think as a proof of concept and "look, with this we get
>> the expected scheduling event counts", that patch is perfect. I think
>> you more than proved the concept.
>
> There is certainly quite some analyis work to do to make this a one to
> one replacement.
>
> With a handful of benchmarks the PoC (tweaked with some obvious fixes)
> is pretty much on par with the current mainline variants (NONE/FULL),
> but the memtier benchmark makes a massive dent.
>
> It sports a whopping 10% regression with the LAZY mode versus the mainline
> NONE model. Non-LAZY and FULL behave unsurprisingly in the same way.
>
> That benchmark is really sensitive to the preemption model. With current
> mainline (DYNAMIC_PREEMPT enabled) the preempt=FULL model has ~20%
> performance drop versus preempt=NONE.

That 20% was a tired pilot error. The real number is in the 5% ballpark.

> I have no clue what's going on there yet, but that shows that there is
> obviously quite some work ahead to get this sorted.

It took some head scratching to figure that out. The initial fix broke
the handling of the hog issue, i.e. the problem that Ankur tried to
solve, but I hacked up a "solution" for that too.

With that the memtier benchmark is roughly back to the mainline numbers,
but my throughput benchmark know how is pretty close to zero, so that
should be looked at by people who actually understand these things.

Likewise the hog prevention is just at the PoC level and clearly beyond
my knowledge of scheduler details: It unconditionally forces a
reschedule when the looping task is not responding to a lazy reschedule
request before the next tick. IOW it forces a reschedule on the second
tick, which is obviously different from the cond_resched()/might_sleep()
behaviour.

The changes vs. the original PoC aside of the bug and thinko fixes:

    1) A hack to utilize the TRACE_FLAG_IRQS_NOSUPPORT flag to trace the
       lazy preempt bit as the trace_entry::flags field is full already.

       That obviously breaks the tracer ABI, but if we go there then
       this needs to be fixed. Steven?

    2) debugfs file to validate that loops can be force preempted w/o
       cond_resched()

       The usage is:

       # taskset -c 1 bash
       # echo 1 > /sys/kernel/debug/sched/hog &
       # echo 1 > /sys/kernel/debug/sched/hog &
       # echo 1 > /sys/kernel/debug/sched/hog &

       top shows ~33% CPU for each of the hogs and tracing confirms that
       the crude hack in the scheduler tick works:

            bash-4559    [001] dlh2.  2253.331202: resched_curr <-__update_curr
            bash-4560    [001] dlh2.  2253.340199: resched_curr <-__update_curr
            bash-4561    [001] dlh2.  2253.346199: resched_curr <-__update_curr
            bash-4559    [001] dlh2.  2253.353199: resched_curr <-__update_curr
            bash-4561    [001] dlh2.  2253.358199: resched_curr <-__update_curr
            bash-4560    [001] dlh2.  2253.370202: resched_curr <-__update_curr
            bash-4559    [001] dlh2.  2253.378198: resched_curr <-__update_curr
            bash-4561    [001] dlh2.  2253.389199: resched_curr <-__update_curr

       The 'l' instead of the usual 'N' reflects that the lazy resched
       bit is set. That makes __update_curr() invoke resched_curr()
       instead of the lazy variant. resched_curr() sets TIF_NEED_RESCHED
       and folds it into preempt_count so that preemption happens at the
       next possible point, i.e. either in return from interrupt or at
       the next preempt_enable().

That's as much as I wanted to demonstrate and I'm not going to spend
more cycles on it as I have already too many other things on flight and
the resulting scheduler woes are clearly outside of my expertice.

Though definitely I'm putting a permanent NAK in place for any attempts
to duct tape the preempt=NONE model any further by sprinkling more
cond*() and whatever warts around.

Thanks,

        tglx

[tglx: s@CONFIG_PREEMPT_AUTO@CONFIG_PREEMPT_BUILD_AUTO@ ]

Link: https://lore.kernel.org/all/87jzshhexi.ffs@tglx/
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Kevin Becker <kevin.becker@canonical.com>
This commit is contained in:
Thomas Gleixner
2023-09-23 03:11:05 +02:00
committed by Kevin Becker
parent 8a1542f50f
commit 5eede802d4
20 changed files with 171 additions and 56 deletions
+2
View File
@@ -2736,6 +2736,8 @@ unsigned int tracing_gen_ctx_irq_test(unsigned int irqs_status)
if (tif_need_resched())
trace_flags |= TRACE_FLAG_NEED_RESCHED;
if (tif_need_resched_lazy())
trace_flags |= TRACE_FLAG_NEED_RESCHED_LAZY;
if (test_preempt_need_resched())
trace_flags |= TRACE_FLAG_PREEMPT_RESCHED;
return (trace_flags << 16) | (min_t(unsigned int, pc & 0xff, 0xf)) |
+14 -2
View File
@@ -464,17 +464,29 @@ int trace_print_lat_fmt(struct trace_seq *s, struct trace_entry *entry)
(entry->flags & TRACE_FLAG_IRQS_OFF && bh_off) ? 'D' :
(entry->flags & TRACE_FLAG_IRQS_OFF) ? 'd' :
bh_off ? 'b' :
(entry->flags & TRACE_FLAG_IRQS_NOSUPPORT) ? 'X' :
!IS_ENABLED(CONFIG_TRACE_IRQFLAGS_SUPPORT) ? 'X' :
'.';
switch (entry->flags & (TRACE_FLAG_NEED_RESCHED |
switch (entry->flags & (TRACE_FLAG_NEED_RESCHED | TRACE_FLAG_NEED_RESCHED_LAZY |
TRACE_FLAG_PREEMPT_RESCHED)) {
case TRACE_FLAG_NEED_RESCHED | TRACE_FLAG_NEED_RESCHED_LAZY | TRACE_FLAG_PREEMPT_RESCHED:
need_resched = 'B';
break;
case TRACE_FLAG_NEED_RESCHED | TRACE_FLAG_PREEMPT_RESCHED:
need_resched = 'N';
break;
case TRACE_FLAG_NEED_RESCHED_LAZY | TRACE_FLAG_PREEMPT_RESCHED:
need_resched = 'L';
break;
case TRACE_FLAG_NEED_RESCHED | TRACE_FLAG_NEED_RESCHED_LAZY:
need_resched = 'b';
break;
case TRACE_FLAG_NEED_RESCHED:
need_resched = 'n';
break;
case TRACE_FLAG_NEED_RESCHED_LAZY:
need_resched = 'l';
break;
case TRACE_FLAG_PREEMPT_RESCHED:
need_resched = 'p';
break;