lkml.org 
[lkml]   [2021]   [Dec]   [13]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 5.15 060/171] timers: implement usleep_idle_range()
    Date
    From: SeongJae Park <sj@kernel.org>

    commit e4779015fd5d2fb8390c258268addff24d6077c7 upstream.

    Patch series "mm/damon: Fix fake /proc/loadavg reports", v3.

    This patchset fixes DAMON's fake load report issue. The first patch
    makes yet another variant of usleep_range() for this fix, and the second
    patch fixes the issue of DAMON by making it using the newly introduced
    function.

    This patch (of 2):

    Some kernel threads such as DAMON could need to repeatedly sleep in
    micro seconds level. Because usleep_range() sleeps in uninterruptible
    state, however, such threads would make /proc/loadavg reports fake load.

    To help such cases, this commit implements a variant of usleep_range()
    called usleep_idle_range(). It is same to usleep_range() but sets the
    state of the current task as TASK_IDLE while sleeping.

    Link: https://lkml.kernel.org/r/20211126145015.15862-1-sj@kernel.org
    Link: https://lkml.kernel.org/r/20211126145015.15862-2-sj@kernel.org
    Signed-off-by: SeongJae Park <sj@kernel.org>
    Suggested-by: Andrew Morton <akpm@linux-foundation.org>
    Reviewed-by: Thomas Gleixner <tglx@linutronix.de>
    Tested-by: Oleksandr Natalenko <oleksandr@natalenko.name>
    Cc: John Stultz <john.stultz@linaro.org>
    Cc: <stable@vger.kernel.org>
    Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
    Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

    ---
    include/linux/delay.h | 14 +++++++++++++-
    kernel/time/timer.c | 16 +++++++++-------
    2 files changed, 22 insertions(+), 8 deletions(-)

    --- a/include/linux/delay.h
    +++ b/include/linux/delay.h
    @@ -20,6 +20,7 @@
    */

    #include <linux/kernel.h>
    +#include <linux/sched.h>

    extern unsigned long loops_per_jiffy;

    @@ -58,7 +59,18 @@ void calibrate_delay(void);
    void __attribute__((weak)) calibration_delay_done(void);
    void msleep(unsigned int msecs);
    unsigned long msleep_interruptible(unsigned int msecs);
    -void usleep_range(unsigned long min, unsigned long max);
    +void usleep_range_state(unsigned long min, unsigned long max,
    + unsigned int state);
    +
    +static inline void usleep_range(unsigned long min, unsigned long max)
    +{
    + usleep_range_state(min, max, TASK_UNINTERRUPTIBLE);
    +}
    +
    +static inline void usleep_idle_range(unsigned long min, unsigned long max)
    +{
    + usleep_range_state(min, max, TASK_IDLE);
    +}

    static inline void ssleep(unsigned int seconds)
    {
    --- a/kernel/time/timer.c
    +++ b/kernel/time/timer.c
    @@ -2054,26 +2054,28 @@ unsigned long msleep_interruptible(unsig
    EXPORT_SYMBOL(msleep_interruptible);

    /**
    - * usleep_range - Sleep for an approximate time
    - * @min: Minimum time in usecs to sleep
    - * @max: Maximum time in usecs to sleep
    + * usleep_range_state - Sleep for an approximate time in a given state
    + * @min: Minimum time in usecs to sleep
    + * @max: Maximum time in usecs to sleep
    + * @state: State of the current task that will be while sleeping
    *
    * In non-atomic context where the exact wakeup time is flexible, use
    - * usleep_range() instead of udelay(). The sleep improves responsiveness
    + * usleep_range_state() instead of udelay(). The sleep improves responsiveness
    * by avoiding the CPU-hogging busy-wait of udelay(), and the range reduces
    * power usage by allowing hrtimers to take advantage of an already-
    * scheduled interrupt instead of scheduling a new one just for this sleep.
    */
    -void __sched usleep_range(unsigned long min, unsigned long max)
    +void __sched usleep_range_state(unsigned long min, unsigned long max,
    + unsigned int state)
    {
    ktime_t exp = ktime_add_us(ktime_get(), min);
    u64 delta = (u64)(max - min) * NSEC_PER_USEC;

    for (;;) {
    - __set_current_state(TASK_UNINTERRUPTIBLE);
    + __set_current_state(state);
    /* Do not return before the requested sleep time has elapsed */
    if (!schedule_hrtimeout_range(&exp, delta, HRTIMER_MODE_ABS))
    break;
    }
    }
    -EXPORT_SYMBOL(usleep_range);
    +EXPORT_SYMBOL(usleep_range_state);

    \
     
     \ /
      Last update: 2021-12-13 11:19    [W:2.608 / U:0.640 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site