* [PATCH v2 00/15] timers: Cleanup delay/sleep related mess
@ 2024-09-11 5:13 Anna-Maria Behnsen
2024-09-11 5:13 ` [PATCH v2 01/15] MAINTAINERS: Add missing file include/linux/delay.h Anna-Maria Behnsen
` (15 more replies)
0 siblings, 16 replies; 47+ messages in thread
From: Anna-Maria Behnsen @ 2024-09-11 5:13 UTC (permalink / raw)
To: Frederic Weisbecker, Thomas Gleixner, Jonathan Corbet
Cc: linux-kernel, Len Brown, Rafael J. Wysocki, Anna-Maria Behnsen,
Andrew Morton, damon, linux-mm, SeongJae Park, Arnd Bergmann,
linux-arch, Heiner Kallweit, David S. Miller, Andy Whitcroft,
Joe Perches, Dwaipayan Ray, Liam Girdwood, Mark Brown,
Andrew Lunn, Jaroslav Kysela, Takashi Iwai, netdev, linux-sound,
Michael Ellerman, Nathan Lynch, linuxppc-dev,
Mauro Carvalho Chehab, linux-media
Hi,
a question about which sleeping function should be used in acpi_os_sleep()
started a discussion and examination about the existing documentation and
implementation of functions which insert a sleep/delay.
The result of the discussion was, that the documentation is outdated and
the implemented fsleep() reflects the outdated documentation but doesn't
help to reflect reality which in turns leads to the queue which covers the
following things:
- Split out all timeout and sleep related functions from hrtimer.c and timer.c
into a separate file
- Update function descriptions of sleep related functions
- Change fsleep() to reflect reality
- Rework all comments or users which obviously rely on the outdated
documentation as they reference "Documentation/timers/timers-howto.rst"
- Last but not least (as there are no more references): Update the outdated
documentation and move it into a file with a self explaining file name
The queue is available here and applies on top of tip/timers/core:
git://git.kernel.org/pub/scm/linux/kernel/git/anna-maria/linux-devel.git timers/misc
Signed-off-by: Anna-Maria Behnsen <anna-maria@linutronix.de>
---
Changes in v2:
- change udelay() and ndelay() as suggested by Thomas
- Update some formatting in the new sleep_timeout.c file
- minor typo changes and other small review remarks
Thanks,
Anna-Maria
---
Anna-Maria Behnsen (15):
MAINTAINERS: Add missing file include/linux/delay.h
timers: Move *sleep*() and timeout functions into a separate file
timers: Update schedule_[hr]timeout*() related function descriptions
timers: Rename usleep_idle_range() to usleep_range_idle()
timers: Update function descriptions of sleep/delay related functions
delay: Rework udelay and ndelay
timers: Adjust flseep() to reflect reality
mm/damon/core: Use generic upper bound recommondation for usleep_range()
timers: Add a warning to usleep_range_state() for wrong order of arguments
checkpatch: Remove broken sleep/delay related checks
regulator: core: Use fsleep() to get best sleep mechanism
iopoll/regmap/phy/snd: Fix comment referencing outdated timer documentation
powerpc/rtas: Use fsleep() to minimize additional sleep duration
media: anysee: Fix link to outdated sleep function documentation
timers/Documentation: Cleanup delay/sleep documentation
Documentation/dev-tools/checkpatch.rst | 6 -
Documentation/timers/delay_sleep_functions.rst | 122 ++++++++
Documentation/timers/index.rst | 2 +-
Documentation/timers/timers-howto.rst | 115 --------
MAINTAINERS | 2 +
arch/powerpc/kernel/rtas.c | 21 +-
drivers/media/usb/dvb-usb-v2/anysee.c | 6 +-
drivers/regulator/core.c | 47 +---
include/asm-generic/delay.h | 95 +++++--
include/linux/delay.h | 79 ++++--
include/linux/iopoll.h | 52 ++--
include/linux/phy.h | 9 +-
include/linux/regmap.h | 38 +--
kernel/time/Makefile | 2 +-
kernel/time/hrtimer.c | 120 --------
kernel/time/sleep_timeout.c | 376 +++++++++++++++++++++++++
kernel/time/timer.c | 192 -------------
mm/damon/core.c | 5 +-
scripts/checkpatch.pl | 38 ---
sound/soc/sof/ops.h | 8 +-
20 files changed, 701 insertions(+), 634 deletions(-)
^ permalink raw reply [flat|nested] 47+ messages in thread
* [PATCH v2 01/15] MAINTAINERS: Add missing file include/linux/delay.h
2024-09-11 5:13 [PATCH v2 00/15] timers: Cleanup delay/sleep related mess Anna-Maria Behnsen
@ 2024-09-11 5:13 ` Anna-Maria Behnsen
2024-10-01 20:11 ` Frederic Weisbecker
2024-09-11 5:13 ` [PATCH v2 02/15] timers: Move *sleep*() and timeout functions into a separate file Anna-Maria Behnsen
` (14 subsequent siblings)
15 siblings, 1 reply; 47+ messages in thread
From: Anna-Maria Behnsen @ 2024-09-11 5:13 UTC (permalink / raw)
To: Frederic Weisbecker, Thomas Gleixner, Jonathan Corbet
Cc: linux-kernel, Len Brown, Rafael J. Wysocki, Anna-Maria Behnsen
include/linux/delay.h is not covered by MAINTAINERS file. Add it to the
"HIGH-RESOLUTION TIMERS, TIMER WHEEL, CLOCKEVENTS" section.
Signed-off-by: Anna-Maria Behnsen <anna-maria@linutronix.de>
---
v2: New (splitted as requested by Frederic)
---
MAINTAINERS | 1 +
1 file changed, 1 insertion(+)
diff --git a/MAINTAINERS b/MAINTAINERS
index 42decde38320..d9135d8ece99 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -10010,6 +10010,7 @@ S: Maintained
T: git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git timers/core
F: Documentation/timers/
F: include/linux/clockchips.h
+F: include/linux/delay.h
F: include/linux/hrtimer.h
F: include/linux/timer.h
F: kernel/time/clockevents.c
--
2.39.2
^ permalink raw reply related [flat|nested] 47+ messages in thread
* [PATCH v2 02/15] timers: Move *sleep*() and timeout functions into a separate file
2024-09-11 5:13 [PATCH v2 00/15] timers: Cleanup delay/sleep related mess Anna-Maria Behnsen
2024-09-11 5:13 ` [PATCH v2 01/15] MAINTAINERS: Add missing file include/linux/delay.h Anna-Maria Behnsen
@ 2024-09-11 5:13 ` Anna-Maria Behnsen
2024-10-01 20:45 ` Frederic Weisbecker
2024-09-11 5:13 ` [PATCH v2 03/15] timers: Update schedule_[hr]timeout*() related function descriptions Anna-Maria Behnsen
` (13 subsequent siblings)
15 siblings, 1 reply; 47+ messages in thread
From: Anna-Maria Behnsen @ 2024-09-11 5:13 UTC (permalink / raw)
To: Frederic Weisbecker, Thomas Gleixner, Jonathan Corbet
Cc: linux-kernel, Len Brown, Rafael J. Wysocki, Anna-Maria Behnsen
All schedule_timeout() and *sleep*() related functions are interfaces on
top of timer list timers and hrtimers to add a sleep to the code. As they
are built on top of the timer list timers and hrtimers, the [hr]timer
interfaces are already used except when queuing the timer in
schedule_timeout(). But there exists the appropriate interface add_timer()
which does the same job with an extra check for an already pending timer.
Split all those functions as they are into a separate file and use
add_timer() instead of __mod_timer() in schedule_timeout().
While at it fix minor formatting issues and a multi line printk function
call in schedule_timeout().
Signed-off-by: Anna-Maria Behnsen <anna-maria@linutronix.de>
---
v2:
- Drop adding delay.h to MAINTAINERS file
- Some more minor formatting fixups
---
MAINTAINERS | 1 +
kernel/time/Makefile | 2 +-
kernel/time/hrtimer.c | 120 -----------------
kernel/time/sleep_timeout.c | 317 ++++++++++++++++++++++++++++++++++++++++++++
kernel/time/timer.c | 192 ---------------------------
5 files changed, 319 insertions(+), 313 deletions(-)
diff --git a/MAINTAINERS b/MAINTAINERS
index d9135d8ece99..e9cb09990e2a 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -10015,6 +10015,7 @@ F: include/linux/hrtimer.h
F: include/linux/timer.h
F: kernel/time/clockevents.c
F: kernel/time/hrtimer.c
+F: kernel/time/sleep_timeout.c
F: kernel/time/timer.c
F: kernel/time/timer_list.c
F: kernel/time/timer_migration.*
diff --git a/kernel/time/Makefile b/kernel/time/Makefile
index 4af2a264a160..fe0ae82124fe 100644
--- a/kernel/time/Makefile
+++ b/kernel/time/Makefile
@@ -1,5 +1,5 @@
# SPDX-License-Identifier: GPL-2.0
-obj-y += time.o timer.o hrtimer.o
+obj-y += time.o timer.o hrtimer.o sleep_timeout.o
obj-y += timekeeping.o ntp.o clocksource.o jiffies.o timer_list.o
obj-y += timeconv.o timecounter.o alarmtimer.o
diff --git a/kernel/time/hrtimer.c b/kernel/time/hrtimer.c
index e834b2bd83df..2750ce6cb2e4 100644
--- a/kernel/time/hrtimer.c
+++ b/kernel/time/hrtimer.c
@@ -2242,123 +2242,3 @@ void __init hrtimers_init(void)
hrtimers_prepare_cpu(smp_processor_id());
open_softirq(HRTIMER_SOFTIRQ, hrtimer_run_softirq);
}
-
-/**
- * schedule_hrtimeout_range_clock - sleep until timeout
- * @expires: timeout value (ktime_t)
- * @delta: slack in expires timeout (ktime_t)
- * @mode: timer mode
- * @clock_id: timer clock to be used
- */
-int __sched
-schedule_hrtimeout_range_clock(ktime_t *expires, u64 delta,
- const enum hrtimer_mode mode, clockid_t clock_id)
-{
- struct hrtimer_sleeper t;
-
- /*
- * Optimize when a zero timeout value is given. It does not
- * matter whether this is an absolute or a relative time.
- */
- if (expires && *expires == 0) {
- __set_current_state(TASK_RUNNING);
- return 0;
- }
-
- /*
- * A NULL parameter means "infinite"
- */
- if (!expires) {
- schedule();
- return -EINTR;
- }
-
- hrtimer_init_sleeper_on_stack(&t, clock_id, mode);
- hrtimer_set_expires_range_ns(&t.timer, *expires, delta);
- hrtimer_sleeper_start_expires(&t, mode);
-
- if (likely(t.task))
- schedule();
-
- hrtimer_cancel(&t.timer);
- destroy_hrtimer_on_stack(&t.timer);
-
- __set_current_state(TASK_RUNNING);
-
- return !t.task ? 0 : -EINTR;
-}
-EXPORT_SYMBOL_GPL(schedule_hrtimeout_range_clock);
-
-/**
- * schedule_hrtimeout_range - sleep until timeout
- * @expires: timeout value (ktime_t)
- * @delta: slack in expires timeout (ktime_t)
- * @mode: timer mode
- *
- * Make the current task sleep until the given expiry time has
- * elapsed. The routine will return immediately unless
- * the current task state has been set (see set_current_state()).
- *
- * The @delta argument gives the kernel the freedom to schedule the
- * actual wakeup to a time that is both power and performance friendly
- * for regular (non RT/DL) tasks.
- * The kernel give the normal best effort behavior for "@expires+@delta",
- * but may decide to fire the timer earlier, but no earlier than @expires.
- *
- * You can set the task state as follows -
- *
- * %TASK_UNINTERRUPTIBLE - at least @timeout time is guaranteed to
- * pass before the routine returns unless the current task is explicitly
- * woken up, (e.g. by wake_up_process()).
- *
- * %TASK_INTERRUPTIBLE - the routine may return early if a signal is
- * delivered to the current task or the current task is explicitly woken
- * up.
- *
- * The current task state is guaranteed to be TASK_RUNNING when this
- * routine returns.
- *
- * Returns 0 when the timer has expired. If the task was woken before the
- * timer expired by a signal (only possible in state TASK_INTERRUPTIBLE) or
- * by an explicit wakeup, it returns -EINTR.
- */
-int __sched schedule_hrtimeout_range(ktime_t *expires, u64 delta,
- const enum hrtimer_mode mode)
-{
- return schedule_hrtimeout_range_clock(expires, delta, mode,
- CLOCK_MONOTONIC);
-}
-EXPORT_SYMBOL_GPL(schedule_hrtimeout_range);
-
-/**
- * schedule_hrtimeout - sleep until timeout
- * @expires: timeout value (ktime_t)
- * @mode: timer mode
- *
- * Make the current task sleep until the given expiry time has
- * elapsed. The routine will return immediately unless
- * the current task state has been set (see set_current_state()).
- *
- * You can set the task state as follows -
- *
- * %TASK_UNINTERRUPTIBLE - at least @timeout time is guaranteed to
- * pass before the routine returns unless the current task is explicitly
- * woken up, (e.g. by wake_up_process()).
- *
- * %TASK_INTERRUPTIBLE - the routine may return early if a signal is
- * delivered to the current task or the current task is explicitly woken
- * up.
- *
- * The current task state is guaranteed to be TASK_RUNNING when this
- * routine returns.
- *
- * Returns 0 when the timer has expired. If the task was woken before the
- * timer expired by a signal (only possible in state TASK_INTERRUPTIBLE) or
- * by an explicit wakeup, it returns -EINTR.
- */
-int __sched schedule_hrtimeout(ktime_t *expires,
- const enum hrtimer_mode mode)
-{
- return schedule_hrtimeout_range(expires, 0, mode);
-}
-EXPORT_SYMBOL_GPL(schedule_hrtimeout);
diff --git a/kernel/time/sleep_timeout.c b/kernel/time/sleep_timeout.c
new file mode 100644
index 000000000000..78b2e7e30b1e
--- /dev/null
+++ b/kernel/time/sleep_timeout.c
@@ -0,0 +1,317 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Kernel internal schedule timeout and sleeping functions
+ */
+
+#include <linux/delay.h>
+#include <linux/jiffies.h>
+#include <linux/timer.h>
+#include <linux/sched/signal.h>
+#include <linux/sched/debug.h>
+
+#include "tick-internal.h"
+
+/*
+ * Since schedule_timeout()'s timer is defined on the stack, it must store
+ * the target task on the stack as well.
+ */
+struct process_timer {
+ struct timer_list timer;
+ struct task_struct *task;
+};
+
+static void process_timeout(struct timer_list *t)
+{
+ struct process_timer *timeout = from_timer(timeout, t, timer);
+
+ wake_up_process(timeout->task);
+}
+
+/**
+ * schedule_timeout - sleep until timeout
+ * @timeout: timeout value in jiffies
+ *
+ * Make the current task sleep until @timeout jiffies have elapsed.
+ * The function behavior depends on the current task state
+ * (see also set_current_state() description):
+ *
+ * %TASK_RUNNING - the scheduler is called, but the task does not sleep
+ * at all. That happens because sched_submit_work() does nothing for
+ * tasks in %TASK_RUNNING state.
+ *
+ * %TASK_UNINTERRUPTIBLE - at least @timeout jiffies are guaranteed to
+ * pass before the routine returns unless the current task is explicitly
+ * woken up, (e.g. by wake_up_process()).
+ *
+ * %TASK_INTERRUPTIBLE - the routine may return early if a signal is
+ * delivered to the current task or the current task is explicitly woken
+ * up.
+ *
+ * The current task state is guaranteed to be %TASK_RUNNING when this
+ * routine returns.
+ *
+ * Specifying a @timeout value of %MAX_SCHEDULE_TIMEOUT will schedule
+ * the CPU away without a bound on the timeout. In this case the return
+ * value will be %MAX_SCHEDULE_TIMEOUT.
+ *
+ * Returns: 0 when the timer has expired otherwise the remaining time in
+ * jiffies will be returned. In all cases the return value is guaranteed
+ * to be non-negative.
+ */
+signed long __sched schedule_timeout(signed long timeout)
+{
+ struct process_timer timer;
+ unsigned long expire;
+
+ switch (timeout) {
+ case MAX_SCHEDULE_TIMEOUT:
+ /*
+ * These two special cases are useful to be comfortable
+ * in the caller. Nothing more. We could take
+ * MAX_SCHEDULE_TIMEOUT from one of the negative value
+ * but I' d like to return a valid offset (>=0) to allow
+ * the caller to do everything it want with the retval.
+ */
+ schedule();
+ goto out;
+ default:
+ /*
+ * Another bit of PARANOID. Note that the retval will be
+ * 0 since no piece of kernel is supposed to do a check
+ * for a negative retval of schedule_timeout() (since it
+ * should never happens anyway). You just have the printk()
+ * that will tell you if something is gone wrong and where.
+ */
+ if (timeout < 0) {
+ pr_err("%s: wrong timeout value %lx\n", __func__, timeout);
+ dump_stack();
+ __set_current_state(TASK_RUNNING);
+ goto out;
+ }
+ }
+
+ expire = timeout + jiffies;
+
+ timer.task = current;
+ timer_setup_on_stack(&timer.timer, process_timeout, 0);
+ timer.timer.expires = expire;
+ add_timer(&timer.timer);
+ schedule();
+ del_timer_sync(&timer.timer);
+
+ /* Remove the timer from the object tracker */
+ destroy_timer_on_stack(&timer.timer);
+
+ timeout = expire - jiffies;
+
+ out:
+ return timeout < 0 ? 0 : timeout;
+}
+EXPORT_SYMBOL(schedule_timeout);
+
+/*
+ * We can use __set_current_state() here because schedule_timeout() calls
+ * schedule() unconditionally.
+ */
+signed long __sched schedule_timeout_interruptible(signed long timeout)
+{
+ __set_current_state(TASK_INTERRUPTIBLE);
+ return schedule_timeout(timeout);
+}
+EXPORT_SYMBOL(schedule_timeout_interruptible);
+
+signed long __sched schedule_timeout_killable(signed long timeout)
+{
+ __set_current_state(TASK_KILLABLE);
+ return schedule_timeout(timeout);
+}
+EXPORT_SYMBOL(schedule_timeout_killable);
+
+signed long __sched schedule_timeout_uninterruptible(signed long timeout)
+{
+ __set_current_state(TASK_UNINTERRUPTIBLE);
+ return schedule_timeout(timeout);
+}
+EXPORT_SYMBOL(schedule_timeout_uninterruptible);
+
+/*
+ * Like schedule_timeout_uninterruptible(), except this task will not contribute
+ * to load average.
+ */
+signed long __sched schedule_timeout_idle(signed long timeout)
+{
+ __set_current_state(TASK_IDLE);
+ return schedule_timeout(timeout);
+}
+EXPORT_SYMBOL(schedule_timeout_idle);
+
+/**
+ * schedule_hrtimeout_range_clock - sleep until timeout
+ * @expires: timeout value (ktime_t)
+ * @delta: slack in expires timeout (ktime_t)
+ * @mode: timer mode
+ * @clock_id: timer clock to be used
+ */
+int __sched schedule_hrtimeout_range_clock(ktime_t *expires, u64 delta,
+ const enum hrtimer_mode mode, clockid_t clock_id)
+{
+ struct hrtimer_sleeper t;
+
+ /*
+ * Optimize when a zero timeout value is given. It does not
+ * matter whether this is an absolute or a relative time.
+ */
+ if (expires && *expires == 0) {
+ __set_current_state(TASK_RUNNING);
+ return 0;
+ }
+
+ /*
+ * A NULL parameter means "infinite"
+ */
+ if (!expires) {
+ schedule();
+ return -EINTR;
+ }
+
+ hrtimer_init_sleeper_on_stack(&t, clock_id, mode);
+ hrtimer_set_expires_range_ns(&t.timer, *expires, delta);
+ hrtimer_sleeper_start_expires(&t, mode);
+
+ if (likely(t.task))
+ schedule();
+
+ hrtimer_cancel(&t.timer);
+ destroy_hrtimer_on_stack(&t.timer);
+
+ __set_current_state(TASK_RUNNING);
+
+ return !t.task ? 0 : -EINTR;
+}
+EXPORT_SYMBOL_GPL(schedule_hrtimeout_range_clock);
+
+/**
+ * schedule_hrtimeout_range - sleep until timeout
+ * @expires: timeout value (ktime_t)
+ * @delta: slack in expires timeout (ktime_t)
+ * @mode: timer mode
+ *
+ * Make the current task sleep until the given expiry time has
+ * elapsed. The routine will return immediately unless
+ * the current task state has been set (see set_current_state()).
+ *
+ * The @delta argument gives the kernel the freedom to schedule the
+ * actual wakeup to a time that is both power and performance friendly
+ * for regular (non RT/DL) tasks.
+ * The kernel give the normal best effort behavior for "@expires+@delta",
+ * but may decide to fire the timer earlier, but no earlier than @expires.
+ *
+ * You can set the task state as follows -
+ *
+ * %TASK_UNINTERRUPTIBLE - at least @timeout time is guaranteed to
+ * pass before the routine returns unless the current task is explicitly
+ * woken up, (e.g. by wake_up_process()).
+ *
+ * %TASK_INTERRUPTIBLE - the routine may return early if a signal is
+ * delivered to the current task or the current task is explicitly woken
+ * up.
+ *
+ * The current task state is guaranteed to be TASK_RUNNING when this
+ * routine returns.
+ *
+ * Returns: 0 when the timer has expired. If the task was woken before the
+ * timer expired by a signal (only possible in state TASK_INTERRUPTIBLE) or
+ * by an explicit wakeup, it returns -EINTR.
+ */
+int __sched schedule_hrtimeout_range(ktime_t *expires, u64 delta,
+ const enum hrtimer_mode mode)
+{
+ return schedule_hrtimeout_range_clock(expires, delta, mode,
+ CLOCK_MONOTONIC);
+}
+EXPORT_SYMBOL_GPL(schedule_hrtimeout_range);
+
+/**
+ * schedule_hrtimeout - sleep until timeout
+ * @expires: timeout value (ktime_t)
+ * @mode: timer mode
+ *
+ * Make the current task sleep until the given expiry time has
+ * elapsed. The routine will return immediately unless
+ * the current task state has been set (see set_current_state()).
+ *
+ * You can set the task state as follows -
+ *
+ * %TASK_UNINTERRUPTIBLE - at least @timeout time is guaranteed to
+ * pass before the routine returns unless the current task is explicitly
+ * woken up, (e.g. by wake_up_process()).
+ *
+ * %TASK_INTERRUPTIBLE - the routine may return early if a signal is
+ * delivered to the current task or the current task is explicitly woken
+ * up.
+ *
+ * The current task state is guaranteed to be TASK_RUNNING when this
+ * routine returns.
+ *
+ * Returns: 0 when the timer has expired. If the task was woken before the
+ * timer expired by a signal (only possible in state TASK_INTERRUPTIBLE) or
+ * by an explicit wakeup, it returns -EINTR.
+ */
+int __sched schedule_hrtimeout(ktime_t *expires, const enum hrtimer_mode mode)
+{
+ return schedule_hrtimeout_range(expires, 0, mode);
+}
+EXPORT_SYMBOL_GPL(schedule_hrtimeout);
+
+/**
+ * msleep - sleep safely even with waitqueue interruptions
+ * @msecs: Time in milliseconds to sleep for
+ */
+void msleep(unsigned int msecs)
+{
+ unsigned long timeout = msecs_to_jiffies(msecs);
+
+ while (timeout)
+ timeout = schedule_timeout_uninterruptible(timeout);
+}
+EXPORT_SYMBOL(msleep);
+
+/**
+ * msleep_interruptible - sleep waiting for signals
+ * @msecs: Time in milliseconds to sleep for
+ */
+unsigned long msleep_interruptible(unsigned int msecs)
+{
+ unsigned long timeout = msecs_to_jiffies(msecs);
+
+ while (timeout && !signal_pending(current))
+ timeout = schedule_timeout_interruptible(timeout);
+ return jiffies_to_msecs(timeout);
+}
+EXPORT_SYMBOL(msleep_interruptible);
+
+/**
+ * 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_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_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(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_state);
diff --git a/kernel/time/timer.c b/kernel/time/timer.c
index 2b38f3035a3e..bb53d22cc911 100644
--- a/kernel/time/timer.c
+++ b/kernel/time/timer.c
@@ -37,7 +37,6 @@
#include <linux/tick.h>
#include <linux/kallsyms.h>
#include <linux/irq_work.h>
-#include <linux/sched/signal.h>
#include <linux/sched/sysctl.h>
#include <linux/sched/nohz.h>
#include <linux/sched/debug.h>
@@ -2526,141 +2525,6 @@ void update_process_times(int user_tick)
run_posix_cpu_timers();
}
-/*
- * Since schedule_timeout()'s timer is defined on the stack, it must store
- * the target task on the stack as well.
- */
-struct process_timer {
- struct timer_list timer;
- struct task_struct *task;
-};
-
-static void process_timeout(struct timer_list *t)
-{
- struct process_timer *timeout = from_timer(timeout, t, timer);
-
- wake_up_process(timeout->task);
-}
-
-/**
- * schedule_timeout - sleep until timeout
- * @timeout: timeout value in jiffies
- *
- * Make the current task sleep until @timeout jiffies have elapsed.
- * The function behavior depends on the current task state
- * (see also set_current_state() description):
- *
- * %TASK_RUNNING - the scheduler is called, but the task does not sleep
- * at all. That happens because sched_submit_work() does nothing for
- * tasks in %TASK_RUNNING state.
- *
- * %TASK_UNINTERRUPTIBLE - at least @timeout jiffies are guaranteed to
- * pass before the routine returns unless the current task is explicitly
- * woken up, (e.g. by wake_up_process()).
- *
- * %TASK_INTERRUPTIBLE - the routine may return early if a signal is
- * delivered to the current task or the current task is explicitly woken
- * up.
- *
- * The current task state is guaranteed to be %TASK_RUNNING when this
- * routine returns.
- *
- * Specifying a @timeout value of %MAX_SCHEDULE_TIMEOUT will schedule
- * the CPU away without a bound on the timeout. In this case the return
- * value will be %MAX_SCHEDULE_TIMEOUT.
- *
- * Returns 0 when the timer has expired otherwise the remaining time in
- * jiffies will be returned. In all cases the return value is guaranteed
- * to be non-negative.
- */
-signed long __sched schedule_timeout(signed long timeout)
-{
- struct process_timer timer;
- unsigned long expire;
-
- switch (timeout)
- {
- case MAX_SCHEDULE_TIMEOUT:
- /*
- * These two special cases are useful to be comfortable
- * in the caller. Nothing more. We could take
- * MAX_SCHEDULE_TIMEOUT from one of the negative value
- * but I' d like to return a valid offset (>=0) to allow
- * the caller to do everything it want with the retval.
- */
- schedule();
- goto out;
- default:
- /*
- * Another bit of PARANOID. Note that the retval will be
- * 0 since no piece of kernel is supposed to do a check
- * for a negative retval of schedule_timeout() (since it
- * should never happens anyway). You just have the printk()
- * that will tell you if something is gone wrong and where.
- */
- if (timeout < 0) {
- printk(KERN_ERR "schedule_timeout: wrong timeout "
- "value %lx\n", timeout);
- dump_stack();
- __set_current_state(TASK_RUNNING);
- goto out;
- }
- }
-
- expire = timeout + jiffies;
-
- timer.task = current;
- timer_setup_on_stack(&timer.timer, process_timeout, 0);
- __mod_timer(&timer.timer, expire, MOD_TIMER_NOTPENDING);
- schedule();
- del_timer_sync(&timer.timer);
-
- /* Remove the timer from the object tracker */
- destroy_timer_on_stack(&timer.timer);
-
- timeout = expire - jiffies;
-
- out:
- return timeout < 0 ? 0 : timeout;
-}
-EXPORT_SYMBOL(schedule_timeout);
-
-/*
- * We can use __set_current_state() here because schedule_timeout() calls
- * schedule() unconditionally.
- */
-signed long __sched schedule_timeout_interruptible(signed long timeout)
-{
- __set_current_state(TASK_INTERRUPTIBLE);
- return schedule_timeout(timeout);
-}
-EXPORT_SYMBOL(schedule_timeout_interruptible);
-
-signed long __sched schedule_timeout_killable(signed long timeout)
-{
- __set_current_state(TASK_KILLABLE);
- return schedule_timeout(timeout);
-}
-EXPORT_SYMBOL(schedule_timeout_killable);
-
-signed long __sched schedule_timeout_uninterruptible(signed long timeout)
-{
- __set_current_state(TASK_UNINTERRUPTIBLE);
- return schedule_timeout(timeout);
-}
-EXPORT_SYMBOL(schedule_timeout_uninterruptible);
-
-/*
- * Like schedule_timeout_uninterruptible(), except this task will not contribute
- * to load average.
- */
-signed long __sched schedule_timeout_idle(signed long timeout)
-{
- __set_current_state(TASK_IDLE);
- return schedule_timeout(timeout);
-}
-EXPORT_SYMBOL(schedule_timeout_idle);
-
#ifdef CONFIG_HOTPLUG_CPU
static void migrate_timer_list(struct timer_base *new_base, struct hlist_head *head)
{
@@ -2757,59 +2621,3 @@ void __init init_timers(void)
posix_cputimers_init_work();
open_softirq(TIMER_SOFTIRQ, run_timer_softirq);
}
-
-/**
- * msleep - sleep safely even with waitqueue interruptions
- * @msecs: Time in milliseconds to sleep for
- */
-void msleep(unsigned int msecs)
-{
- unsigned long timeout = msecs_to_jiffies(msecs);
-
- while (timeout)
- timeout = schedule_timeout_uninterruptible(timeout);
-}
-
-EXPORT_SYMBOL(msleep);
-
-/**
- * msleep_interruptible - sleep waiting for signals
- * @msecs: Time in milliseconds to sleep for
- */
-unsigned long msleep_interruptible(unsigned int msecs)
-{
- unsigned long timeout = msecs_to_jiffies(msecs);
-
- while (timeout && !signal_pending(current))
- timeout = schedule_timeout_interruptible(timeout);
- return jiffies_to_msecs(timeout);
-}
-
-EXPORT_SYMBOL(msleep_interruptible);
-
-/**
- * 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_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_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(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_state);
--
2.39.2
^ permalink raw reply related [flat|nested] 47+ messages in thread
* [PATCH v2 03/15] timers: Update schedule_[hr]timeout*() related function descriptions
2024-09-11 5:13 [PATCH v2 00/15] timers: Cleanup delay/sleep related mess Anna-Maria Behnsen
2024-09-11 5:13 ` [PATCH v2 01/15] MAINTAINERS: Add missing file include/linux/delay.h Anna-Maria Behnsen
2024-09-11 5:13 ` [PATCH v2 02/15] timers: Move *sleep*() and timeout functions into a separate file Anna-Maria Behnsen
@ 2024-09-11 5:13 ` Anna-Maria Behnsen
2024-10-01 21:16 ` Frederic Weisbecker
2024-09-11 5:13 ` [PATCH v2 04/15] timers: Rename usleep_idle_range() to usleep_range_idle() Anna-Maria Behnsen
` (12 subsequent siblings)
15 siblings, 1 reply; 47+ messages in thread
From: Anna-Maria Behnsen @ 2024-09-11 5:13 UTC (permalink / raw)
To: Frederic Weisbecker, Thomas Gleixner, Jonathan Corbet
Cc: linux-kernel, Len Brown, Rafael J. Wysocki, Anna-Maria Behnsen
schedule_timeout*() functions do not have proper kernel-doc formatted
function descriptions. schedule_hrtimeout() and schedule_hrtimeout_range()
have a almost identical description.
Add missing function descriptions. Remove copy of function description and
add a pointer to the existing description instead.
Signed-off-by: Anna-Maria Behnsen <anna-maria@linutronix.de>
---
v2: New in v2
---
kernel/time/sleep_timeout.c | 66 ++++++++++++++++++++++++++++-----------------
1 file changed, 41 insertions(+), 25 deletions(-)
diff --git a/kernel/time/sleep_timeout.c b/kernel/time/sleep_timeout.c
index 78b2e7e30b1e..560d17c30aa5 100644
--- a/kernel/time/sleep_timeout.c
+++ b/kernel/time/sleep_timeout.c
@@ -110,8 +110,17 @@ signed long __sched schedule_timeout(signed long timeout)
EXPORT_SYMBOL(schedule_timeout);
/*
- * We can use __set_current_state() here because schedule_timeout() calls
- * schedule() unconditionally.
+ * __set_current_state() can be used in schedule_timeout_*() functions, because
+ * schedule_timeout() calls schedule() unconditionally.
+ */
+
+/**
+ * schedule_timeout_interruptible - sleep until timeout (interruptible)
+ * @timeout: timeout value in jiffies
+ *
+ * See schedule_timeout() for details.
+ *
+ * Task state is set to TASK_INTERRUPTIBLE before starting the timeout.
*/
signed long __sched schedule_timeout_interruptible(signed long timeout)
{
@@ -120,6 +129,14 @@ signed long __sched schedule_timeout_interruptible(signed long timeout)
}
EXPORT_SYMBOL(schedule_timeout_interruptible);
+/**
+ * schedule_timeout_killable - sleep until timeout (killable)
+ * @timeout: timeout value in jiffies
+ *
+ * See schedule_timeout() for details.
+ *
+ * Task state is set to TASK_KILLABLE before starting the timeout.
+ */
signed long __sched schedule_timeout_killable(signed long timeout)
{
__set_current_state(TASK_KILLABLE);
@@ -127,6 +144,14 @@ signed long __sched schedule_timeout_killable(signed long timeout)
}
EXPORT_SYMBOL(schedule_timeout_killable);
+/**
+ * schedule_timeout_uninterruptible - sleep until timeout (uninterruptible)
+ * @timeout: timeout value in jiffies
+ *
+ * See schedule_timeout() for details.
+ *
+ * Task state is set to TASK_UNINTERRUPTIBLE before starting the timeout.
+ */
signed long __sched schedule_timeout_uninterruptible(signed long timeout)
{
__set_current_state(TASK_UNINTERRUPTIBLE);
@@ -134,9 +159,15 @@ signed long __sched schedule_timeout_uninterruptible(signed long timeout)
}
EXPORT_SYMBOL(schedule_timeout_uninterruptible);
-/*
- * Like schedule_timeout_uninterruptible(), except this task will not contribute
- * to load average.
+/**
+ * schedule_timeout_idle - sleep until timeout (idle)
+ * @timeout: timeout value in jiffies
+ *
+ * See schedule_timeout() for details.
+ *
+ * Task state is set to TASK_IDLE before starting the timeout. It is similar to
+ * schedule_timeout_uninterruptible(), except this task will not contribute to
+ * load average.
*/
signed long __sched schedule_timeout_idle(signed long timeout)
{
@@ -151,6 +182,9 @@ EXPORT_SYMBOL(schedule_timeout_idle);
* @delta: slack in expires timeout (ktime_t)
* @mode: timer mode
* @clock_id: timer clock to be used
+ *
+ * Details are explained in schedule_hrtimeout_range() function description as
+ * this function is commonly used.
*/
int __sched schedule_hrtimeout_range_clock(ktime_t *expires, u64 delta,
const enum hrtimer_mode mode, clockid_t clock_id)
@@ -236,26 +270,8 @@ EXPORT_SYMBOL_GPL(schedule_hrtimeout_range);
* @expires: timeout value (ktime_t)
* @mode: timer mode
*
- * Make the current task sleep until the given expiry time has
- * elapsed. The routine will return immediately unless
- * the current task state has been set (see set_current_state()).
- *
- * You can set the task state as follows -
- *
- * %TASK_UNINTERRUPTIBLE - at least @timeout time is guaranteed to
- * pass before the routine returns unless the current task is explicitly
- * woken up, (e.g. by wake_up_process()).
- *
- * %TASK_INTERRUPTIBLE - the routine may return early if a signal is
- * delivered to the current task or the current task is explicitly woken
- * up.
- *
- * The current task state is guaranteed to be TASK_RUNNING when this
- * routine returns.
- *
- * Returns: 0 when the timer has expired. If the task was woken before the
- * timer expired by a signal (only possible in state TASK_INTERRUPTIBLE) or
- * by an explicit wakeup, it returns -EINTR.
+ * See schedule_hrtimeout_range() for details. @delta argument of
+ * schedule_hrtimeout_range() is set to 0 and has therefore no impact.
*/
int __sched schedule_hrtimeout(ktime_t *expires, const enum hrtimer_mode mode)
{
--
2.39.2
^ permalink raw reply related [flat|nested] 47+ messages in thread
* [PATCH v2 04/15] timers: Rename usleep_idle_range() to usleep_range_idle()
2024-09-11 5:13 [PATCH v2 00/15] timers: Cleanup delay/sleep related mess Anna-Maria Behnsen
` (2 preceding siblings ...)
2024-09-11 5:13 ` [PATCH v2 03/15] timers: Update schedule_[hr]timeout*() related function descriptions Anna-Maria Behnsen
@ 2024-09-11 5:13 ` Anna-Maria Behnsen
2024-09-11 5:13 ` [PATCH v2 05/15] timers: Update function descriptions of sleep/delay related functions Anna-Maria Behnsen
` (11 subsequent siblings)
15 siblings, 0 replies; 47+ messages in thread
From: Anna-Maria Behnsen @ 2024-09-11 5:13 UTC (permalink / raw)
To: Frederic Weisbecker, Thomas Gleixner, Jonathan Corbet
Cc: linux-kernel, Len Brown, Rafael J. Wysocki, Anna-Maria Behnsen,
Andrew Morton, damon, linux-mm, SeongJae Park
usleep_idle_range() is a variant of usleep_range(). Both are using
usleep_range_state() as a base. To be able to find all the related
functions in one go, rename it usleep_idle_range() to usleep_range_idle().
No functional change.
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: damon@lists.linux.dev
Cc: linux-mm@kvack.org
Signed-off-by: Anna-Maria Behnsen <anna-maria@linutronix.de>
Reviewed-by: Frederic Weisbecker <frederic@kernel.org>
Reviewed-by: SeongJae Park <sj@kernel.org>
---
v2: Fix typos in commit message
---
include/linux/delay.h | 2 +-
mm/damon/core.c | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/include/linux/delay.h b/include/linux/delay.h
index ff9cda975e30..2bc586aa2068 100644
--- a/include/linux/delay.h
+++ b/include/linux/delay.h
@@ -68,7 +68,7 @@ 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)
+static inline void usleep_range_idle(unsigned long min, unsigned long max)
{
usleep_range_state(min, max, TASK_IDLE);
}
diff --git a/mm/damon/core.c b/mm/damon/core.c
index 7a87628b76ab..94fe2f1f9b0e 100644
--- a/mm/damon/core.c
+++ b/mm/damon/core.c
@@ -1887,7 +1887,7 @@ static void kdamond_usleep(unsigned long usecs)
if (usecs > 20 * USEC_PER_MSEC)
schedule_timeout_idle(usecs_to_jiffies(usecs));
else
- usleep_idle_range(usecs, usecs + 1);
+ usleep_range_idle(usecs, usecs + 1);
}
/* Returns negative error code if it's not activated but should return */
--
2.39.2
^ permalink raw reply related [flat|nested] 47+ messages in thread
* [PATCH v2 05/15] timers: Update function descriptions of sleep/delay related functions
2024-09-11 5:13 [PATCH v2 00/15] timers: Cleanup delay/sleep related mess Anna-Maria Behnsen
` (3 preceding siblings ...)
2024-09-11 5:13 ` [PATCH v2 04/15] timers: Rename usleep_idle_range() to usleep_range_idle() Anna-Maria Behnsen
@ 2024-09-11 5:13 ` Anna-Maria Behnsen
2024-10-06 21:49 ` Frederic Weisbecker
2024-09-11 5:13 ` [PATCH v2 06/15] delay: Rework udelay and ndelay Anna-Maria Behnsen
` (10 subsequent siblings)
15 siblings, 1 reply; 47+ messages in thread
From: Anna-Maria Behnsen @ 2024-09-11 5:13 UTC (permalink / raw)
To: Frederic Weisbecker, Thomas Gleixner, Jonathan Corbet
Cc: linux-kernel, Len Brown, Rafael J. Wysocki, Anna-Maria Behnsen,
Arnd Bergmann, linux-arch
A lot of commonly used functions for inserting a sleep or delay lack a
proper function description. Add function descriptions to all of them to
have important information in a central place close to the code.
No functional change.
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: linux-arch@vger.kernel.org
Signed-off-by: Anna-Maria Behnsen <anna-maria@linutronix.de>
---
v2:
- Fix typos
- Fix proper usage of kernel-doc return formatting
---
include/asm-generic/delay.h | 41 +++++++++++++++++++++++++++++++----
include/linux/delay.h | 48 ++++++++++++++++++++++++++++++----------
kernel/time/sleep_timeout.c | 53 ++++++++++++++++++++++++++++++++++++++++-----
3 files changed, 120 insertions(+), 22 deletions(-)
diff --git a/include/asm-generic/delay.h b/include/asm-generic/delay.h
index e448ac61430c..70a1b20f3e1a 100644
--- a/include/asm-generic/delay.h
+++ b/include/asm-generic/delay.h
@@ -12,11 +12,39 @@ extern void __const_udelay(unsigned long xloops);
extern void __delay(unsigned long loops);
/*
- * The weird n/20000 thing suppresses a "comparison is always false due to
- * limited range of data type" warning with non-const 8-bit arguments.
+ * Implementation details:
+ *
+ * * The weird n/20000 thing suppresses a "comparison is always false due to
+ * limited range of data type" warning with non-const 8-bit arguments.
+ * * 0x10c7 is 2**32 / 1000000 (rounded up) -> udelay
+ * * 0x5 is 2**32 / 1000000000 (rounded up) -> ndelay
*/
-/* 0x10c7 is 2**32 / 1000000 (rounded up) */
+/**
+ * udelay - Inserting a delay based on microseconds with busy waiting
+ * @usec: requested delay in microseconds
+ *
+ * When delaying in an atomic context ndelay(), udelay() and mdelay() are the
+ * only valid variants of delaying/sleeping to go with.
+ *
+ * When inserting delays in non atomic context which are shorter than the time
+ * which is required to queue e.g. an hrtimer and to enter then the scheduler,
+ * it is also valuable to use udelay(). But is not simple to specify a generic
+ * threshold for this which will fit for all systems, but an approximation would
+ * be a threshold for all delays up to 10 microseconds.
+ *
+ * When having a delay which is larger than the architecture specific
+ * %MAX_UDELAY_MS value, please make sure mdelay() is used. Otherwise a overflow
+ * risk is given.
+ *
+ * Please note that ndelay(), udelay() and mdelay() may return early for several
+ * reasons (https://lists.openwall.net/linux-kernel/2011/01/09/56):
+ *
+ * #. computed loops_per_jiffy too low (due to the time taken to execute the
+ * timer interrupt.)
+ * #. cache behaviour affecting the time it takes to execute the loop function.
+ * #. CPU clock rate changes.
+ */
#define udelay(n) \
({ \
if (__builtin_constant_p(n)) { \
@@ -29,7 +57,12 @@ extern void __delay(unsigned long loops);
} \
})
-/* 0x5 is 2**32 / 1000000000 (rounded up) */
+/**
+ * ndelay - Inserting a delay based on nanoseconds with busy waiting
+ * @nsec: requested delay in nanoseconds
+ *
+ * See udelay() for basic information about ndelay() and it's variants.
+ */
#define ndelay(n) \
({ \
if (__builtin_constant_p(n)) { \
diff --git a/include/linux/delay.h b/include/linux/delay.h
index 2bc586aa2068..23623fa79768 100644
--- a/include/linux/delay.h
+++ b/include/linux/delay.h
@@ -6,17 +6,7 @@
* Copyright (C) 1993 Linus Torvalds
*
* Delay routines, using a pre-computed "loops_per_jiffy" value.
- *
- * Please note that ndelay(), udelay() and mdelay() may return early for
- * several reasons:
- * 1. computed loops_per_jiffy too low (due to the time taken to
- * execute the timer interrupt.)
- * 2. cache behaviour affecting the time it takes to execute the
- * loop function.
- * 3. CPU clock rate changes.
- *
- * Please see this thread:
- * https://lists.openwall.net/linux-kernel/2011/01/09/56
+ * Sleep routines using timer list timers or hrtimers.
*/
#include <linux/math.h>
@@ -35,12 +25,21 @@ extern unsigned long loops_per_jiffy;
* The 2nd mdelay() definition ensures GCC will optimize away the
* while loop for the common cases where n <= MAX_UDELAY_MS -- Paul G.
*/
-
#ifndef MAX_UDELAY_MS
#define MAX_UDELAY_MS 5
#endif
#ifndef mdelay
+/**
+ * mdelay - Inserting a delay based on microseconds with busy waiting
+ * @n: requested delay in microseconds
+ *
+ * See udelay() for basic information about mdelay() and it's variants.
+ *
+ * Please double check, whether mdelay() is the right way to go or whether a
+ * refactoring of the code is the better variant to be able to use msleep()
+ * instead.
+ */
#define mdelay(n) (\
(__builtin_constant_p(n) && (n)<=MAX_UDELAY_MS) ? udelay((n)*1000) : \
({unsigned long __ms=(n); while (__ms--) udelay(1000);}))
@@ -63,16 +62,41 @@ unsigned long msleep_interruptible(unsigned int msecs);
void usleep_range_state(unsigned long min, unsigned long max,
unsigned int state);
+/**
+ * usleep_range - Sleep for an approximate time
+ * @min: Minimum time in microseconds to sleep
+ * @max: Maximum time in microseconds to sleep
+ *
+ * For basic information please refere to usleep_range_state().
+ *
+ * The task will be in the state TASK_UNINTERRUPTIBLE during the sleep.
+ */
static inline void usleep_range(unsigned long min, unsigned long max)
{
usleep_range_state(min, max, TASK_UNINTERRUPTIBLE);
}
+/**
+ * usleep_range_idle - Sleep for an approximate time with idle time accounting
+ * @min: Minimum time in microseconds to sleep
+ * @max: Maximum time in microseconds to sleep
+ *
+ * For basic information please refere to usleep_range_state().
+ *
+ * The sleeping task has the state TASK_IDLE during the sleep to prevent
+ * contribution to the load avarage.
+ */
static inline void usleep_range_idle(unsigned long min, unsigned long max)
{
usleep_range_state(min, max, TASK_IDLE);
}
+/**
+ * ssleep - wrapper for seconds arount msleep
+ * @seconds: Requested sleep duration in seconds
+ *
+ * Please refere to msleep() for detailed information.
+ */
static inline void ssleep(unsigned int seconds)
{
msleep(seconds * 1000);
diff --git a/kernel/time/sleep_timeout.c b/kernel/time/sleep_timeout.c
index 560d17c30aa5..21f412350b15 100644
--- a/kernel/time/sleep_timeout.c
+++ b/kernel/time/sleep_timeout.c
@@ -281,7 +281,34 @@ EXPORT_SYMBOL_GPL(schedule_hrtimeout);
/**
* msleep - sleep safely even with waitqueue interruptions
- * @msecs: Time in milliseconds to sleep for
+ * @msecs: Requested sleep duration in milliseconds
+ *
+ * msleep() uses jiffy based timeouts for the sleep duration. The accuracy of
+ * the resulting sleep duration depends on:
+ *
+ * * HZ configuration
+ * * sleep duration (as granularity of a bucket which collects timers increases
+ * with the timer wheel levels)
+ *
+ * When the timer is queued into the second level of the timer wheel the maximum
+ * additional delay will be 12.5%. For explanation please check the detailed
+ * description about the basics of the timer wheel. In case this is accurate
+ * enough check which sleep length is selected to make sure required accuracy is
+ * given. Please use therefore the following simple steps:
+ *
+ * #. Decide which slack is fine for the requested sleep duration - but do not
+ * use values shorter than 1/8
+ * #. Check whether your sleep duration is equal or greater than the following
+ * result: ``TICK_NSEC / slack / NSEC_PER_MSEC``
+ *
+ * Examples:
+ *
+ * * ``HZ=1000`` with `slack=1/4``: all sleep durations greater or equal 4ms will meet
+ * the constrains.
+ * * ``HZ=250`` with ``slack=1/4``: all sleep durations greater or equal 16ms will meet
+ * the constrains.
+ *
+ * See also the signal aware variant msleep_interruptible().
*/
void msleep(unsigned int msecs)
{
@@ -294,7 +321,15 @@ EXPORT_SYMBOL(msleep);
/**
* msleep_interruptible - sleep waiting for signals
- * @msecs: Time in milliseconds to sleep for
+ * @msecs: Requested sleep duration in milliseconds
+ *
+ * See msleep() for some basic information.
+ *
+ * The difference between msleep() and msleep_interruptible() is that the sleep
+ * could be interrupted by a signal delivery and then returns early.
+ *
+ * Returns: The remaining time of the sleep duration transformed to msecs (see
+ * schedule_timeout() for details).
*/
unsigned long msleep_interruptible(unsigned int msecs)
{
@@ -312,11 +347,17 @@ EXPORT_SYMBOL(msleep_interruptible);
* @max: Maximum time in usecs to sleep
* @state: State of the current task that will be while sleeping
*
+ * usleep_range_state() sleeps at least for the minimum specified time but not
+ * longer than the maximum specified amount of time. The range might reduce
+ * power usage by allowing hrtimers to coalesce an already scheduled interrupt
+ * with this hrtimer. In the worst case, an interrupt is scheduled for the upper
+ * bound.
+ *
+ * The sleeping task is set to the specified state before starting the sleep.
+ *
* In non-atomic context where the exact wakeup time is flexible, use
- * 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.
+ * usleep_range() or its variants instead of udelay(). The sleep improves
+ * responsiveness by avoiding the CPU-hogging busy-wait of udelay().
*/
void __sched usleep_range_state(unsigned long min, unsigned long max, unsigned int state)
{
--
2.39.2
^ permalink raw reply related [flat|nested] 47+ messages in thread
* [PATCH v2 06/15] delay: Rework udelay and ndelay
2024-09-11 5:13 [PATCH v2 00/15] timers: Cleanup delay/sleep related mess Anna-Maria Behnsen
` (4 preceding siblings ...)
2024-09-11 5:13 ` [PATCH v2 05/15] timers: Update function descriptions of sleep/delay related functions Anna-Maria Behnsen
@ 2024-09-11 5:13 ` Anna-Maria Behnsen
2024-09-23 15:40 ` Anna-Maria Behnsen
2024-10-08 14:24 ` Frederic Weisbecker
2024-09-11 5:13 ` [PATCH v2 07/15] timers: Adjust flseep() to reflect reality Anna-Maria Behnsen
` (9 subsequent siblings)
15 siblings, 2 replies; 47+ messages in thread
From: Anna-Maria Behnsen @ 2024-09-11 5:13 UTC (permalink / raw)
To: Frederic Weisbecker, Thomas Gleixner, Jonathan Corbet
Cc: linux-kernel, Len Brown, Rafael J. Wysocki, Anna-Maria Behnsen
udelay() as well as ndelay() are defines and no functions and are using
constants to be able to transform a sleep time into loops and to prevent
too long udelays/ndelays. There was a compiler error with non-const 8 bit
arguments which was fixed by commit a87e553fabe8 ("asm-generic: delay.h fix
udelay and ndelay for 8 bit args"). When using a function, the non-const 8
bit argument is type casted and the problem would be gone.
Transform udelay() and ndelay() into proper functions, remove the no longer
and confusing division, add defines for the magic values and add some
explanations as well.
Suggested-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Anna-Maria Behnsen <anna-maria@linutronix.de>
---
v2: New in v2 (as suggested by Thomas)
---
include/asm-generic/delay.h | 64 +++++++++++++++++++++++++--------------------
1 file changed, 36 insertions(+), 28 deletions(-)
diff --git a/include/asm-generic/delay.h b/include/asm-generic/delay.h
index 70a1b20f3e1a..40d30dc2488b 100644
--- a/include/asm-generic/delay.h
+++ b/include/asm-generic/delay.h
@@ -2,6 +2,8 @@
#ifndef __ASM_GENERIC_DELAY_H
#define __ASM_GENERIC_DELAY_H
+#include <vdso/time64.h>
+
/* Undefined functions to get compile-time errors */
extern void __bad_udelay(void);
extern void __bad_ndelay(void);
@@ -12,13 +14,18 @@ extern void __const_udelay(unsigned long xloops);
extern void __delay(unsigned long loops);
/*
- * Implementation details:
- *
- * * The weird n/20000 thing suppresses a "comparison is always false due to
- * limited range of data type" warning with non-const 8-bit arguments.
- * * 0x10c7 is 2**32 / 1000000 (rounded up) -> udelay
- * * 0x5 is 2**32 / 1000000000 (rounded up) -> ndelay
+ * The microseconds/nanosecond delay multiplicators are used to convert a
+ * constant microseconds/nanoseconds value to a value which can be used by the
+ * architectures specific implementation to transform it into loops.
+ */
+#define UDELAY_CONST_MULT ((unsigned long)DIV_ROUND_UP(1ULL << 32, USEC_PER_SEC))
+#define NDELAY_CONST_MULT ((unsigned long)DIV_ROUND_UP(1ULL << 32, NSEC_PER_SEC))
+
+/*
+ * The maximum constant udelay/ndelay value picked out of thin air to prevent
+ * too long constant udelays/ndelays.
*/
+#define DELAY_CONST_MAX 20000
/**
* udelay - Inserting a delay based on microseconds with busy waiting
@@ -45,17 +52,17 @@ extern void __delay(unsigned long loops);
* #. cache behaviour affecting the time it takes to execute the loop function.
* #. CPU clock rate changes.
*/
-#define udelay(n) \
- ({ \
- if (__builtin_constant_p(n)) { \
- if ((n) / 20000 >= 1) \
- __bad_udelay(); \
- else \
- __const_udelay((n) * 0x10c7ul); \
- } else { \
- __udelay(n); \
- } \
- })
+static __always_inline void udelay(unsigned long usec)
+{
+ if (__builtin_constant_p(usec)) {
+ if (usec >= DELAY_CONST_MAX)
+ __bad_udelay();
+ else
+ __const_udelay(usec * UDELAY_CONST_MULT);
+ } else {
+ __udelay(usec);
+ }
+}
/**
* ndelay - Inserting a delay based on nanoseconds with busy waiting
@@ -63,16 +70,17 @@ extern void __delay(unsigned long loops);
*
* See udelay() for basic information about ndelay() and it's variants.
*/
-#define ndelay(n) \
- ({ \
- if (__builtin_constant_p(n)) { \
- if ((n) / 20000 >= 1) \
- __bad_ndelay(); \
- else \
- __const_udelay((n) * 5ul); \
- } else { \
- __ndelay(n); \
- } \
- })
+static __always_inline void ndelay(unsigned long nsec)
+{
+ if (__builtin_constant_p(nsec)) {
+ if (nsec >= DELAY_CONST_MAX)
+ __bad_udelay();
+ else
+ __const_udelay(nsec * NDELAY_CONST_MULT);
+ } else {
+ __udelay(nsec);
+ }
+}
+#define ndelay(x) ndelay(x)
#endif /* __ASM_GENERIC_DELAY_H */
--
2.39.2
^ permalink raw reply related [flat|nested] 47+ messages in thread
* [PATCH v2 07/15] timers: Adjust flseep() to reflect reality
2024-09-11 5:13 [PATCH v2 00/15] timers: Cleanup delay/sleep related mess Anna-Maria Behnsen
` (5 preceding siblings ...)
2024-09-11 5:13 ` [PATCH v2 06/15] delay: Rework udelay and ndelay Anna-Maria Behnsen
@ 2024-09-11 5:13 ` Anna-Maria Behnsen
2024-10-08 21:45 ` Frederic Weisbecker
2024-09-11 5:13 ` [PATCH v2 08/15] mm/damon/core: Use generic upper bound recommondation for usleep_range() Anna-Maria Behnsen
` (8 subsequent siblings)
15 siblings, 1 reply; 47+ messages in thread
From: Anna-Maria Behnsen @ 2024-09-11 5:13 UTC (permalink / raw)
To: Frederic Weisbecker, Thomas Gleixner, Jonathan Corbet
Cc: linux-kernel, Len Brown, Rafael J. Wysocki, Anna-Maria Behnsen,
Heiner Kallweit, David S. Miller
fsleep() simply implements the recommondations of the outdated
documentation in "Documentation/timers/timers-howto.rst". This should be a
user friendly interface to choose always the best timeout function
approach:
- udelay() for very short sleep durations shorter than 10 microseconds
- usleep_range() for sleep durations until 20 milliseconds
- msleep() for the others
The actual implementation has several problems:
- It does not take into account that HZ resolution also has an impact on
granularity of jiffies and has also an impact on the granularity of the
buckets of timer wheel levels. This means that accuracy for the timeout
does not have an upper limit. When executing fsleep(20000) on a HZ=100
system, the possible additional slack will be 50% as the granularity of
the buckets in the lowest level is 10 milliseconds.
- The upper limit of usleep_range() is twice the requested timeout. When no
other interrupts occur in this range, the maximum value is used. This
means that the requested sleep length has then an additional delay of
100%.
Change the thresholds for the decisions in fsleep() to make sure the
maximum slack which is added to the sleep duration is 25%.
Note: Outdated documentation will be updated in a followup patch.
Cc: Heiner Kallweit <hkallweit1@gmail.com>
Cc: David S. Miller <davem@davemloft.net>
Signed-off-by: Anna-Maria Behnsen <anna-maria@linutronix.de>
---
include/linux/delay.h | 29 +++++++++++++++++++++++++----
1 file changed, 25 insertions(+), 4 deletions(-)
diff --git a/include/linux/delay.h b/include/linux/delay.h
index 23623fa79768..b49a63c85c43 100644
--- a/include/linux/delay.h
+++ b/include/linux/delay.h
@@ -11,6 +11,7 @@
#include <linux/math.h>
#include <linux/sched.h>
+#include <linux/jiffies.h>
extern unsigned long loops_per_jiffy;
@@ -102,15 +103,35 @@ static inline void ssleep(unsigned int seconds)
msleep(seconds * 1000);
}
-/* see Documentation/timers/timers-howto.rst for the thresholds */
+static const unsigned int max_slack_shift = 2;
+#define USLEEP_RANGE_UPPER_BOUND ((TICK_NSEC << max_slack_shift) / NSEC_PER_USEC)
+
+/**
+ * fsleep - flexible sleep which autoselects the best mechanism
+ * @usecs: requested sleep duration in microseconds
+ *
+ * flseep() selects the best mechanism that will provide maximum 25% slack
+ * to the requested sleep duration. Therefore it uses:
+ *
+ * * udelay() loop for sleep durations <= 10 microseconds to avoid hrtimer
+ * overhead for really short sleep durations.
+ * * usleep_range() for sleep durations which would lead with the usage of
+ * msleep() to a slack larger than 25%. This depends on the granularity of
+ * jiffies.
+ * * msleep() for all other sleep durations.
+ *
+ * Note: When %CONFIG_HIGH_RES_TIMERS is not set, all sleeps are processed with
+ * the granularity of jiffies and the slack might exceed 25% especially for
+ * short sleep durations.
+ */
static inline void fsleep(unsigned long usecs)
{
if (usecs <= 10)
udelay(usecs);
- else if (usecs <= 20000)
- usleep_range(usecs, 2 * usecs);
+ else if (usecs < USLEEP_RANGE_UPPER_BOUND)
+ usleep_range(usecs, usecs + (usecs >> max_slack_shift));
else
- msleep(DIV_ROUND_UP(usecs, 1000));
+ msleep(DIV_ROUND_UP(usecs, USEC_PER_MSEC));
}
#endif /* defined(_LINUX_DELAY_H) */
--
2.39.2
^ permalink raw reply related [flat|nested] 47+ messages in thread
* [PATCH v2 08/15] mm/damon/core: Use generic upper bound recommondation for usleep_range()
2024-09-11 5:13 [PATCH v2 00/15] timers: Cleanup delay/sleep related mess Anna-Maria Behnsen
` (6 preceding siblings ...)
2024-09-11 5:13 ` [PATCH v2 07/15] timers: Adjust flseep() to reflect reality Anna-Maria Behnsen
@ 2024-09-11 5:13 ` Anna-Maria Behnsen
2024-10-09 12:01 ` Frederic Weisbecker
2024-09-11 5:13 ` [PATCH v2 09/15] timers: Add a warning to usleep_range_state() for wrong order of arguments Anna-Maria Behnsen
` (7 subsequent siblings)
15 siblings, 1 reply; 47+ messages in thread
From: Anna-Maria Behnsen @ 2024-09-11 5:13 UTC (permalink / raw)
To: Frederic Weisbecker, Thomas Gleixner, Jonathan Corbet
Cc: linux-kernel, Len Brown, Rafael J. Wysocki, Anna-Maria Behnsen,
SeongJae Park, Andrew Morton, damon, linux-mm
The upper bound for usleep_range_idle() was taken from the outdated
documentation. As a recommondation for the upper bound of usleep_range()
depends on HZ configuration it is not possible to hard code it.
Use the define "USLEEP_RANGE_UPPER_BOUND" instead.
Cc: SeongJae Park <sj@kernel.org>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: damon@lists.linux.dev
Cc: linux-mm@kvack.org
Signed-off-by: Anna-Maria Behnsen <anna-maria@linutronix.de>
Reviewed-by: SeongJae Park <sj@kernel.org>
---
mm/damon/core.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/mm/damon/core.c b/mm/damon/core.c
index 94fe2f1f9b0e..4b971871da75 100644
--- a/mm/damon/core.c
+++ b/mm/damon/core.c
@@ -1883,8 +1883,7 @@ static unsigned long damos_wmark_wait_us(struct damos *scheme)
static void kdamond_usleep(unsigned long usecs)
{
- /* See Documentation/timers/timers-howto.rst for the thresholds */
- if (usecs > 20 * USEC_PER_MSEC)
+ if (usecs >= USLEEP_RANGE_UPPER_BOUND)
schedule_timeout_idle(usecs_to_jiffies(usecs));
else
usleep_range_idle(usecs, usecs + 1);
--
2.39.2
^ permalink raw reply related [flat|nested] 47+ messages in thread
* [PATCH v2 09/15] timers: Add a warning to usleep_range_state() for wrong order of arguments
2024-09-11 5:13 [PATCH v2 00/15] timers: Cleanup delay/sleep related mess Anna-Maria Behnsen
` (7 preceding siblings ...)
2024-09-11 5:13 ` [PATCH v2 08/15] mm/damon/core: Use generic upper bound recommondation for usleep_range() Anna-Maria Behnsen
@ 2024-09-11 5:13 ` Anna-Maria Behnsen
2024-09-11 6:41 ` Joe Perches
2024-10-09 12:22 ` Frederic Weisbecker
2024-09-11 5:13 ` [PATCH v2 10/15] checkpatch: Remove broken sleep/delay related checks Anna-Maria Behnsen
` (6 subsequent siblings)
15 siblings, 2 replies; 47+ messages in thread
From: Anna-Maria Behnsen @ 2024-09-11 5:13 UTC (permalink / raw)
To: Frederic Weisbecker, Thomas Gleixner, Jonathan Corbet
Cc: linux-kernel, Len Brown, Rafael J. Wysocki, Anna-Maria Behnsen,
Andy Whitcroft, Joe Perches
There is a warning in checkpatch script that triggers, when min and max
arguments of usleep_range_state() are in reverse order. This check does
only cover callsites which uses constants. Move this check into the code as
a WARN_ON_ONCE() to also cover callsites not using constants and get rid of
it in checkpatch.
Cc: Andy Whitcroft <apw@canonical.com>
Cc: Joe Perches <joe@perches.com>
Signed-off-by: Anna-Maria Behnsen <anna-maria@linutronix.de>
---
kernel/time/sleep_timeout.c | 2 ++
scripts/checkpatch.pl | 4 ----
2 files changed, 2 insertions(+), 4 deletions(-)
diff --git a/kernel/time/sleep_timeout.c b/kernel/time/sleep_timeout.c
index 21f412350b15..4b805d7e1903 100644
--- a/kernel/time/sleep_timeout.c
+++ b/kernel/time/sleep_timeout.c
@@ -364,6 +364,8 @@ void __sched usleep_range_state(unsigned long min, unsigned long max, unsigned i
ktime_t exp = ktime_add_us(ktime_get(), min);
u64 delta = (u64)(max - min) * NSEC_PER_USEC;
+ WARN_ON_ONCE(max < min);
+
for (;;) {
__set_current_state(state);
/* Do not return before the requested sleep time has elapsed */
diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
index 39032224d504..ba3359bdd1fa 100755
--- a/scripts/checkpatch.pl
+++ b/scripts/checkpatch.pl
@@ -7088,10 +7088,6 @@ sub process {
if ($min eq $max) {
WARN("USLEEP_RANGE",
"usleep_range should not use min == max args; see Documentation/timers/timers-howto.rst\n" . "$here\n$stat\n");
- } elsif ($min =~ /^\d+$/ && $max =~ /^\d+$/ &&
- $min > $max) {
- WARN("USLEEP_RANGE",
- "usleep_range args reversed, use min then max; see Documentation/timers/timers-howto.rst\n" . "$here\n$stat\n");
}
}
--
2.39.2
^ permalink raw reply related [flat|nested] 47+ messages in thread
* [PATCH v2 10/15] checkpatch: Remove broken sleep/delay related checks
2024-09-11 5:13 [PATCH v2 00/15] timers: Cleanup delay/sleep related mess Anna-Maria Behnsen
` (8 preceding siblings ...)
2024-09-11 5:13 ` [PATCH v2 09/15] timers: Add a warning to usleep_range_state() for wrong order of arguments Anna-Maria Behnsen
@ 2024-09-11 5:13 ` Anna-Maria Behnsen
2024-09-11 6:44 ` Joe Perches
2024-10-09 12:45 ` Frederic Weisbecker
2024-09-11 5:13 ` [PATCH v2 11/15] regulator: core: Use fsleep() to get best sleep mechanism Anna-Maria Behnsen
` (5 subsequent siblings)
15 siblings, 2 replies; 47+ messages in thread
From: Anna-Maria Behnsen @ 2024-09-11 5:13 UTC (permalink / raw)
To: Frederic Weisbecker, Thomas Gleixner, Jonathan Corbet
Cc: linux-kernel, Len Brown, Rafael J. Wysocki, Anna-Maria Behnsen,
Andy Whitcroft, Joe Perches, Dwaipayan Ray
checkpatch.pl checks for several things related to sleep and delay
functions. In all warnings the outdated documentation is referenced. All
broken parts are listed one by one in the following with an explanation why
this check is broken. For a basic background of those functions please also
refere to the updated function descriptions of udelay(), nsleep_range() and
msleep().
Be aware: The change is done with a perl knowledge of the level "I'm able
to spell perl".
The following checks are broken:
- Check: (! ($delay < 10) )
Message: "usleep_range is preferred over udelay;
see Documentation/timers/timers-howto.rst\n"
Why is the check broken: When it is an atomic context, udelay() is
mandatory.
- Check: ($min eq $max)
Message: "usleep_range should not use min == max args;
see Documentation/timers/timers-howto.rst\n"
Why is the check broken: When the requested accuracy for the sleep
duration requires it, it is also valid to use
min == max.
- Check: ($delay > 2000)
Message: "long udelay - prefer mdelay;
see arch/arm/include/asm/delay.h\n"
Why is the check broken: The threshold when to start using mdelay() to
prevent an overflow depends on
MAX_UDELAY_MS. This value is architecture
dependent. The used value for the check and
reference is arm specific. Generic would be 5ms,
but this would "break" arm, loongarch and mips
and also the arm value might "break" mips and
loongarch in some configurations.
- Check: ($1 < 20)
Message: "msleep < 20ms can sleep for up to 20ms;
see Documentation/timers/timers-howto.rst\n"
Why is the check broken: msleep(1) might sleep up to 20ms but only on a
HZ=100 system. On a HZ=1000 system this will be
2ms. This means, the threshold cannot be hard
coded as it depends on HZ (jiffy granularity and
timer wheel bucket/level granularity) and also
on the required accuracy of the callsite. See
msleep() and also the USLEEP_RANGE_UPPER_BOUND
value.
Remove all broken checks. Update checkpatch documentation accordingly.
Cc: Andy Whitcroft <apw@canonical.com>
Cc: Joe Perches <joe@perches.com>
Cc: Dwaipayan Ray <dwaipayanray1@gmail.com>
Signed-off-by: Anna-Maria Behnsen <anna-maria@linutronix.de>
---
v2: Rephrase commit message
---
Documentation/dev-tools/checkpatch.rst | 6 ------
scripts/checkpatch.pl | 34 ----------------------------------
2 files changed, 40 deletions(-)
diff --git a/Documentation/dev-tools/checkpatch.rst b/Documentation/dev-tools/checkpatch.rst
index a9fac978a525..f5c27be9e673 100644
--- a/Documentation/dev-tools/checkpatch.rst
+++ b/Documentation/dev-tools/checkpatch.rst
@@ -466,12 +466,6 @@ API usage
**UAPI_INCLUDE**
No #include statements in include/uapi should use a uapi/ path.
- **USLEEP_RANGE**
- usleep_range() should be preferred over udelay(). The proper way of
- using usleep_range() is mentioned in the kernel docs.
-
- See: https://www.kernel.org/doc/html/latest/timers/timers-howto.html#delays-information-on-the-various-kernel-delay-sleep-mechanisms
-
Comments
--------
diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
index ba3359bdd1fa..80497da4aaac 100755
--- a/scripts/checkpatch.pl
+++ b/scripts/checkpatch.pl
@@ -6601,28 +6601,6 @@ sub process {
}
}
-# prefer usleep_range over udelay
- if ($line =~ /\budelay\s*\(\s*(\d+)\s*\)/) {
- my $delay = $1;
- # ignore udelay's < 10, however
- if (! ($delay < 10) ) {
- CHK("USLEEP_RANGE",
- "usleep_range is preferred over udelay; see Documentation/timers/timers-howto.rst\n" . $herecurr);
- }
- if ($delay > 2000) {
- WARN("LONG_UDELAY",
- "long udelay - prefer mdelay; see arch/arm/include/asm/delay.h\n" . $herecurr);
- }
- }
-
-# warn about unexpectedly long msleep's
- if ($line =~ /\bmsleep\s*\((\d+)\);/) {
- if ($1 < 20) {
- WARN("MSLEEP",
- "msleep < 20ms can sleep for up to 20ms; see Documentation/timers/timers-howto.rst\n" . $herecurr);
- }
- }
-
# check for comparisons of jiffies
if ($line =~ /\bjiffies\s*$Compare|$Compare\s*jiffies\b/) {
WARN("JIFFIES_COMPARISON",
@@ -7079,18 +7057,6 @@ sub process {
}
}
-# check usleep_range arguments
- if ($perl_version_ok &&
- defined $stat &&
- $stat =~ /^\+(?:.*?)\busleep_range\s*\(\s*($FuncArg)\s*,\s*($FuncArg)\s*\)/) {
- my $min = $1;
- my $max = $7;
- if ($min eq $max) {
- WARN("USLEEP_RANGE",
- "usleep_range should not use min == max args; see Documentation/timers/timers-howto.rst\n" . "$here\n$stat\n");
- }
- }
-
# check for naked sscanf
if ($perl_version_ok &&
defined $stat &&
--
2.39.2
^ permalink raw reply related [flat|nested] 47+ messages in thread
* [PATCH v2 11/15] regulator: core: Use fsleep() to get best sleep mechanism
2024-09-11 5:13 [PATCH v2 00/15] timers: Cleanup delay/sleep related mess Anna-Maria Behnsen
` (9 preceding siblings ...)
2024-09-11 5:13 ` [PATCH v2 10/15] checkpatch: Remove broken sleep/delay related checks Anna-Maria Behnsen
@ 2024-09-11 5:13 ` Anna-Maria Behnsen
2024-10-09 13:37 ` Frederic Weisbecker
2024-09-11 5:13 ` [PATCH v2 12/15] iopoll/regmap/phy/snd: Fix comment referencing outdated timer documentation Anna-Maria Behnsen
` (4 subsequent siblings)
15 siblings, 1 reply; 47+ messages in thread
From: Anna-Maria Behnsen @ 2024-09-11 5:13 UTC (permalink / raw)
To: Frederic Weisbecker, Thomas Gleixner, Jonathan Corbet
Cc: linux-kernel, Len Brown, Rafael J. Wysocki, Anna-Maria Behnsen,
Liam Girdwood, Mark Brown
_regulator_delay_helper() implements the recommondation of the outdated
documentation which sleep mechanism should be used. There is already a
function in place which does everything and also maps to reality called
fsleep().
Use fsleep() directly.
Cc: Liam Girdwood <lgirdwood@gmail.com>
Cc: Mark Brown <broonie@kernel.org>
Signed-off-by: Anna-Maria Behnsen <anna-maria@linutronix.de>
---
v2: Use fsleep() directly
---
drivers/regulator/core.c | 47 ++++-------------------------------------------
1 file changed, 4 insertions(+), 43 deletions(-)
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index 7674b7f2df14..5d4cfb14fada 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -2667,45 +2667,6 @@ static int regulator_ena_gpio_ctrl(struct regulator_dev *rdev, bool enable)
return 0;
}
-/**
- * _regulator_delay_helper - a delay helper function
- * @delay: time to delay in microseconds
- *
- * Delay for the requested amount of time as per the guidelines in:
- *
- * Documentation/timers/timers-howto.rst
- *
- * The assumption here is that these regulator operations will never used in
- * atomic context and therefore sleeping functions can be used.
- */
-static void _regulator_delay_helper(unsigned int delay)
-{
- unsigned int ms = delay / 1000;
- unsigned int us = delay % 1000;
-
- if (ms > 0) {
- /*
- * For small enough values, handle super-millisecond
- * delays in the usleep_range() call below.
- */
- if (ms < 20)
- us += ms * 1000;
- else
- msleep(ms);
- }
-
- /*
- * Give the scheduler some room to coalesce with any other
- * wakeup sources. For delays shorter than 10 us, don't even
- * bother setting up high-resolution timers and just busy-
- * loop.
- */
- if (us >= 10)
- usleep_range(us, us + 100);
- else
- udelay(us);
-}
-
/**
* _regulator_check_status_enabled
*
@@ -2760,7 +2721,7 @@ static int _regulator_do_enable(struct regulator_dev *rdev)
s64 remaining = ktime_us_delta(end, ktime_get_boottime());
if (remaining > 0)
- _regulator_delay_helper(remaining);
+ fsleep(remaining);
}
if (rdev->ena_pin) {
@@ -2794,7 +2755,7 @@ static int _regulator_do_enable(struct regulator_dev *rdev)
int time_remaining = delay;
while (time_remaining > 0) {
- _regulator_delay_helper(rdev->desc->poll_enabled_time);
+ fsleep(rdev->desc->poll_enabled_time);
if (rdev->desc->ops->get_status) {
ret = _regulator_check_status_enabled(rdev);
@@ -2813,7 +2774,7 @@ static int _regulator_do_enable(struct regulator_dev *rdev)
return -ETIMEDOUT;
}
} else {
- _regulator_delay_helper(delay);
+ fsleep(delay);
}
trace_regulator_enable_complete(rdev_get_name(rdev));
@@ -3741,7 +3702,7 @@ static int _regulator_do_set_voltage(struct regulator_dev *rdev,
}
/* Insert any necessary delays */
- _regulator_delay_helper(delay);
+ fsleep(delay);
if (best_val >= 0) {
unsigned long data = best_val;
--
2.39.2
^ permalink raw reply related [flat|nested] 47+ messages in thread
* [PATCH v2 12/15] iopoll/regmap/phy/snd: Fix comment referencing outdated timer documentation
2024-09-11 5:13 [PATCH v2 00/15] timers: Cleanup delay/sleep related mess Anna-Maria Behnsen
` (10 preceding siblings ...)
2024-09-11 5:13 ` [PATCH v2 11/15] regulator: core: Use fsleep() to get best sleep mechanism Anna-Maria Behnsen
@ 2024-09-11 5:13 ` Anna-Maria Behnsen
2024-09-11 12:08 ` Andrew Lunn
2024-10-09 16:14 ` Frederic Weisbecker
2024-09-11 5:13 ` [PATCH v2 13/15] powerpc/rtas: Use fsleep() to minimize additional sleep duration Anna-Maria Behnsen
` (3 subsequent siblings)
15 siblings, 2 replies; 47+ messages in thread
From: Anna-Maria Behnsen @ 2024-09-11 5:13 UTC (permalink / raw)
To: Frederic Weisbecker, Thomas Gleixner, Jonathan Corbet
Cc: linux-kernel, Len Brown, Rafael J. Wysocki, Anna-Maria Behnsen,
Andrew Lunn, Heiner Kallweit, Jaroslav Kysela, Takashi Iwai,
netdev, linux-sound
Function descriptions in iopoll.h, regmap.h, phy.h and sound/soc/sof/ops.h
copied all the same outdated documentation about sleep/delay function
limitations. In those comments, the generic (and still outdated) timer
documentation file is referenced.
As proper function descriptions for used delay and sleep functions are in
place, simply update the descriptions to reference to them. While at it fix
missing colon after "Returns" in function description and move return value
description to the end of the function description.
Cc: Andrew Lunn <andrew@lunn.ch>
Cc: Heiner Kallweit <hkallweit1@gmail.com>
Cc: Jaroslav Kysela <perex@perex.cz>
Cc: Takashi Iwai <tiwai@suse.com>
Cc: netdev@vger.kernel.org
Cc: linux-sound@vger.kernel.org
Signed-off-by: Anna-Maria Behnsen <anna-maria@linutronix.de>
---
v2: Add cleanup of usage of 'Returns' in function description
---
include/linux/iopoll.h | 52 +++++++++++++++++++++++++-------------------------
include/linux/phy.h | 9 +++++----
include/linux/regmap.h | 38 ++++++++++++++++++------------------
sound/soc/sof/ops.h | 8 ++++----
4 files changed, 54 insertions(+), 53 deletions(-)
diff --git a/include/linux/iopoll.h b/include/linux/iopoll.h
index 19a7b00baff4..91324c331a4b 100644
--- a/include/linux/iopoll.h
+++ b/include/linux/iopoll.h
@@ -19,19 +19,19 @@
* @op: accessor function (takes @args as its arguments)
* @val: Variable to read the value into
* @cond: Break condition (usually involving @val)
- * @sleep_us: Maximum time to sleep between reads in us (0
- * tight-loops). Should be less than ~20ms since usleep_range
- * is used (see Documentation/timers/timers-howto.rst).
+ * @sleep_us: Maximum time to sleep between reads in us (0 tight-loops). Please
+ * read usleep_range() function description for details and
+ * limitations.
* @timeout_us: Timeout in us, 0 means never timeout
* @sleep_before_read: if it is true, sleep @sleep_us before read.
* @args: arguments for @op poll
*
- * Returns 0 on success and -ETIMEDOUT upon a timeout. In either
- * case, the last read value at @args is stored in @val. Must not
- * be called from atomic context if sleep_us or timeout_us are used.
- *
* When available, you'll probably want to use one of the specialized
* macros defined below rather than this macro directly.
+ *
+ * Returns: 0 on success and -ETIMEDOUT upon a timeout. In either
+ * case, the last read value at @args is stored in @val. Must not
+ * be called from atomic context if sleep_us or timeout_us are used.
*/
#define read_poll_timeout(op, val, cond, sleep_us, timeout_us, \
sleep_before_read, args...) \
@@ -64,22 +64,22 @@
* @op: accessor function (takes @args as its arguments)
* @val: Variable to read the value into
* @cond: Break condition (usually involving @val)
- * @delay_us: Time to udelay between reads in us (0 tight-loops). Should
- * be less than ~10us since udelay is used (see
- * Documentation/timers/timers-howto.rst).
+ * @delay_us: Time to udelay between reads in us (0 tight-loops). Please
+ * read udelay() function description for details and
+ * limitations.
* @timeout_us: Timeout in us, 0 means never timeout
* @delay_before_read: if it is true, delay @delay_us before read.
* @args: arguments for @op poll
*
- * Returns 0 on success and -ETIMEDOUT upon a timeout. In either
- * case, the last read value at @args is stored in @val.
- *
* This macro does not rely on timekeeping. Hence it is safe to call even when
* timekeeping is suspended, at the expense of an underestimation of wall clock
* time, which is rather minimal with a non-zero delay_us.
*
* When available, you'll probably want to use one of the specialized
* macros defined below rather than this macro directly.
+ *
+ * Returns: 0 on success and -ETIMEDOUT upon a timeout. In either
+ * case, the last read value at @args is stored in @val.
*/
#define read_poll_timeout_atomic(op, val, cond, delay_us, timeout_us, \
delay_before_read, args...) \
@@ -119,17 +119,17 @@
* @addr: Address to poll
* @val: Variable to read the value into
* @cond: Break condition (usually involving @val)
- * @sleep_us: Maximum time to sleep between reads in us (0
- * tight-loops). Should be less than ~20ms since usleep_range
- * is used (see Documentation/timers/timers-howto.rst).
+ * @sleep_us: Maximum time to sleep between reads in us (0 tight-loops). Please
+ * read usleep_range() function description for details and
+ * limitations.
* @timeout_us: Timeout in us, 0 means never timeout
*
- * Returns 0 on success and -ETIMEDOUT upon a timeout. In either
- * case, the last read value at @addr is stored in @val. Must not
- * be called from atomic context if sleep_us or timeout_us are used.
- *
* When available, you'll probably want to use one of the specialized
* macros defined below rather than this macro directly.
+ *
+ * Returns: 0 on success and -ETIMEDOUT upon a timeout. In either
+ * case, the last read value at @addr is stored in @val. Must not
+ * be called from atomic context if sleep_us or timeout_us are used.
*/
#define readx_poll_timeout(op, addr, val, cond, sleep_us, timeout_us) \
read_poll_timeout(op, val, cond, sleep_us, timeout_us, false, addr)
@@ -140,16 +140,16 @@
* @addr: Address to poll
* @val: Variable to read the value into
* @cond: Break condition (usually involving @val)
- * @delay_us: Time to udelay between reads in us (0 tight-loops). Should
- * be less than ~10us since udelay is used (see
- * Documentation/timers/timers-howto.rst).
+ * @delay_us: Time to udelay between reads in us (0 tight-loops). Please
+ * read udelay() function description for details and
+ * limitations.
* @timeout_us: Timeout in us, 0 means never timeout
*
- * Returns 0 on success and -ETIMEDOUT upon a timeout. In either
- * case, the last read value at @addr is stored in @val.
- *
* When available, you'll probably want to use one of the specialized
* macros defined below rather than this macro directly.
+ *
+ * Returns: 0 on success and -ETIMEDOUT upon a timeout. In either
+ * case, the last read value at @addr is stored in @val.
*/
#define readx_poll_timeout_atomic(op, addr, val, cond, delay_us, timeout_us) \
read_poll_timeout_atomic(op, val, cond, delay_us, timeout_us, false, addr)
diff --git a/include/linux/phy.h b/include/linux/phy.h
index 6b7d40d49129..cadf51441ee1 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -1374,12 +1374,13 @@ int phy_read_mmd(struct phy_device *phydev, int devad, u32 regnum);
* @regnum: The register on the MMD to read
* @val: Variable to read the register into
* @cond: Break condition (usually involving @val)
- * @sleep_us: Maximum time to sleep between reads in us (0
- * tight-loops). Should be less than ~20ms since usleep_range
- * is used (see Documentation/timers/timers-howto.rst).
+ * @sleep_us: Maximum time to sleep between reads in us (0 tight-loops). Please
+ * read usleep_range() function description for details and
+ * limitations.
* @timeout_us: Timeout in us, 0 means never timeout
* @sleep_before_read: if it is true, sleep @sleep_us before read.
- * Returns 0 on success and -ETIMEDOUT upon a timeout. In either
+ *
+ * Returns: 0 on success and -ETIMEDOUT upon a timeout. In either
* case, the last read value at @args is stored in @val. Must not
* be called from atomic context if sleep_us or timeout_us are used.
*/
diff --git a/include/linux/regmap.h b/include/linux/regmap.h
index 122e38161acb..d733b08466fd 100644
--- a/include/linux/regmap.h
+++ b/include/linux/regmap.h
@@ -106,17 +106,17 @@ struct reg_sequence {
* @addr: Address to poll
* @val: Unsigned integer variable to read the value into
* @cond: Break condition (usually involving @val)
- * @sleep_us: Maximum time to sleep between reads in us (0
- * tight-loops). Should be less than ~20ms since usleep_range
- * is used (see Documentation/timers/timers-howto.rst).
+ * @sleep_us: Maximum time to sleep between reads in us (0 tight-loops). Please
+ * read usleep_range() function description for details and
+ * limitations.
* @timeout_us: Timeout in us, 0 means never timeout
*
- * Returns 0 on success and -ETIMEDOUT upon a timeout or the regmap_read
+ * This is modelled after the readx_poll_timeout macros in linux/iopoll.h.
+ *
+ * Returns: 0 on success and -ETIMEDOUT upon a timeout or the regmap_read
* error return value in case of a error read. In the two former cases,
* the last read value at @addr is stored in @val. Must not be called
* from atomic context if sleep_us or timeout_us are used.
- *
- * This is modelled after the readx_poll_timeout macros in linux/iopoll.h.
*/
#define regmap_read_poll_timeout(map, addr, val, cond, sleep_us, timeout_us) \
({ \
@@ -133,20 +133,20 @@ struct reg_sequence {
* @addr: Address to poll
* @val: Unsigned integer variable to read the value into
* @cond: Break condition (usually involving @val)
- * @delay_us: Time to udelay between reads in us (0 tight-loops).
- * Should be less than ~10us since udelay is used
- * (see Documentation/timers/timers-howto.rst).
+ * @delay_us: Time to udelay between reads in us (0 tight-loops). Please
+ * read udelay() function description for details and
+ * limitations.
* @timeout_us: Timeout in us, 0 means never timeout
*
- * Returns 0 on success and -ETIMEDOUT upon a timeout or the regmap_read
- * error return value in case of a error read. In the two former cases,
- * the last read value at @addr is stored in @val.
- *
* This is modelled after the readx_poll_timeout_atomic macros in linux/iopoll.h.
*
* Note: In general regmap cannot be used in atomic context. If you want to use
* this macro then first setup your regmap for atomic use (flat or no cache
* and MMIO regmap).
+ *
+ * Returns: 0 on success and -ETIMEDOUT upon a timeout or the regmap_read
+ * error return value in case of a error read. In the two former cases,
+ * the last read value at @addr is stored in @val.
*/
#define regmap_read_poll_timeout_atomic(map, addr, val, cond, delay_us, timeout_us) \
({ \
@@ -177,17 +177,17 @@ struct reg_sequence {
* @field: Regmap field to read from
* @val: Unsigned integer variable to read the value into
* @cond: Break condition (usually involving @val)
- * @sleep_us: Maximum time to sleep between reads in us (0
- * tight-loops). Should be less than ~20ms since usleep_range
- * is used (see Documentation/timers/timers-howto.rst).
+ * @sleep_us: Maximum time to sleep between reads in us (0 tight-loops). Please
+ * read usleep_range() function description for details and
+ * limitations.
* @timeout_us: Timeout in us, 0 means never timeout
*
- * Returns 0 on success and -ETIMEDOUT upon a timeout or the regmap_field_read
+ * This is modelled after the readx_poll_timeout macros in linux/iopoll.h.
+ *
+ * Returns: 0 on success and -ETIMEDOUT upon a timeout or the regmap_field_read
* error return value in case of a error read. In the two former cases,
* the last read value at @addr is stored in @val. Must not be called
* from atomic context if sleep_us or timeout_us are used.
- *
- * This is modelled after the readx_poll_timeout macros in linux/iopoll.h.
*/
#define regmap_field_read_poll_timeout(field, val, cond, sleep_us, timeout_us) \
({ \
diff --git a/sound/soc/sof/ops.h b/sound/soc/sof/ops.h
index 2584621c3b2d..d73644e85b6e 100644
--- a/sound/soc/sof/ops.h
+++ b/sound/soc/sof/ops.h
@@ -597,12 +597,12 @@ snd_sof_is_chain_dma_supported(struct snd_sof_dev *sdev, u32 dai_type)
* @addr: Address to poll
* @val: Variable to read the value into
* @cond: Break condition (usually involving @val)
- * @sleep_us: Maximum time to sleep between reads in us (0
- * tight-loops). Should be less than ~20ms since usleep_range
- * is used (see Documentation/timers/timers-howto.rst).
+ * @sleep_us: Maximum time to sleep between reads in us (0 tight-loops). Please
+ * read usleep_range() function description for details and
+ * limitations.
* @timeout_us: Timeout in us, 0 means never timeout
*
- * Returns 0 on success and -ETIMEDOUT upon a timeout. In either
+ * Returns: 0 on success and -ETIMEDOUT upon a timeout. In either
* case, the last read value at @addr is stored in @val. Must not
* be called from atomic context if sleep_us or timeout_us are used.
*
--
2.39.2
^ permalink raw reply related [flat|nested] 47+ messages in thread
* [PATCH v2 13/15] powerpc/rtas: Use fsleep() to minimize additional sleep duration
2024-09-11 5:13 [PATCH v2 00/15] timers: Cleanup delay/sleep related mess Anna-Maria Behnsen
` (11 preceding siblings ...)
2024-09-11 5:13 ` [PATCH v2 12/15] iopoll/regmap/phy/snd: Fix comment referencing outdated timer documentation Anna-Maria Behnsen
@ 2024-09-11 5:13 ` Anna-Maria Behnsen
2024-10-09 16:20 ` Frederic Weisbecker
2024-09-11 5:13 ` [PATCH v2 14/15] media: anysee: Fix link to outdated sleep function documentation Anna-Maria Behnsen
` (2 subsequent siblings)
15 siblings, 1 reply; 47+ messages in thread
From: Anna-Maria Behnsen @ 2024-09-11 5:13 UTC (permalink / raw)
To: Frederic Weisbecker, Thomas Gleixner, Jonathan Corbet
Cc: linux-kernel, Len Brown, Rafael J. Wysocki, Anna-Maria Behnsen,
Michael Ellerman, Nathan Lynch, linuxppc-dev
When commit 38f7b7067dae ("powerpc/rtas: rtas_busy_delay() improvements")
was introduced, documentation about proper usage of sleep realted functions
was outdated.
The commit message references the usage of a HZ=100 system. When using a
20ms sleep duration on such a system and therefore using msleep(), the
possible additional slack will be +10ms.
When the system is configured with HZ=100 the granularity of a jiffy and of
a bucket of the lowest timer wheel level is 10ms. To make sure a timer will
not expire early (when queueing of the timer races with an concurrent
update of jiffies), timers are always queued into the next bucket. This is
the reason for the maximal possible slack of 10ms.
fsleep() limits the maximal possible slack to 25% by making threshold
between usleep_range() and msleep() HZ dependent. As soon as the accuracy
of msleep() is sufficient, the less expensive timer list timer based
sleeping function is used instead of the more expensive hrtimer based
usleep_range() function. The udelay() will not be used in this specific
usecase as the lowest sleep length is larger than 1 microsecond.
Use fsleep() directly instead of using an own heuristic for the best
sleeping mechanism to use..
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: Nathan Lynch <nathanl@linux.ibm.com>
Cc: linuxppc-dev@lists.ozlabs.org
Signed-off-by: Anna-Maria Behnsen <anna-maria@linutronix.de>
Acked-by: Michael Ellerman <mpe@ellerman.id.au> (powerpc)
---
v2: fix typos
---
arch/powerpc/kernel/rtas.c | 21 +++++++--------------
1 file changed, 7 insertions(+), 14 deletions(-)
diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c
index f7e86e09c49f..d31c9799cab2 100644
--- a/arch/powerpc/kernel/rtas.c
+++ b/arch/powerpc/kernel/rtas.c
@@ -1390,21 +1390,14 @@ bool __ref rtas_busy_delay(int status)
*/
ms = clamp(ms, 1U, 1000U);
/*
- * The delay hint is an order-of-magnitude suggestion, not
- * a minimum. It is fine, possibly even advantageous, for
- * us to pause for less time than hinted. For small values,
- * use usleep_range() to ensure we don't sleep much longer
- * than actually needed.
- *
- * See Documentation/timers/timers-howto.rst for
- * explanation of the threshold used here. In effect we use
- * usleep_range() for 9900 and 9901, msleep() for
- * 9902-9905.
+ * The delay hint is an order-of-magnitude suggestion, not a
+ * minimum. It is fine, possibly even advantageous, for us to
+ * pause for less time than hinted. To make sure pause time will
+ * not be way longer than requested independent of HZ
+ * configuration, use fsleep(). See fsleep() for details of
+ * used sleeping functions.
*/
- if (ms <= 20)
- usleep_range(ms * 100, ms * 1000);
- else
- msleep(ms);
+ fsleep(ms * 1000);
break;
case RTAS_BUSY:
ret = true;
--
2.39.2
^ permalink raw reply related [flat|nested] 47+ messages in thread
* [PATCH v2 14/15] media: anysee: Fix link to outdated sleep function documentation
2024-09-11 5:13 [PATCH v2 00/15] timers: Cleanup delay/sleep related mess Anna-Maria Behnsen
` (12 preceding siblings ...)
2024-09-11 5:13 ` [PATCH v2 13/15] powerpc/rtas: Use fsleep() to minimize additional sleep duration Anna-Maria Behnsen
@ 2024-09-11 5:13 ` Anna-Maria Behnsen
2024-10-09 16:30 ` Frederic Weisbecker
2024-09-11 5:13 ` [PATCH v2 15/15] timers/Documentation: Cleanup delay/sleep documentation Anna-Maria Behnsen
2024-09-16 20:20 ` [PATCH v2 00/15] timers: Cleanup delay/sleep related mess Christophe JAILLET
15 siblings, 1 reply; 47+ messages in thread
From: Anna-Maria Behnsen @ 2024-09-11 5:13 UTC (permalink / raw)
To: Frederic Weisbecker, Thomas Gleixner, Jonathan Corbet
Cc: linux-kernel, Len Brown, Rafael J. Wysocki, Anna-Maria Behnsen,
Mauro Carvalho Chehab, linux-media
The TODO FIXME comment references the outdated lower limit for msleep()
function of 20ms. As this is not right and the proper documentation of
msleep() is now part of the function description, remove the old stuff and
point to the up to date documentation.
Cc: Mauro Carvalho Chehab <mchehab@kernel.org>
Cc: linux-media@vger.kernel.org
Signed-off-by: Anna-Maria Behnsen <anna-maria@linutronix.de>
---
drivers/media/usb/dvb-usb-v2/anysee.c | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/drivers/media/usb/dvb-usb-v2/anysee.c b/drivers/media/usb/dvb-usb-v2/anysee.c
index 8699846eb416..b2f5db961245 100644
--- a/drivers/media/usb/dvb-usb-v2/anysee.c
+++ b/drivers/media/usb/dvb-usb-v2/anysee.c
@@ -55,10 +55,8 @@ static int anysee_ctrl_msg(struct dvb_usb_device *d,
/* TODO FIXME: dvb_usb_generic_rw() fails rarely with error code -32
* (EPIPE, Broken pipe). Function supports currently msleep() as a
- * parameter but I would not like to use it, since according to
- * Documentation/timers/timers-howto.rst it should not be used such
- * short, under < 20ms, sleeps. Repeating failed message would be
- * better choice as not to add unwanted delays...
+ * parameter. Check msleep() for details. Repeating failed message would
+ * be better choice as not to add unwanted delays...
* Fixing that correctly is one of those or both;
* 1) use repeat if possible
* 2) add suitable delay
--
2.39.2
^ permalink raw reply related [flat|nested] 47+ messages in thread
* [PATCH v2 15/15] timers/Documentation: Cleanup delay/sleep documentation
2024-09-11 5:13 [PATCH v2 00/15] timers: Cleanup delay/sleep related mess Anna-Maria Behnsen
` (13 preceding siblings ...)
2024-09-11 5:13 ` [PATCH v2 14/15] media: anysee: Fix link to outdated sleep function documentation Anna-Maria Behnsen
@ 2024-09-11 5:13 ` Anna-Maria Behnsen
2024-10-10 13:10 ` Frederic Weisbecker
2024-09-16 20:20 ` [PATCH v2 00/15] timers: Cleanup delay/sleep related mess Christophe JAILLET
15 siblings, 1 reply; 47+ messages in thread
From: Anna-Maria Behnsen @ 2024-09-11 5:13 UTC (permalink / raw)
To: Frederic Weisbecker, Thomas Gleixner, Jonathan Corbet
Cc: linux-kernel, Len Brown, Rafael J. Wysocki, Anna-Maria Behnsen
The documentation which tries to give advises how to properly inserting
delays or sleeps is outdated. The file name is 'timers-howto.rst' which
might be missleading as it is only about delay and sleep mechanisms and not
how to use timers.
Update the documentation by integrating the important parts from the
related function descriptions and move it all into a self explaining file
with the name "delay_sleep_functions.rst".
Signed-off-by: Anna-Maria Behnsen <anna-maria@linutronix.de>
---
Documentation/timers/delay_sleep_functions.rst | 122 +++++++++++++++++++++++++
Documentation/timers/index.rst | 2 +-
Documentation/timers/timers-howto.rst | 115 -----------------------
3 files changed, 123 insertions(+), 116 deletions(-)
diff --git a/Documentation/timers/delay_sleep_functions.rst b/Documentation/timers/delay_sleep_functions.rst
new file mode 100644
index 000000000000..05d7c3c8fbe8
--- /dev/null
+++ b/Documentation/timers/delay_sleep_functions.rst
@@ -0,0 +1,122 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+Delay and sleep mechanisms
+==========================
+
+This document seeks to answer the common question: "What is the
+RightWay (TM) to insert a delay?"
+
+This question is most often faced by driver writers who have to
+deal with hardware delays and who may not be the most intimately
+familiar with the inner workings of the Linux Kernel.
+
+The following table gives a rough overview about the existing function
+'families' and their limitations. This overview table does not replace the
+reading of the function description before usage!
+
+.. list-table::
+ :widths: 20 20 20 20 20
+ :header-rows: 2
+
+ * -
+ - `*delay()`
+ - `usleep_range*()`
+ - `*sleep()`
+ - `fsleep()`
+ * -
+ - busy-wait loop
+ - hrtimers based
+ - timer list timers based
+ - combines the others
+ * - Usage in atomic Context
+ - yes
+ - no
+ - no
+ - no
+ * - precise on "short intervals"
+ - yes
+ - yes
+ - depends
+ - yes
+ * - precise on "long intervals"
+ - Do not use!
+ - yes
+ - max 12.5% slack
+ - yes
+ * - interruptible variant
+ - no
+ - yes
+ - yes
+ - no
+
+A generic advice for non atomic contexts could be:
+
+#. Use `fsleep()` whenever unsure (as it combines all the advantages of the
+ others)
+#. Use `*sleep()` whenever possible
+#. Use `usleep_range*()` whenever accuracy of `*sleep()` is not sufficient
+#. Use `*delay()` for very, very short delays
+
+Find some more detailed information about the function 'families' in the next
+sections.
+
+`*delay()` family of functions
+------------------------------
+
+These functions use the jiffy estimation of clock speed and will busy wait for
+enough loop cycles to achieve the desired delay. udelay() is the basic
+implementation and ndelay() as well as mdelay() are variants.
+
+These functions are mainly used to add a delay in atomic context. Please make
+sure to ask yourself before adding a delay in atomic context: Is this really
+required?
+
+.. kernel-doc:: include/asm-generic/delay.h
+ :identifiers: udelay ndelay
+
+.. kernel-doc:: include/linux/delay.h
+ :identifiers: mdelay
+
+
+`usleep_range*()` and `*sleep()` family of functions
+----------------------------------------------------
+
+These functions uses hrtimers or timer list timers to provide the requested
+sleeping duration. For a decision which function is the right one to use, take
+some basic information into account:
+
+#. hrtimers are more expensive as they are using an rb-tree (instead of hashing)
+#. hrtimers are more expensive when the requested sleeping duration is the first
+ timer which means real hardware has to be programmed
+#. timer list timers always providing some sort of slack as they are jiffy
+ based
+
+The generic advice is repeated here:
+
+#. Use `fsleep()` whenever unsure (as it combines all the advantages of the
+ others)
+#. Use `*sleep()` whenever possible
+#. Use `usleep_range*()` whenever accuracy of `*sleep()` is not sufficient
+
+First check fsleep() function description and to learn more about accuracy,
+please check msleep() function description.
+
+
+`usleep_range*()`
+~~~~~~~~~~~~~~~~~
+
+.. kernel-doc:: include/linux/delay.h
+ :identifiers: usleep_range usleep_range_idle
+
+.. kernel-doc:: kernel/time/sleep_timeout.c
+ :identifiers: usleep_range_state
+
+
+`*sleep()`
+~~~~~~~~~~
+
+.. kernel-doc:: kernel/time/sleep_timeout.c
+ :identifiers: msleep msleep_interruptible
+
+.. kernel-doc:: include/linux/delay.h
+ :identifiers: ssleep fsleep
diff --git a/Documentation/timers/index.rst b/Documentation/timers/index.rst
index 983f91f8f023..4e88116e4dcf 100644
--- a/Documentation/timers/index.rst
+++ b/Documentation/timers/index.rst
@@ -12,7 +12,7 @@ Timers
hrtimers
no_hz
timekeeping
- timers-howto
+ delay_sleep_functions
.. only:: subproject and html
diff --git a/Documentation/timers/timers-howto.rst b/Documentation/timers/timers-howto.rst
deleted file mode 100644
index ef7a4652ccc9..000000000000
--- a/Documentation/timers/timers-howto.rst
+++ /dev/null
@@ -1,115 +0,0 @@
-===================================================================
-delays - Information on the various kernel delay / sleep mechanisms
-===================================================================
-
-This document seeks to answer the common question: "What is the
-RightWay (TM) to insert a delay?"
-
-This question is most often faced by driver writers who have to
-deal with hardware delays and who may not be the most intimately
-familiar with the inner workings of the Linux Kernel.
-
-
-Inserting Delays
-----------------
-
-The first, and most important, question you need to ask is "Is my
-code in an atomic context?" This should be followed closely by "Does
-it really need to delay in atomic context?" If so...
-
-ATOMIC CONTEXT:
- You must use the `*delay` family of functions. These
- functions use the jiffy estimation of clock speed
- and will busy wait for enough loop cycles to achieve
- the desired delay:
-
- ndelay(unsigned long nsecs)
- udelay(unsigned long usecs)
- mdelay(unsigned long msecs)
-
- udelay is the generally preferred API; ndelay-level
- precision may not actually exist on many non-PC devices.
-
- mdelay is macro wrapper around udelay, to account for
- possible overflow when passing large arguments to udelay.
- In general, use of mdelay is discouraged and code should
- be refactored to allow for the use of msleep.
-
-NON-ATOMIC CONTEXT:
- You should use the `*sleep[_range]` family of functions.
- There are a few more options here, while any of them may
- work correctly, using the "right" sleep function will
- help the scheduler, power management, and just make your
- driver better :)
-
- -- Backed by busy-wait loop:
-
- udelay(unsigned long usecs)
-
- -- Backed by hrtimers:
-
- usleep_range(unsigned long min, unsigned long max)
-
- -- Backed by jiffies / legacy_timers
-
- msleep(unsigned long msecs)
- msleep_interruptible(unsigned long msecs)
-
- Unlike the `*delay` family, the underlying mechanism
- driving each of these calls varies, thus there are
- quirks you should be aware of.
-
-
- SLEEPING FOR "A FEW" USECS ( < ~10us? ):
- * Use udelay
-
- - Why not usleep?
- On slower systems, (embedded, OR perhaps a speed-
- stepped PC!) the overhead of setting up the hrtimers
- for usleep *may* not be worth it. Such an evaluation
- will obviously depend on your specific situation, but
- it is something to be aware of.
-
- SLEEPING FOR ~USECS OR SMALL MSECS ( 10us - 20ms):
- * Use usleep_range
-
- - Why not msleep for (1ms - 20ms)?
- Explained originally here:
- https://lore.kernel.org/r/15327.1186166232@lwn.net
-
- msleep(1~20) may not do what the caller intends, and
- will often sleep longer (~20 ms actual sleep for any
- value given in the 1~20ms range). In many cases this
- is not the desired behavior.
-
- - Why is there no "usleep" / What is a good range?
- Since usleep_range is built on top of hrtimers, the
- wakeup will be very precise (ish), thus a simple
- usleep function would likely introduce a large number
- of undesired interrupts.
-
- With the introduction of a range, the scheduler is
- free to coalesce your wakeup with any other wakeup
- that may have happened for other reasons, or at the
- worst case, fire an interrupt for your upper bound.
-
- The larger a range you supply, the greater a chance
- that you will not trigger an interrupt; this should
- be balanced with what is an acceptable upper bound on
- delay / performance for your specific code path. Exact
- tolerances here are very situation specific, thus it
- is left to the caller to determine a reasonable range.
-
- SLEEPING FOR LARGER MSECS ( 10ms+ )
- * Use msleep or possibly msleep_interruptible
-
- - What's the difference?
- msleep sets the current task to TASK_UNINTERRUPTIBLE
- whereas msleep_interruptible sets the current task to
- TASK_INTERRUPTIBLE before scheduling the sleep. In
- short, the difference is whether the sleep can be ended
- early by a signal. In general, just use msleep unless
- you know you have a need for the interruptible variant.
-
- FLEXIBLE SLEEPING (any delay, uninterruptible)
- * Use fsleep
--
2.39.2
^ permalink raw reply related [flat|nested] 47+ messages in thread
* Re: [PATCH v2 09/15] timers: Add a warning to usleep_range_state() for wrong order of arguments
2024-09-11 5:13 ` [PATCH v2 09/15] timers: Add a warning to usleep_range_state() for wrong order of arguments Anna-Maria Behnsen
@ 2024-09-11 6:41 ` Joe Perches
2024-09-11 7:45 ` Anna-Maria Behnsen
2024-10-09 12:22 ` Frederic Weisbecker
1 sibling, 1 reply; 47+ messages in thread
From: Joe Perches @ 2024-09-11 6:41 UTC (permalink / raw)
To: Anna-Maria Behnsen, Frederic Weisbecker, Thomas Gleixner,
Jonathan Corbet
Cc: linux-kernel, Len Brown, Rafael J. Wysocki, Andy Whitcroft
On Wed, 2024-09-11 at 07:13 +0200, Anna-Maria Behnsen wrote:
> There is a warning in checkpatch script that triggers, when min and max
> arguments of usleep_range_state() are in reverse order. This check does
> only cover callsites which uses constants. Move this check into the code as
> a WARN_ON_ONCE() to also cover callsites not using constants and get rid of
> it in checkpatch.
I don't disagree that a runtime test is useful
and relatively cost free.
But checkpatch is for patches.
There's no reason as far as I can tell to remove
this source code test.
Why make the test runtime only?
>
> Cc: Andy Whitcroft <apw@canonical.com>
> Cc: Joe Perches <joe@perches.com>
> Signed-off-by: Anna-Maria Behnsen <anna-maria@linutronix.de>
> ---
> kernel/time/sleep_timeout.c | 2 ++
> scripts/checkpatch.pl | 4 ----
> 2 files changed, 2 insertions(+), 4 deletions(-)
>
> diff --git a/kernel/time/sleep_timeout.c b/kernel/time/sleep_timeout.c
> index 21f412350b15..4b805d7e1903 100644
> --- a/kernel/time/sleep_timeout.c
> +++ b/kernel/time/sleep_timeout.c
> @@ -364,6 +364,8 @@ void __sched usleep_range_state(unsigned long min, unsigned long max, unsigned i
> ktime_t exp = ktime_add_us(ktime_get(), min);
> u64 delta = (u64)(max - min) * NSEC_PER_USEC;
>
> + WARN_ON_ONCE(max < min);
> +
> for (;;) {
> __set_current_state(state);
> /* Do not return before the requested sleep time has elapsed */
> diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
> index 39032224d504..ba3359bdd1fa 100755
> --- a/scripts/checkpatch.pl
> +++ b/scripts/checkpatch.pl
> @@ -7088,10 +7088,6 @@ sub process {
> if ($min eq $max) {
> WARN("USLEEP_RANGE",
> "usleep_range should not use min == max args; see Documentation/timers/timers-howto.rst\n" . "$here\n$stat\n");
> - } elsif ($min =~ /^\d+$/ && $max =~ /^\d+$/ &&
> - $min > $max) {
> - WARN("USLEEP_RANGE",
> - "usleep_range args reversed, use min then max; see Documentation/timers/timers-howto.rst\n" . "$here\n$stat\n");
> }
> }
>
>
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: [PATCH v2 10/15] checkpatch: Remove broken sleep/delay related checks
2024-09-11 5:13 ` [PATCH v2 10/15] checkpatch: Remove broken sleep/delay related checks Anna-Maria Behnsen
@ 2024-09-11 6:44 ` Joe Perches
2024-09-11 7:41 ` Anna-Maria Behnsen
2024-10-09 12:45 ` Frederic Weisbecker
1 sibling, 1 reply; 47+ messages in thread
From: Joe Perches @ 2024-09-11 6:44 UTC (permalink / raw)
To: Anna-Maria Behnsen, Frederic Weisbecker, Thomas Gleixner,
Jonathan Corbet
Cc: linux-kernel, Len Brown, Rafael J. Wysocki, Andy Whitcroft,
Dwaipayan Ray
On Wed, 2024-09-11 at 07:13 +0200, Anna-Maria Behnsen wrote:
> checkpatch.pl checks for several things related to sleep and delay
> functions. In all warnings the outdated documentation is referenced. All
> broken parts are listed one by one in the following with an explanation why
> this check is broken. For a basic background of those functions please also
> refere to the updated function descriptions of udelay(), nsleep_range() and
> msleep().
>
> Be aware: The change is done with a perl knowledge of the level "I'm able
> to spell perl".
>
> The following checks are broken:
>
> - Check: (! ($delay < 10) )
> Message: "usleep_range is preferred over udelay;
> see Documentation/timers/timers-howto.rst\n"
> Why is the check broken: When it is an atomic context, udelay() is
> mandatory.
>
> - Check: ($min eq $max)
> Message: "usleep_range should not use min == max args;
> see Documentation/timers/timers-howto.rst\n"
> Why is the check broken: When the requested accuracy for the sleep
> duration requires it, it is also valid to use
> min == max.
There is a runtime setup cost to use usleep_range.
I believe udelay should generally be used when there
is a specific microsecond time delay required.
>
> - Check: ($delay > 2000)
> Message: "long udelay - prefer mdelay;
> see arch/arm/include/asm/delay.h\n"
> Why is the check broken: The threshold when to start using mdelay() to
> prevent an overflow depends on
> MAX_UDELAY_MS. This value is architecture
> dependent. The used value for the check and
> reference is arm specific. Generic would be 5ms,
> but this would "break" arm, loongarch and mips
> and also the arm value might "break" mips and
> loongarch in some configurations.
It likely won't "break", just perhaps be inefficient.
> - Check: ($1 < 20)
> Message: "msleep < 20ms can sleep for up to 20ms;
> see Documentation/timers/timers-howto.rst\n"
> Why is the check broken: msleep(1) might sleep up to 20ms but only on a
> HZ=100 system. On a HZ=1000 system this will be
> 2ms. This means, the threshold cannot be hard
> coded as it depends on HZ (jiffy granularity and
> timer wheel bucket/level granularity) and also
> on the required accuracy of the callsite. See
> msleep() and also the USLEEP_RANGE_UPPER_BOUND
> value.
>
> Remove all broken checks. Update checkpatch documentation accordingly.
>
> Cc: Andy Whitcroft <apw@canonical.com>
> Cc: Joe Perches <joe@perches.com>
> Cc: Dwaipayan Ray <dwaipayanray1@gmail.com>
> Signed-off-by: Anna-Maria Behnsen <anna-maria@linutronix.de>
> ---
> v2: Rephrase commit message
> ---
> Documentation/dev-tools/checkpatch.rst | 6 ------
> scripts/checkpatch.pl | 34 ----------------------------------
> 2 files changed, 40 deletions(-)
>
> diff --git a/Documentation/dev-tools/checkpatch.rst b/Documentation/dev-tools/checkpatch.rst
> index a9fac978a525..f5c27be9e673 100644
> --- a/Documentation/dev-tools/checkpatch.rst
> +++ b/Documentation/dev-tools/checkpatch.rst
> @@ -466,12 +466,6 @@ API usage
> **UAPI_INCLUDE**
> No #include statements in include/uapi should use a uapi/ path.
>
> - **USLEEP_RANGE**
> - usleep_range() should be preferred over udelay(). The proper way of
> - using usleep_range() is mentioned in the kernel docs.
> -
> - See: https://www.kernel.org/doc/html/latest/timers/timers-howto.html#delays-information-on-the-various-kernel-delay-sleep-mechanisms
> -
>
> Comments
> --------
> diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
> index ba3359bdd1fa..80497da4aaac 100755
> --- a/scripts/checkpatch.pl
> +++ b/scripts/checkpatch.pl
> @@ -6601,28 +6601,6 @@ sub process {
> }
> }
>
> -# prefer usleep_range over udelay
> - if ($line =~ /\budelay\s*\(\s*(\d+)\s*\)/) {
> - my $delay = $1;
> - # ignore udelay's < 10, however
> - if (! ($delay < 10) ) {
> - CHK("USLEEP_RANGE",
> - "usleep_range is preferred over udelay; see Documentation/timers/timers-howto.rst\n" . $herecurr);
> - }
> - if ($delay > 2000) {
> - WARN("LONG_UDELAY",
> - "long udelay - prefer mdelay; see arch/arm/include/asm/delay.h\n" . $herecurr);
> - }
> - }
> -
> -# warn about unexpectedly long msleep's
> - if ($line =~ /\bmsleep\s*\((\d+)\);/) {
> - if ($1 < 20) {
> - WARN("MSLEEP",
> - "msleep < 20ms can sleep for up to 20ms; see Documentation/timers/timers-howto.rst\n" . $herecurr);
> - }
> - }
> -
> # check for comparisons of jiffies
> if ($line =~ /\bjiffies\s*$Compare|$Compare\s*jiffies\b/) {
> WARN("JIFFIES_COMPARISON",
> @@ -7079,18 +7057,6 @@ sub process {
> }
> }
>
> -# check usleep_range arguments
> - if ($perl_version_ok &&
> - defined $stat &&
> - $stat =~ /^\+(?:.*?)\busleep_range\s*\(\s*($FuncArg)\s*,\s*($FuncArg)\s*\)/) {
> - my $min = $1;
> - my $max = $7;
> - if ($min eq $max) {
> - WARN("USLEEP_RANGE",
> - "usleep_range should not use min == max args; see Documentation/timers/timers-howto.rst\n" . "$here\n$stat\n");
> - }
> - }
> -
> # check for naked sscanf
> if ($perl_version_ok &&
> defined $stat &&
>
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: [PATCH v2 10/15] checkpatch: Remove broken sleep/delay related checks
2024-09-11 6:44 ` Joe Perches
@ 2024-09-11 7:41 ` Anna-Maria Behnsen
0 siblings, 0 replies; 47+ messages in thread
From: Anna-Maria Behnsen @ 2024-09-11 7:41 UTC (permalink / raw)
To: Joe Perches, Frederic Weisbecker, Thomas Gleixner,
Jonathan Corbet
Cc: linux-kernel, Len Brown, Rafael J. Wysocki, Andy Whitcroft,
Dwaipayan Ray
Joe Perches <joe@perches.com> writes:
> On Wed, 2024-09-11 at 07:13 +0200, Anna-Maria Behnsen wrote:
>> checkpatch.pl checks for several things related to sleep and delay
>> functions. In all warnings the outdated documentation is referenced. All
>> broken parts are listed one by one in the following with an explanation why
>> this check is broken. For a basic background of those functions please also
>> refere to the updated function descriptions of udelay(), nsleep_range() and
>> msleep().
>>
>> Be aware: The change is done with a perl knowledge of the level "I'm able
>> to spell perl".
>>
>> The following checks are broken:
>>
>> - Check: (! ($delay < 10) )
>> Message: "usleep_range is preferred over udelay;
>> see Documentation/timers/timers-howto.rst\n"
>> Why is the check broken: When it is an atomic context, udelay() is
>> mandatory.
>>
>> - Check: ($min eq $max)
>> Message: "usleep_range should not use min == max args;
>> see Documentation/timers/timers-howto.rst\n"
>> Why is the check broken: When the requested accuracy for the sleep
>> duration requires it, it is also valid to use
>> min == max.
>
> There is a runtime setup cost to use usleep_range.
Sure, it's because of hrtimers. This is also documented in the new
documentation.
> I believe udelay should generally be used when there
> is a specific microsecond time delay required.
The aim of the whole series is to cleanup the outdated documentation of
the usage of delay/sleep related functions. Please read the new
documentation which is provided by the last patch of the queue, when to
use which function. Also updated function descriptions itself contain
important information about usage. If you have any concerns about
correctness of the new documentation or if there is something missing,
please let me know.
As several comments in the kernel and also checkpatch contain several
links to the outdated documentation file (which will be also moved to a
more self explaining file name by the last patch), I need to update
those places to be able to move the file. Also checkpatch.
>>
>> - Check: ($delay > 2000)
>> Message: "long udelay - prefer mdelay;
>> see arch/arm/include/asm/delay.h\n"
>> Why is the check broken: The threshold when to start using mdelay() to
>> prevent an overflow depends on
>> MAX_UDELAY_MS. This value is architecture
>> dependent. The used value for the check and
>> reference is arm specific. Generic would be 5ms,
>> but this would "break" arm, loongarch and mips
>> and also the arm value might "break" mips and
>> loongarch in some configurations.
>
> It likely won't "break", just perhaps be inefficient.
If running on loongarch with HZ>=1000 MAX_UDELAY_MS is 1. When keeping
the above check, then there is the risk of an overflow. I'm not sure if
an overflow is the same than beeing inefficient. Same for mips with HZ>=1000.
When using the generic value of 5, also arm would have the risk of an
overflow as MAX_UDELAY_MS for arm is 2.
So my general questions here are:
- What do you think about the change of this patch in general or do you
want to have things changed?
- Should I only make changes to the commit message so that it's more clear?
This would really much help me to make progress with this queue.
Thanks a lot for your support!
Anna-Maria
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: [PATCH v2 09/15] timers: Add a warning to usleep_range_state() for wrong order of arguments
2024-09-11 6:41 ` Joe Perches
@ 2024-09-11 7:45 ` Anna-Maria Behnsen
0 siblings, 0 replies; 47+ messages in thread
From: Anna-Maria Behnsen @ 2024-09-11 7:45 UTC (permalink / raw)
To: Joe Perches, Frederic Weisbecker, Thomas Gleixner,
Jonathan Corbet
Cc: linux-kernel, Len Brown, Rafael J. Wysocki, Andy Whitcroft
Joe Perches <joe@perches.com> writes:
> On Wed, 2024-09-11 at 07:13 +0200, Anna-Maria Behnsen wrote:
>> There is a warning in checkpatch script that triggers, when min and max
>> arguments of usleep_range_state() are in reverse order. This check does
>> only cover callsites which uses constants. Move this check into the code as
>> a WARN_ON_ONCE() to also cover callsites not using constants and get rid of
>> it in checkpatch.
>
> I don't disagree that a runtime test is useful
> and relatively cost free.
>
> But checkpatch is for patches.
>
> There's no reason as far as I can tell to remove
> this source code test.
>
> Why make the test runtime only?
>
Sure, we can keep the test in checkpatch as well and I will only add the
runtime check. Then I would change the link to the documentation in
checkpatch into a link to the updated function description. Before I do
any update there, I want to wait for your answer to the other patch of
the queue.
Thanks,
Anna-Maria
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: [PATCH v2 12/15] iopoll/regmap/phy/snd: Fix comment referencing outdated timer documentation
2024-09-11 5:13 ` [PATCH v2 12/15] iopoll/regmap/phy/snd: Fix comment referencing outdated timer documentation Anna-Maria Behnsen
@ 2024-09-11 12:08 ` Andrew Lunn
2024-10-09 16:14 ` Frederic Weisbecker
1 sibling, 0 replies; 47+ messages in thread
From: Andrew Lunn @ 2024-09-11 12:08 UTC (permalink / raw)
To: Anna-Maria Behnsen
Cc: Frederic Weisbecker, Thomas Gleixner, Jonathan Corbet,
linux-kernel, Len Brown, Rafael J. Wysocki, Heiner Kallweit,
Jaroslav Kysela, Takashi Iwai, netdev, linux-sound
On Wed, Sep 11, 2024 at 07:13:38AM +0200, Anna-Maria Behnsen wrote:
> Function descriptions in iopoll.h, regmap.h, phy.h and sound/soc/sof/ops.h
> copied all the same outdated documentation about sleep/delay function
> limitations. In those comments, the generic (and still outdated) timer
> documentation file is referenced.
>
> As proper function descriptions for used delay and sleep functions are in
> place, simply update the descriptions to reference to them. While at it fix
> missing colon after "Returns" in function description and move return value
> description to the end of the function description.
>
> Cc: Andrew Lunn <andrew@lunn.ch>
> Cc: Heiner Kallweit <hkallweit1@gmail.com>
> Cc: Jaroslav Kysela <perex@perex.cz>
> Cc: Takashi Iwai <tiwai@suse.com>
> Cc: netdev@vger.kernel.org
> Cc: linux-sound@vger.kernel.org
> Signed-off-by: Anna-Maria Behnsen <anna-maria@linutronix.de>
> ---
> v2: Add cleanup of usage of 'Returns' in function description
> ---
> include/linux/iopoll.h | 52 +++++++++++++++++++++++++-------------------------
> include/linux/phy.h | 9 +++++----
For the phy.h parts:
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Andrew
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: [PATCH v2 00/15] timers: Cleanup delay/sleep related mess
2024-09-11 5:13 [PATCH v2 00/15] timers: Cleanup delay/sleep related mess Anna-Maria Behnsen
` (14 preceding siblings ...)
2024-09-11 5:13 ` [PATCH v2 15/15] timers/Documentation: Cleanup delay/sleep documentation Anna-Maria Behnsen
@ 2024-09-16 20:20 ` Christophe JAILLET
2024-09-17 5:22 ` Christophe JAILLET
2024-10-02 15:02 ` Thomas Gleixner
15 siblings, 2 replies; 47+ messages in thread
From: Christophe JAILLET @ 2024-09-16 20:20 UTC (permalink / raw)
To: Frederic Weisbecker, Thomas Gleixner, Jonathan Corbet,
Anna-Maria Behnsen
Cc: linux-kernel, Len Brown, Rafael J. Wysocki, Anna-Maria Behnsen,
Andrew Morton, damon, linux-mm, SeongJae Park, Arnd Bergmann,
linux-arch, Heiner Kallweit, David S. Miller, Andy Whitcroft,
Joe Perches, Dwaipayan Ray, Liam Girdwood, Mark Brown,
Andrew Lunn, Jaroslav Kysela, Takashi Iwai, netdev, linux-sound,
Michael Ellerman, Nathan Lynch, linuxppc-dev,
Mauro Carvalho Chehab, linux-media
Le 11/09/2024 à 07:13, Anna-Maria Behnsen a écrit :
> Hi,
>
> a question about which sleeping function should be used in acpi_os_sleep()
> started a discussion and examination about the existing documentation and
> implementation of functions which insert a sleep/delay.
>
> The result of the discussion was, that the documentation is outdated and
> the implemented fsleep() reflects the outdated documentation but doesn't
> help to reflect reality which in turns leads to the queue which covers the
> following things:
>
> - Split out all timeout and sleep related functions from hrtimer.c and timer.c
> into a separate file
>
> - Update function descriptions of sleep related functions
>
> - Change fsleep() to reflect reality
>
> - Rework all comments or users which obviously rely on the outdated
> documentation as they reference "Documentation/timers/timers-howto.rst"
>
> - Last but not least (as there are no more references): Update the outdated
> documentation and move it into a file with a self explaining file name
>
> The queue is available here and applies on top of tip/timers/core:
>
> git://git.kernel.org/pub/scm/linux/kernel/git/anna-maria/linux-devel.git timers/misc
>
> Signed-off-by: Anna-Maria Behnsen <anna-maria@linutronix.de>
Hi,
not directly related to your serie, but some time ago I sent a patch to
micro-optimize Optimize usleep_range(). (See [1])
The idea is that the 2 parameters of usleep_range() are usually
constants and some code reordering could easily let the compiler compute
a few things at compilation time.
There was consensus on the value of the change (see [2]), but as you are
touching things here, maybe it makes sense now to save a few cycles at
runtime and a few bytes of code?
CJ
[1]:
https://lore.kernel.org/all/f0361b83a0a0b549f8ec5ab8134905001a6f2509.1659126514.git.christophe.jaillet@wanadoo.fr/
[2]:
https://lore.kernel.org/all/03c2bbe795fe4ddcab66eb852bae3715@AcuMS.aculab.com/
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: [PATCH v2 00/15] timers: Cleanup delay/sleep related mess
2024-09-16 20:20 ` [PATCH v2 00/15] timers: Cleanup delay/sleep related mess Christophe JAILLET
@ 2024-09-17 5:22 ` Christophe JAILLET
2024-09-23 15:12 ` Anna-Maria Behnsen
2024-10-02 15:02 ` Thomas Gleixner
1 sibling, 1 reply; 47+ messages in thread
From: Christophe JAILLET @ 2024-09-17 5:22 UTC (permalink / raw)
To: Anna-Maria Behnsen
Cc: linux-kernel, Len Brown, Rafael J. Wysocki, Andrew Morton, damon,
linux-mm, SeongJae Park, Arnd Bergmann, linux-arch,
Heiner Kallweit, David S. Miller, Andy Whitcroft, Joe Perches,
Dwaipayan Ray, Liam Girdwood, Mark Brown, Andrew Lunn,
Jaroslav Kysela, Takashi Iwai, netdev, linux-sound,
Michael Ellerman, Nathan Lynch, linuxppc-dev,
Mauro Carvalho Chehab, linux-media, Frederic Weisbecker,
Thomas Gleixner, Jonathan Corbet
Le 16/09/2024 à 22:20, Christophe JAILLET a écrit :
> Le 11/09/2024 à 07:13, Anna-Maria Behnsen a écrit :
>> Hi,
>>
>> a question about which sleeping function should be used in
>> acpi_os_sleep()
>> started a discussion and examination about the existing documentation and
>> implementation of functions which insert a sleep/delay.
>>
>> The result of the discussion was, that the documentation is outdated and
>> the implemented fsleep() reflects the outdated documentation but doesn't
>> help to reflect reality which in turns leads to the queue which covers
>> the
>> following things:
>>
>> - Split out all timeout and sleep related functions from hrtimer.c and
>> timer.c
>> into a separate file
>>
>> - Update function descriptions of sleep related functions
>>
>> - Change fsleep() to reflect reality
>>
>> - Rework all comments or users which obviously rely on the outdated
>> documentation as they reference "Documentation/timers/timers-
>> howto.rst"
>>
>> - Last but not least (as there are no more references): Update the
>> outdated
>> documentation and move it into a file with a self explaining file name
>>
>> The queue is available here and applies on top of tip/timers/core:
>>
>> git://git.kernel.org/pub/scm/linux/kernel/git/anna-maria/linux-
>> devel.git timers/misc
>>
>> Signed-off-by: Anna-Maria Behnsen <anna-maria@linutronix.de>
>
> Hi,
>
> not directly related to your serie, but some time ago I sent a patch to
> micro-optimize Optimize usleep_range(). (See [1])
>
> The idea is that the 2 parameters of usleep_range() are usually
> constants and some code reordering could easily let the compiler compute
> a few things at compilation time.
>
> There was consensus on the value of the change (see [2]), but as you are
Typo: there was *no* consensus...
> touching things here, maybe it makes sense now to save a few cycles at
> runtime and a few bytes of code?
>
> CJ
>
> [1]: https://lore.kernel.org/all/
> f0361b83a0a0b549f8ec5ab8134905001a6f2509.1659126514.git.christophe.jaillet@wanadoo.fr/
>
> [2]: https://lore.kernel.org/
> all/03c2bbe795fe4ddcab66eb852bae3715@AcuMS.aculab.com/
>
>
>
>
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: [PATCH v2 00/15] timers: Cleanup delay/sleep related mess
2024-09-17 5:22 ` Christophe JAILLET
@ 2024-09-23 15:12 ` Anna-Maria Behnsen
0 siblings, 0 replies; 47+ messages in thread
From: Anna-Maria Behnsen @ 2024-09-23 15:12 UTC (permalink / raw)
To: Christophe JAILLET
Cc: linux-kernel, Len Brown, Rafael J. Wysocki, Andrew Morton, damon,
linux-mm, SeongJae Park, Arnd Bergmann, linux-arch,
Heiner Kallweit, David S. Miller, Andy Whitcroft, Joe Perches,
Dwaipayan Ray, Liam Girdwood, Mark Brown, Andrew Lunn,
Jaroslav Kysela, Takashi Iwai, netdev, linux-sound,
Michael Ellerman, Nathan Lynch, linuxppc-dev,
Mauro Carvalho Chehab, linux-media, Frederic Weisbecker,
Thomas Gleixner, Jonathan Corbet
Christophe JAILLET <christophe.jaillet@wanadoo.fr> writes:
> Le 16/09/2024 à 22:20, Christophe JAILLET a écrit :
>> Le 11/09/2024 à 07:13, Anna-Maria Behnsen a écrit :
>>> Hi,
>>>
>>> a question about which sleeping function should be used in
>>> acpi_os_sleep()
>>> started a discussion and examination about the existing documentation and
>>> implementation of functions which insert a sleep/delay.
>>>
>>> The result of the discussion was, that the documentation is outdated and
>>> the implemented fsleep() reflects the outdated documentation but doesn't
>>> help to reflect reality which in turns leads to the queue which covers
>>> the
>>> following things:
>>>
>>> - Split out all timeout and sleep related functions from hrtimer.c and
>>> timer.c
>>> into a separate file
>>>
>>> - Update function descriptions of sleep related functions
>>>
>>> - Change fsleep() to reflect reality
>>>
>>> - Rework all comments or users which obviously rely on the outdated
>>> documentation as they reference "Documentation/timers/timers-
>>> howto.rst"
>>>
>>> - Last but not least (as there are no more references): Update the
>>> outdated
>>> documentation and move it into a file with a self explaining file name
>>>
>>> The queue is available here and applies on top of tip/timers/core:
>>>
>>> git://git.kernel.org/pub/scm/linux/kernel/git/anna-maria/linux-
>>> devel.git timers/misc
>>>
>>> Signed-off-by: Anna-Maria Behnsen <anna-maria@linutronix.de>
>>
>> Hi,
>>
>> not directly related to your serie, but some time ago I sent a patch to
>> micro-optimize Optimize usleep_range(). (See [1])
>>
>> The idea is that the 2 parameters of usleep_range() are usually
>> constants and some code reordering could easily let the compiler compute
>> a few things at compilation time.
>>
>> There was consensus on the value of the change (see [2]), but as you are
>
> Typo: there was *no* consensus...
>
>> touching things here, maybe it makes sense now to save a few cycles at
>> runtime and a few bytes of code?
>>
Sorry for the late reply. I'll check it and will come back to you.
Thanks,
Anna-Maria
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: [PATCH v2 06/15] delay: Rework udelay and ndelay
2024-09-11 5:13 ` [PATCH v2 06/15] delay: Rework udelay and ndelay Anna-Maria Behnsen
@ 2024-09-23 15:40 ` Anna-Maria Behnsen
2024-10-08 14:24 ` Frederic Weisbecker
1 sibling, 0 replies; 47+ messages in thread
From: Anna-Maria Behnsen @ 2024-09-23 15:40 UTC (permalink / raw)
To: Frederic Weisbecker, Thomas Gleixner, Jonathan Corbet
Cc: linux-kernel, Len Brown, Rafael J. Wysocki
Anna-Maria Behnsen <anna-maria@linutronix.de> writes:
> udelay() as well as ndelay() are defines and no functions and are using
> constants to be able to transform a sleep time into loops and to prevent
> too long udelays/ndelays. There was a compiler error with non-const 8 bit
> arguments which was fixed by commit a87e553fabe8 ("asm-generic: delay.h fix
> udelay and ndelay for 8 bit args"). When using a function, the non-const 8
> bit argument is type casted and the problem would be gone.
>
> Transform udelay() and ndelay() into proper functions, remove the no longer
> and confusing division, add defines for the magic values and add some
> explanations as well.
>
> Suggested-by: Thomas Gleixner <tglx@linutronix.de>
> Signed-off-by: Anna-Maria Behnsen <anna-maria@linutronix.de>
> ---
> v2: New in v2 (as suggested by Thomas)
> ---
> include/asm-generic/delay.h | 64 +++++++++++++++++++++++++--------------------
> 1 file changed, 36 insertions(+), 28 deletions(-)
>
> diff --git a/include/asm-generic/delay.h b/include/asm-generic/delay.h
> index 70a1b20f3e1a..40d30dc2488b 100644
> --- a/include/asm-generic/delay.h
> +++ b/include/asm-generic/delay.h
> @@ -2,6 +2,8 @@
> #ifndef __ASM_GENERIC_DELAY_H
> #define __ASM_GENERIC_DELAY_H
>
> +#include <vdso/time64.h>
There was a build failure for i386 (missing include
<linux/math.h>). Will be updated with v3.
Thanks,
Anna-Maria
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: [PATCH v2 01/15] MAINTAINERS: Add missing file include/linux/delay.h
2024-09-11 5:13 ` [PATCH v2 01/15] MAINTAINERS: Add missing file include/linux/delay.h Anna-Maria Behnsen
@ 2024-10-01 20:11 ` Frederic Weisbecker
0 siblings, 0 replies; 47+ messages in thread
From: Frederic Weisbecker @ 2024-10-01 20:11 UTC (permalink / raw)
To: Anna-Maria Behnsen
Cc: Thomas Gleixner, Jonathan Corbet, linux-kernel, Len Brown,
Rafael J. Wysocki
Le Wed, Sep 11, 2024 at 07:13:27AM +0200, Anna-Maria Behnsen a écrit :
> include/linux/delay.h is not covered by MAINTAINERS file. Add it to the
> "HIGH-RESOLUTION TIMERS, TIMER WHEEL, CLOCKEVENTS" section.
>
> Signed-off-by: Anna-Maria Behnsen <anna-maria@linutronix.de>
Acked-by: Frederic Weisbecker <frederic@kernel.org>
> ---
> v2: New (splitted as requested by Frederic)
> ---
> MAINTAINERS | 1 +
> 1 file changed, 1 insertion(+)
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 42decde38320..d9135d8ece99 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -10010,6 +10010,7 @@ S: Maintained
> T: git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git timers/core
> F: Documentation/timers/
> F: include/linux/clockchips.h
> +F: include/linux/delay.h
> F: include/linux/hrtimer.h
> F: include/linux/timer.h
> F: kernel/time/clockevents.c
>
> --
> 2.39.2
>
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: [PATCH v2 02/15] timers: Move *sleep*() and timeout functions into a separate file
2024-09-11 5:13 ` [PATCH v2 02/15] timers: Move *sleep*() and timeout functions into a separate file Anna-Maria Behnsen
@ 2024-10-01 20:45 ` Frederic Weisbecker
0 siblings, 0 replies; 47+ messages in thread
From: Frederic Weisbecker @ 2024-10-01 20:45 UTC (permalink / raw)
To: Anna-Maria Behnsen
Cc: Thomas Gleixner, Jonathan Corbet, linux-kernel, Len Brown,
Rafael J. Wysocki
Le Wed, Sep 11, 2024 at 07:13:28AM +0200, Anna-Maria Behnsen a écrit :
> All schedule_timeout() and *sleep*() related functions are interfaces on
> top of timer list timers and hrtimers to add a sleep to the code. As they
> are built on top of the timer list timers and hrtimers, the [hr]timer
> interfaces are already used except when queuing the timer in
> schedule_timeout(). But there exists the appropriate interface add_timer()
> which does the same job with an extra check for an already pending timer.
>
> Split all those functions as they are into a separate file and use
> add_timer() instead of __mod_timer() in schedule_timeout().
>
> While at it fix minor formatting issues and a multi line printk function
> call in schedule_timeout().
>
> Signed-off-by: Anna-Maria Behnsen <anna-maria@linutronix.de>
Acked-by: Frederic Weisbecker <frederic@kernel.org>
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: [PATCH v2 03/15] timers: Update schedule_[hr]timeout*() related function descriptions
2024-09-11 5:13 ` [PATCH v2 03/15] timers: Update schedule_[hr]timeout*() related function descriptions Anna-Maria Behnsen
@ 2024-10-01 21:16 ` Frederic Weisbecker
0 siblings, 0 replies; 47+ messages in thread
From: Frederic Weisbecker @ 2024-10-01 21:16 UTC (permalink / raw)
To: Anna-Maria Behnsen
Cc: Thomas Gleixner, Jonathan Corbet, linux-kernel, Len Brown,
Rafael J. Wysocki
Le Wed, Sep 11, 2024 at 07:13:29AM +0200, Anna-Maria Behnsen a écrit :
> schedule_timeout*() functions do not have proper kernel-doc formatted
> function descriptions. schedule_hrtimeout() and schedule_hrtimeout_range()
> have a almost identical description.
>
> Add missing function descriptions. Remove copy of function description and
> add a pointer to the existing description instead.
>
> Signed-off-by: Anna-Maria Behnsen <anna-maria@linutronix.de>
Acked-by: Frederic Weisbecker <frederic@kernel.org>
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: [PATCH v2 00/15] timers: Cleanup delay/sleep related mess
2024-09-16 20:20 ` [PATCH v2 00/15] timers: Cleanup delay/sleep related mess Christophe JAILLET
2024-09-17 5:22 ` Christophe JAILLET
@ 2024-10-02 15:02 ` Thomas Gleixner
1 sibling, 0 replies; 47+ messages in thread
From: Thomas Gleixner @ 2024-10-02 15:02 UTC (permalink / raw)
To: Christophe JAILLET, Frederic Weisbecker, Jonathan Corbet,
Anna-Maria Behnsen
Cc: linux-kernel, Len Brown, Rafael J. Wysocki, Anna-Maria Behnsen,
Andrew Morton, damon, linux-mm, SeongJae Park, Arnd Bergmann,
linux-arch, Heiner Kallweit, David S. Miller, Andy Whitcroft,
Joe Perches, Dwaipayan Ray, Liam Girdwood, Mark Brown,
Andrew Lunn, Jaroslav Kysela, Takashi Iwai, netdev, linux-sound,
Michael Ellerman, Nathan Lynch, linuxppc-dev,
Mauro Carvalho Chehab, linux-media
On Mon, Sep 16 2024 at 22:20, Christophe JAILLET wrote:
> Le 11/09/2024 à 07:13, Anna-Maria Behnsen a écrit :
>
> not directly related to your serie, but some time ago I sent a patch to
> micro-optimize Optimize usleep_range(). (See [1])
>
> The idea is that the 2 parameters of usleep_range() are usually
> constants and some code reordering could easily let the compiler compute
> a few things at compilation time.
>
> There was consensus on the value of the change (see [2]), but as you are
> touching things here, maybe it makes sense now to save a few cycles at
> runtime and a few bytes of code?
For the price of yet another ugly interface and pushing the
multiplication into the non-constant call sites.
Seriously usleep() is not a hotpath operation and the multiplication is
not even measurable except in micro benchmarks.
Thanks,
tglx
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: [PATCH v2 05/15] timers: Update function descriptions of sleep/delay related functions
2024-09-11 5:13 ` [PATCH v2 05/15] timers: Update function descriptions of sleep/delay related functions Anna-Maria Behnsen
@ 2024-10-06 21:49 ` Frederic Weisbecker
2024-10-10 8:45 ` Anna-Maria Behnsen
0 siblings, 1 reply; 47+ messages in thread
From: Frederic Weisbecker @ 2024-10-06 21:49 UTC (permalink / raw)
To: Anna-Maria Behnsen
Cc: Thomas Gleixner, Jonathan Corbet, linux-kernel, Len Brown,
Rafael J. Wysocki, Arnd Bergmann, linux-arch
Le Wed, Sep 11, 2024 at 07:13:31AM +0200, Anna-Maria Behnsen a écrit :
> A lot of commonly used functions for inserting a sleep or delay lack a
> proper function description. Add function descriptions to all of them to
> have important information in a central place close to the code.
>
> No functional change.
>
> Cc: Arnd Bergmann <arnd@arndb.de>
> Cc: linux-arch@vger.kernel.org
> Signed-off-by: Anna-Maria Behnsen <anna-maria@linutronix.de>
> ---
> v2:
> - Fix typos
> - Fix proper usage of kernel-doc return formatting
> ---
> include/asm-generic/delay.h | 41 +++++++++++++++++++++++++++++++----
> include/linux/delay.h | 48 ++++++++++++++++++++++++++++++----------
> kernel/time/sleep_timeout.c | 53 ++++++++++++++++++++++++++++++++++++++++-----
> 3 files changed, 120 insertions(+), 22 deletions(-)
>
> diff --git a/include/asm-generic/delay.h b/include/asm-generic/delay.h
> index e448ac61430c..70a1b20f3e1a 100644
> --- a/include/asm-generic/delay.h
> +++ b/include/asm-generic/delay.h
> @@ -12,11 +12,39 @@ extern void __const_udelay(unsigned long xloops);
> extern void __delay(unsigned long loops);
>
> /*
> - * The weird n/20000 thing suppresses a "comparison is always false due to
> - * limited range of data type" warning with non-const 8-bit arguments.
> + * Implementation details:
> + *
> + * * The weird n/20000 thing suppresses a "comparison is always false due to
> + * limited range of data type" warning with non-const 8-bit arguments.
> + * * 0x10c7 is 2**32 / 1000000 (rounded up) -> udelay
> + * * 0x5 is 2**32 / 1000000000 (rounded up) -> ndelay
I can't say I'm less confused about these values but at least it
brings a bit of light in the horizon...
> */
>
> -/* 0x10c7 is 2**32 / 1000000 (rounded up) */
> +/**
> + * udelay - Inserting a delay based on microseconds with busy waiting
> + * @usec: requested delay in microseconds
> + *
> + * When delaying in an atomic context ndelay(), udelay() and mdelay() are the
> + * only valid variants of delaying/sleeping to go with.
> + *
> + * When inserting delays in non atomic context which are shorter than the time
> + * which is required to queue e.g. an hrtimer and to enter then the scheduler,
> + * it is also valuable to use udelay(). But is not simple to specify a generic
But it is*
> + * threshold for this which will fit for all systems, but an approximation would
But but?
> + * be a threshold for all delays up to 10 microseconds.
> + *
> + * When having a delay which is larger than the architecture specific
> + * %MAX_UDELAY_MS value, please make sure mdelay() is used. Otherwise a overflow
> + * risk is given.
> + *
> + * Please note that ndelay(), udelay() and mdelay() may return early for several
> + * reasons (https://lists.openwall.net/linux-kernel/2011/01/09/56):
> + *
> + * #. computed loops_per_jiffy too low (due to the time taken to execute the
> + * timer interrupt.)
> + * #. cache behaviour affecting the time it takes to execute the loop function.
> + * #. CPU clock rate changes.
> + */
> #define udelay(n) \
> ({ \
> if (__builtin_constant_p(n)) { \
> @@ -35,12 +25,21 @@ extern unsigned long loops_per_jiffy;
> * The 2nd mdelay() definition ensures GCC will optimize away the
> * while loop for the common cases where n <= MAX_UDELAY_MS -- Paul G.
> */
> -
> #ifndef MAX_UDELAY_MS
> #define MAX_UDELAY_MS 5
> #endif
>
> #ifndef mdelay
> +/**
> + * mdelay - Inserting a delay based on microseconds with busy waiting
Milliseconds?
> + * @n: requested delay in microseconds
Ditto
> + *
> + * See udelay() for basic information about mdelay() and it's variants.
> + *
> + * Please double check, whether mdelay() is the right way to go or whether a
> + * refactoring of the code is the better variant to be able to use msleep()
> + * instead.
> + */
> #define mdelay(n) (\
> (__builtin_constant_p(n) && (n)<=MAX_UDELAY_MS) ? udelay((n)*1000) : \
> ({unsigned long __ms=(n); while (__ms--) udelay(1000);}))
> @@ -63,16 +62,41 @@ unsigned long msleep_interruptible(unsigned int msecs);
> void usleep_range_state(unsigned long min, unsigned long max,
> unsigned int state);
>
> +/**
> + * usleep_range - Sleep for an approximate time
> + * @min: Minimum time in microseconds to sleep
> + * @max: Maximum time in microseconds to sleep
> + *
> + * For basic information please refere to usleep_range_state().
> + *
> + * The task will be in the state TASK_UNINTERRUPTIBLE during the sleep.
> + */
> static inline void usleep_range(unsigned long min, unsigned long max)
> {
> usleep_range_state(min, max, TASK_UNINTERRUPTIBLE);
> }
>
> +/**
> + * usleep_range_idle - Sleep for an approximate time with idle time accounting
> + * @min: Minimum time in microseconds to sleep
> + * @max: Maximum time in microseconds to sleep
> + *
> + * For basic information please refere to usleep_range_state().
> + *
> + * The sleeping task has the state TASK_IDLE during the sleep to prevent
> + * contribution to the load avarage.
> + */
> static inline void usleep_range_idle(unsigned long min, unsigned long max)
> {
> usleep_range_state(min, max, TASK_IDLE);
> }
>
> +/**
> + * ssleep - wrapper for seconds arount msleep
around
> + * @seconds: Requested sleep duration in seconds
> + *
> + * Please refere to msleep() for detailed information.
> + */
> static inline void ssleep(unsigned int seconds)
> {
> msleep(seconds * 1000);
> diff --git a/kernel/time/sleep_timeout.c b/kernel/time/sleep_timeout.c
> index 560d17c30aa5..21f412350b15 100644
> --- a/kernel/time/sleep_timeout.c
> +++ b/kernel/time/sleep_timeout.c
> @@ -281,7 +281,34 @@ EXPORT_SYMBOL_GPL(schedule_hrtimeout);
>
> /**
> * msleep - sleep safely even with waitqueue interruptions
> - * @msecs: Time in milliseconds to sleep for
> + * @msecs: Requested sleep duration in milliseconds
> + *
> + * msleep() uses jiffy based timeouts for the sleep duration. The accuracy of
> + * the resulting sleep duration depends on:
> + *
> + * * HZ configuration
> + * * sleep duration (as granularity of a bucket which collects timers increases
> + * with the timer wheel levels)
> + *
> + * When the timer is queued into the second level of the timer wheel the maximum
> + * additional delay will be 12.5%. For explanation please check the detailed
> + * description about the basics of the timer wheel. In case this is accurate
> + * enough check which sleep length is selected to make sure required accuracy is
> + * given. Please use therefore the following simple steps:
> + *
> + * #. Decide which slack is fine for the requested sleep duration - but do not
> + * use values shorter than 1/8
I'm confused, what means 1/x for a slack value? 1/8 means 125 msecs? I'm not
even I understand what you mean by slack. Is it the bucket_expiry - expiry?
> + * #. Check whether your sleep duration is equal or greater than the following
> + * result: ``TICK_NSEC / slack / NSEC_PER_MSEC``
> + *
> + * Examples:
> + *
> + * * ``HZ=1000`` with `slack=1/4``: all sleep durations greater or equal 4ms will meet
> + * the constrains.
> + * * ``HZ=250`` with ``slack=1/4``: all sleep durations greater or equal 16ms will meet
> + * the constrains.
constraints.
But I'm still lost...
Thanks.
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: [PATCH v2 06/15] delay: Rework udelay and ndelay
2024-09-11 5:13 ` [PATCH v2 06/15] delay: Rework udelay and ndelay Anna-Maria Behnsen
2024-09-23 15:40 ` Anna-Maria Behnsen
@ 2024-10-08 14:24 ` Frederic Weisbecker
1 sibling, 0 replies; 47+ messages in thread
From: Frederic Weisbecker @ 2024-10-08 14:24 UTC (permalink / raw)
To: Anna-Maria Behnsen
Cc: Thomas Gleixner, Jonathan Corbet, linux-kernel, Len Brown,
Rafael J. Wysocki
Le Wed, Sep 11, 2024 at 07:13:32AM +0200, Anna-Maria Behnsen a écrit :
> udelay() as well as ndelay() are defines and no functions and are using
> constants to be able to transform a sleep time into loops and to prevent
> too long udelays/ndelays. There was a compiler error with non-const 8 bit
> arguments which was fixed by commit a87e553fabe8 ("asm-generic: delay.h fix
> udelay and ndelay for 8 bit args"). When using a function, the non-const 8
> bit argument is type casted and the problem would be gone.
>
> Transform udelay() and ndelay() into proper functions, remove the no longer
> and confusing division, add defines for the magic values and add some
> explanations as well.
>
> Suggested-by: Thomas Gleixner <tglx@linutronix.de>
> Signed-off-by: Anna-Maria Behnsen <anna-maria@linutronix.de>
More light at the end of the tunnel for my brain!
Reviewed-by: Frederic Weisbecker <frederic@kernel.org>
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: [PATCH v2 07/15] timers: Adjust flseep() to reflect reality
2024-09-11 5:13 ` [PATCH v2 07/15] timers: Adjust flseep() to reflect reality Anna-Maria Behnsen
@ 2024-10-08 21:45 ` Frederic Weisbecker
0 siblings, 0 replies; 47+ messages in thread
From: Frederic Weisbecker @ 2024-10-08 21:45 UTC (permalink / raw)
To: Anna-Maria Behnsen
Cc: Thomas Gleixner, Jonathan Corbet, linux-kernel, Len Brown,
Rafael J. Wysocki, Heiner Kallweit, David S. Miller
Le Wed, Sep 11, 2024 at 07:13:33AM +0200, Anna-Maria Behnsen a écrit :
> fsleep() simply implements the recommondations of the outdated
recommendations*
> documentation in "Documentation/timers/timers-howto.rst". This should be a
> user friendly interface to choose always the best timeout function
> approach:
>
> - udelay() for very short sleep durations shorter than 10 microseconds
> - usleep_range() for sleep durations until 20 milliseconds
> - msleep() for the others
>
> The actual implementation has several problems:
>
> - It does not take into account that HZ resolution also has an impact on
> granularity of jiffies and has also an impact on the granularity of the
> buckets of timer wheel levels. This means that accuracy for the timeout
> does not have an upper limit. When executing fsleep(20000) on a HZ=100
> system, the possible additional slack will be 50% as the granularity of
> the buckets in the lowest level is 10 milliseconds.
>
> - The upper limit of usleep_range() is twice the requested timeout. When no
> other interrupts occur in this range, the maximum value is used. This
> means that the requested sleep length has then an additional delay of
> 100%.
>
> Change the thresholds for the decisions in fsleep() to make sure the
> maximum slack which is added to the sleep duration is 25%.
>
> Note: Outdated documentation will be updated in a followup patch.
>
> Cc: Heiner Kallweit <hkallweit1@gmail.com>
> Cc: David S. Miller <davem@davemloft.net>
> Signed-off-by: Anna-Maria Behnsen <anna-maria@linutronix.de>
> ---
> include/linux/delay.h | 29 +++++++++++++++++++++++++----
> 1 file changed, 25 insertions(+), 4 deletions(-)
>
> diff --git a/include/linux/delay.h b/include/linux/delay.h
> index 23623fa79768..b49a63c85c43 100644
> --- a/include/linux/delay.h
> +++ b/include/linux/delay.h
> @@ -11,6 +11,7 @@
>
> #include <linux/math.h>
> #include <linux/sched.h>
> +#include <linux/jiffies.h>
>
> extern unsigned long loops_per_jiffy;
>
> @@ -102,15 +103,35 @@ static inline void ssleep(unsigned int seconds)
> msleep(seconds * 1000);
> }
>
> -/* see Documentation/timers/timers-howto.rst for the thresholds */
> +static const unsigned int max_slack_shift = 2;
Should it be a define? (such const variables are usually for arrays).
Anyway:
Reviewed-by: Frederic Weisbecker <frederic@kernel.org>
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: [PATCH v2 08/15] mm/damon/core: Use generic upper bound recommondation for usleep_range()
2024-09-11 5:13 ` [PATCH v2 08/15] mm/damon/core: Use generic upper bound recommondation for usleep_range() Anna-Maria Behnsen
@ 2024-10-09 12:01 ` Frederic Weisbecker
0 siblings, 0 replies; 47+ messages in thread
From: Frederic Weisbecker @ 2024-10-09 12:01 UTC (permalink / raw)
To: Anna-Maria Behnsen
Cc: Thomas Gleixner, Jonathan Corbet, linux-kernel, Len Brown,
Rafael J. Wysocki, SeongJae Park, Andrew Morton, damon, linux-mm
Le Wed, Sep 11, 2024 at 07:13:34AM +0200, Anna-Maria Behnsen a écrit :
> The upper bound for usleep_range_idle() was taken from the outdated
> documentation. As a recommondation for the upper bound of usleep_range()
> depends on HZ configuration it is not possible to hard code it.
>
> Use the define "USLEEP_RANGE_UPPER_BOUND" instead.
>
> Cc: SeongJae Park <sj@kernel.org>
> Cc: Andrew Morton <akpm@linux-foundation.org>
> Cc: damon@lists.linux.dev
> Cc: linux-mm@kvack.org
> Signed-off-by: Anna-Maria Behnsen <anna-maria@linutronix.de>
> Reviewed-by: SeongJae Park <sj@kernel.org>
Reviewed-by: Frederic Weisbecker <frederic@kernel.org>
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: [PATCH v2 09/15] timers: Add a warning to usleep_range_state() for wrong order of arguments
2024-09-11 5:13 ` [PATCH v2 09/15] timers: Add a warning to usleep_range_state() for wrong order of arguments Anna-Maria Behnsen
2024-09-11 6:41 ` Joe Perches
@ 2024-10-09 12:22 ` Frederic Weisbecker
2024-10-10 9:06 ` Anna-Maria Behnsen
1 sibling, 1 reply; 47+ messages in thread
From: Frederic Weisbecker @ 2024-10-09 12:22 UTC (permalink / raw)
To: Anna-Maria Behnsen
Cc: Thomas Gleixner, Jonathan Corbet, linux-kernel, Len Brown,
Rafael J. Wysocki, Andy Whitcroft, Joe Perches
Le Wed, Sep 11, 2024 at 07:13:35AM +0200, Anna-Maria Behnsen a écrit :
> There is a warning in checkpatch script that triggers, when min and max
> arguments of usleep_range_state() are in reverse order. This check does
> only cover callsites which uses constants. Move this check into the code as
> a WARN_ON_ONCE() to also cover callsites not using constants and get rid of
> it in checkpatch.
>
> Cc: Andy Whitcroft <apw@canonical.com>
> Cc: Joe Perches <joe@perches.com>
> Signed-off-by: Anna-Maria Behnsen <anna-maria@linutronix.de>
> ---
> kernel/time/sleep_timeout.c | 2 ++
> scripts/checkpatch.pl | 4 ----
> 2 files changed, 2 insertions(+), 4 deletions(-)
>
> diff --git a/kernel/time/sleep_timeout.c b/kernel/time/sleep_timeout.c
> index 21f412350b15..4b805d7e1903 100644
> --- a/kernel/time/sleep_timeout.c
> +++ b/kernel/time/sleep_timeout.c
> @@ -364,6 +364,8 @@ void __sched usleep_range_state(unsigned long min, unsigned long max, unsigned i
> ktime_t exp = ktime_add_us(ktime_get(), min);
> u64 delta = (u64)(max - min) * NSEC_PER_USEC;
>
> + WARN_ON_ONCE(max < min);
> +
Should it try to "fix" to avoid overflow?
if WARN_ON_ONCE(max < min)
delta = 0
> for (;;) {
> __set_current_state(state);
> /* Do not return before the requested sleep time has elapsed */
> diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
> index 39032224d504..ba3359bdd1fa 100755
> --- a/scripts/checkpatch.pl
> +++ b/scripts/checkpatch.pl
> @@ -7088,10 +7088,6 @@ sub process {
> if ($min eq $max) {
> WARN("USLEEP_RANGE",
> "usleep_range should not use min == max args; see Documentation/timers/timers-howto.rst\n" . "$here\n$stat\n");
> - } elsif ($min =~ /^\d+$/ && $max =~ /^\d+$/ &&
> - $min > $max) {
> - WARN("USLEEP_RANGE",
> - "usleep_range args reversed, use min then max; see Documentation/timers/timers-howto.rst\n" . "$here\n$stat\n");
Perhaps it doesn't hurt to keep the static check?
Thanks.
> }
> }
>
>
> --
> 2.39.2
>
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: [PATCH v2 10/15] checkpatch: Remove broken sleep/delay related checks
2024-09-11 5:13 ` [PATCH v2 10/15] checkpatch: Remove broken sleep/delay related checks Anna-Maria Behnsen
2024-09-11 6:44 ` Joe Perches
@ 2024-10-09 12:45 ` Frederic Weisbecker
1 sibling, 0 replies; 47+ messages in thread
From: Frederic Weisbecker @ 2024-10-09 12:45 UTC (permalink / raw)
To: Anna-Maria Behnsen
Cc: Thomas Gleixner, Jonathan Corbet, linux-kernel, Len Brown,
Rafael J. Wysocki, Andy Whitcroft, Joe Perches, Dwaipayan Ray
Le Wed, Sep 11, 2024 at 07:13:36AM +0200, Anna-Maria Behnsen a écrit :
> checkpatch.pl checks for several things related to sleep and delay
> functions. In all warnings the outdated documentation is referenced. All
> broken parts are listed one by one in the following with an explanation why
> this check is broken. For a basic background of those functions please also
> refere to the updated function descriptions of udelay(), nsleep_range() and
> msleep().
>
> Be aware: The change is done with a perl knowledge of the level "I'm able
> to spell perl".
>
> The following checks are broken:
>
> - Check: (! ($delay < 10) )
> Message: "usleep_range is preferred over udelay;
> see Documentation/timers/timers-howto.rst\n"
> Why is the check broken: When it is an atomic context, udelay() is
> mandatory.
>
> - Check: ($min eq $max)
> Message: "usleep_range should not use min == max args;
> see Documentation/timers/timers-howto.rst\n"
> Why is the check broken: When the requested accuracy for the sleep
> duration requires it, it is also valid to use
> min == max.
>
> - Check: ($delay > 2000)
> Message: "long udelay - prefer mdelay;
> see arch/arm/include/asm/delay.h\n"
> Why is the check broken: The threshold when to start using mdelay() to
> prevent an overflow depends on
> MAX_UDELAY_MS. This value is architecture
> dependent. The used value for the check and
> reference is arm specific. Generic would be 5ms,
> but this would "break" arm, loongarch and mips
> and also the arm value might "break" mips and
> loongarch in some configurations.
>
> - Check: ($1 < 20)
> Message: "msleep < 20ms can sleep for up to 20ms;
> see Documentation/timers/timers-howto.rst\n"
> Why is the check broken: msleep(1) might sleep up to 20ms but only on a
> HZ=100 system. On a HZ=1000 system this will be
> 2ms. This means, the threshold cannot be hard
> coded as it depends on HZ (jiffy granularity and
> timer wheel bucket/level granularity) and also
> on the required accuracy of the callsite. See
> msleep() and also the USLEEP_RANGE_UPPER_BOUND
> value.
>
> Remove all broken checks. Update checkpatch documentation accordingly.
>
> Cc: Andy Whitcroft <apw@canonical.com>
> Cc: Joe Perches <joe@perches.com>
> Cc: Dwaipayan Ray <dwaipayanray1@gmail.com>
> Signed-off-by: Anna-Maria Behnsen <anna-maria@linutronix.de>
Acked-by: Frederic Weisbecker <frederic@kernel.org>
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: [PATCH v2 11/15] regulator: core: Use fsleep() to get best sleep mechanism
2024-09-11 5:13 ` [PATCH v2 11/15] regulator: core: Use fsleep() to get best sleep mechanism Anna-Maria Behnsen
@ 2024-10-09 13:37 ` Frederic Weisbecker
0 siblings, 0 replies; 47+ messages in thread
From: Frederic Weisbecker @ 2024-10-09 13:37 UTC (permalink / raw)
To: Anna-Maria Behnsen
Cc: Thomas Gleixner, Jonathan Corbet, linux-kernel, Len Brown,
Rafael J. Wysocki, Liam Girdwood, Mark Brown
Le Wed, Sep 11, 2024 at 07:13:37AM +0200, Anna-Maria Behnsen a écrit :
> _regulator_delay_helper() implements the recommondation of the outdated
> documentation which sleep mechanism should be used. There is already a
> function in place which does everything and also maps to reality called
> fsleep().
>
> Use fsleep() directly.
>
> Cc: Liam Girdwood <lgirdwood@gmail.com>
> Cc: Mark Brown <broonie@kernel.org>
> Signed-off-by: Anna-Maria Behnsen <anna-maria@linutronix.de>
Reviewed-by: Frederic Weisbecker <frederic@kernel.org>
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: [PATCH v2 12/15] iopoll/regmap/phy/snd: Fix comment referencing outdated timer documentation
2024-09-11 5:13 ` [PATCH v2 12/15] iopoll/regmap/phy/snd: Fix comment referencing outdated timer documentation Anna-Maria Behnsen
2024-09-11 12:08 ` Andrew Lunn
@ 2024-10-09 16:14 ` Frederic Weisbecker
1 sibling, 0 replies; 47+ messages in thread
From: Frederic Weisbecker @ 2024-10-09 16:14 UTC (permalink / raw)
To: Anna-Maria Behnsen
Cc: Thomas Gleixner, Jonathan Corbet, linux-kernel, Len Brown,
Rafael J. Wysocki, Andrew Lunn, Heiner Kallweit, Jaroslav Kysela,
Takashi Iwai, netdev, linux-sound
Le Wed, Sep 11, 2024 at 07:13:38AM +0200, Anna-Maria Behnsen a écrit :
> Function descriptions in iopoll.h, regmap.h, phy.h and sound/soc/sof/ops.h
> copied all the same outdated documentation about sleep/delay function
> limitations. In those comments, the generic (and still outdated) timer
> documentation file is referenced.
>
> As proper function descriptions for used delay and sleep functions are in
> place, simply update the descriptions to reference to them. While at it fix
> missing colon after "Returns" in function description and move return value
> description to the end of the function description.
>
> Cc: Andrew Lunn <andrew@lunn.ch>
> Cc: Heiner Kallweit <hkallweit1@gmail.com>
> Cc: Jaroslav Kysela <perex@perex.cz>
> Cc: Takashi Iwai <tiwai@suse.com>
> Cc: netdev@vger.kernel.org
> Cc: linux-sound@vger.kernel.org
> Signed-off-by: Anna-Maria Behnsen <anna-maria@linutronix.de>
Reviewed-by: Frederic Weisbecker <frederic@kernel.org>
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: [PATCH v2 13/15] powerpc/rtas: Use fsleep() to minimize additional sleep duration
2024-09-11 5:13 ` [PATCH v2 13/15] powerpc/rtas: Use fsleep() to minimize additional sleep duration Anna-Maria Behnsen
@ 2024-10-09 16:20 ` Frederic Weisbecker
2024-10-10 9:27 ` Anna-Maria Behnsen
0 siblings, 1 reply; 47+ messages in thread
From: Frederic Weisbecker @ 2024-10-09 16:20 UTC (permalink / raw)
To: Anna-Maria Behnsen
Cc: Thomas Gleixner, Jonathan Corbet, linux-kernel, Len Brown,
Rafael J. Wysocki, Michael Ellerman, Nathan Lynch, linuxppc-dev
Le Wed, Sep 11, 2024 at 07:13:39AM +0200, Anna-Maria Behnsen a écrit :
> When commit 38f7b7067dae ("powerpc/rtas: rtas_busy_delay() improvements")
> was introduced, documentation about proper usage of sleep realted functions
related*
> was outdated.
>
> The commit message references the usage of a HZ=100 system. When using a
> 20ms sleep duration on such a system and therefore using msleep(), the
> possible additional slack will be +10ms.
>
> When the system is configured with HZ=100 the granularity of a jiffy and of
> a bucket of the lowest timer wheel level is 10ms. To make sure a timer will
> not expire early (when queueing of the timer races with an concurrent
> update of jiffies), timers are always queued into the next bucket. This is
> the reason for the maximal possible slack of 10ms.
>
> fsleep() limits the maximal possible slack to 25% by making threshold
> between usleep_range() and msleep() HZ dependent. As soon as the accuracy
> of msleep() is sufficient, the less expensive timer list timer based
> sleeping function is used instead of the more expensive hrtimer based
> usleep_range() function. The udelay() will not be used in this specific
> usecase as the lowest sleep length is larger than 1 microsecond.
Isn't udelay() for everything below 10us ?
>
> Use fsleep() directly instead of using an own heuristic for the best
> sleeping mechanism to use..
>
> Cc: Michael Ellerman <mpe@ellerman.id.au>
> Cc: Nathan Lynch <nathanl@linux.ibm.com>
> Cc: linuxppc-dev@lists.ozlabs.org
> Signed-off-by: Anna-Maria Behnsen <anna-maria@linutronix.de>
> Acked-by: Michael Ellerman <mpe@ellerman.id.au> (powerpc)
Reviewed-by: Frederic Weisbecker <frederic@kernel.org>
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: [PATCH v2 14/15] media: anysee: Fix link to outdated sleep function documentation
2024-09-11 5:13 ` [PATCH v2 14/15] media: anysee: Fix link to outdated sleep function documentation Anna-Maria Behnsen
@ 2024-10-09 16:30 ` Frederic Weisbecker
2024-10-11 10:28 ` Anna-Maria Behnsen
0 siblings, 1 reply; 47+ messages in thread
From: Frederic Weisbecker @ 2024-10-09 16:30 UTC (permalink / raw)
To: Anna-Maria Behnsen
Cc: Thomas Gleixner, Jonathan Corbet, linux-kernel, Len Brown,
Rafael J. Wysocki, Mauro Carvalho Chehab, linux-media
Le Wed, Sep 11, 2024 at 07:13:40AM +0200, Anna-Maria Behnsen a écrit :
> The TODO FIXME comment references the outdated lower limit for msleep()
> function of 20ms. As this is not right and the proper documentation of
> msleep() is now part of the function description, remove the old stuff and
> point to the up to date documentation.
>
> Cc: Mauro Carvalho Chehab <mchehab@kernel.org>
> Cc: linux-media@vger.kernel.org
> Signed-off-by: Anna-Maria Behnsen <anna-maria@linutronix.de>
> ---
> drivers/media/usb/dvb-usb-v2/anysee.c | 6 ++----
> 1 file changed, 2 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/media/usb/dvb-usb-v2/anysee.c b/drivers/media/usb/dvb-usb-v2/anysee.c
> index 8699846eb416..b2f5db961245 100644
> --- a/drivers/media/usb/dvb-usb-v2/anysee.c
> +++ b/drivers/media/usb/dvb-usb-v2/anysee.c
> @@ -55,10 +55,8 @@ static int anysee_ctrl_msg(struct dvb_usb_device *d,
>
> /* TODO FIXME: dvb_usb_generic_rw() fails rarely with error code -32
> * (EPIPE, Broken pipe). Function supports currently msleep() as a
> - * parameter but I would not like to use it, since according to
> - * Documentation/timers/timers-howto.rst it should not be used such
> - * short, under < 20ms, sleeps. Repeating failed message would be
> - * better choice as not to add unwanted delays...
> + * parameter. Check msleep() for details. Repeating failed message would
> + * be better choice as not to add unwanted delays...
Does the comment still matches any up-to-date worry? It passes 2000 ms which is
2 seconds...
Thanks.
> * Fixing that correctly is one of those or both;
> * 1) use repeat if possible
> * 2) add suitable delay
>
> --
> 2.39.2
>
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: [PATCH v2 05/15] timers: Update function descriptions of sleep/delay related functions
2024-10-06 21:49 ` Frederic Weisbecker
@ 2024-10-10 8:45 ` Anna-Maria Behnsen
2024-10-10 12:36 ` Frederic Weisbecker
0 siblings, 1 reply; 47+ messages in thread
From: Anna-Maria Behnsen @ 2024-10-10 8:45 UTC (permalink / raw)
To: Frederic Weisbecker
Cc: Thomas Gleixner, Jonathan Corbet, linux-kernel, Len Brown,
Rafael J. Wysocki, Arnd Bergmann, linux-arch
Frederic Weisbecker <frederic@kernel.org> writes:
> Le Wed, Sep 11, 2024 at 07:13:31AM +0200, Anna-Maria Behnsen a écrit :
>> A lot of commonly used functions for inserting a sleep or delay lack a
>> proper function description. Add function descriptions to all of them to
>> have important information in a central place close to the code.
>>
>> No functional change.
>>
>> Cc: Arnd Bergmann <arnd@arndb.de>
>> Cc: linux-arch@vger.kernel.org
>> Signed-off-by: Anna-Maria Behnsen <anna-maria@linutronix.de>
>> ---
>> v2:
>> - Fix typos
>> - Fix proper usage of kernel-doc return formatting
>> ---
>> include/asm-generic/delay.h | 41 +++++++++++++++++++++++++++++++----
>> include/linux/delay.h | 48 ++++++++++++++++++++++++++++++----------
>> kernel/time/sleep_timeout.c | 53 ++++++++++++++++++++++++++++++++++++++++-----
>> 3 files changed, 120 insertions(+), 22 deletions(-)
>>
>> diff --git a/include/asm-generic/delay.h b/include/asm-generic/delay.h
>> index e448ac61430c..70a1b20f3e1a 100644
>> --- a/include/asm-generic/delay.h
>> +++ b/include/asm-generic/delay.h
>> @@ -12,11 +12,39 @@ extern void __const_udelay(unsigned long xloops);
>> extern void __delay(unsigned long loops);
>>
>> /*
>> - * The weird n/20000 thing suppresses a "comparison is always false due to
>> - * limited range of data type" warning with non-const 8-bit arguments.
>> + * Implementation details:
>> + *
>> + * * The weird n/20000 thing suppresses a "comparison is always false due to
>> + * limited range of data type" warning with non-const 8-bit arguments.
>> + * * 0x10c7 is 2**32 / 1000000 (rounded up) -> udelay
>> + * * 0x5 is 2**32 / 1000000000 (rounded up) -> ndelay
>
> I can't say I'm less confused about these values but at least it
> brings a bit of light in the horizon...
:) This will be cleaned up in a second step all over the place as
suggested by Thomas already in v1. But for now, the aim is only to fix
fsleep and especially the outdated documentation of delay and sleep
related functions.
>> */
>>
>> -/* 0x10c7 is 2**32 / 1000000 (rounded up) */
>> +/**
>> + * udelay - Inserting a delay based on microseconds with busy waiting
>> + * @usec: requested delay in microseconds
>> + *
>> + * When delaying in an atomic context ndelay(), udelay() and mdelay() are the
>> + * only valid variants of delaying/sleeping to go with.
>> + *
>> + * When inserting delays in non atomic context which are shorter than the time
>> + * which is required to queue e.g. an hrtimer and to enter then the scheduler,
>> + * it is also valuable to use udelay(). But is not simple to specify a generic
>
> But it is*
>
>> + * threshold for this which will fit for all systems, but an approximation would
>
> But but?
change those two sentences into: But it is not simple to specify a
generic threshold for this which will fit for all systems. An
approximation is a threshold for all delays up to 10 microseconds.
>> + * be a threshold for all delays up to 10 microseconds.
>> + *
>> + * When having a delay which is larger than the architecture specific
>> + * %MAX_UDELAY_MS value, please make sure mdelay() is used. Otherwise a overflow
>> + * risk is given.
>> + *
>> + * Please note that ndelay(), udelay() and mdelay() may return early for several
>> + * reasons (https://lists.openwall.net/linux-kernel/2011/01/09/56):
>> + *
>> + * #. computed loops_per_jiffy too low (due to the time taken to execute the
>> + * timer interrupt.)
>> + * #. cache behaviour affecting the time it takes to execute the loop function.
>> + * #. CPU clock rate changes.
>> + */
>> #define udelay(n) \
>> ({ \
>> if (__builtin_constant_p(n)) { \
>> diff --git a/kernel/time/sleep_timeout.c b/kernel/time/sleep_timeout.c
>> index 560d17c30aa5..21f412350b15 100644
>> --- a/kernel/time/sleep_timeout.c
>> +++ b/kernel/time/sleep_timeout.c
>> @@ -281,7 +281,34 @@ EXPORT_SYMBOL_GPL(schedule_hrtimeout);
>>
>> /**
>> * msleep - sleep safely even with waitqueue interruptions
>> - * @msecs: Time in milliseconds to sleep for
>> + * @msecs: Requested sleep duration in milliseconds
>> + *
>> + * msleep() uses jiffy based timeouts for the sleep duration. The accuracy of
>> + * the resulting sleep duration depends on:
>> + *
>> + * * HZ configuration
>> + * * sleep duration (as granularity of a bucket which collects timers increases
>> + * with the timer wheel levels)
>> + *
>> + * When the timer is queued into the second level of the timer wheel the maximum
>> + * additional delay will be 12.5%. For explanation please check the detailed
>> + * description about the basics of the timer wheel. In case this is accurate
>> + * enough check which sleep length is selected to make sure required accuracy is
>> + * given. Please use therefore the following simple steps:
>> + *
>> + * #. Decide which slack is fine for the requested sleep duration - but do not
>> + * use values shorter than 1/8
>
> I'm confused, what means 1/x for a slack value? 1/8 means 125 msecs? I'm not
> even I understand what you mean by slack. Is it the bucket_expiry - expiry?
I was confused as well and had to read it twice... I would propose to
rephrase the whole function description:
/**
* msleep - sleep safely even with waitqueue interruptions
* @msecs: Requested sleep duration in milliseconds
*
* msleep() uses jiffy based timeouts for the sleep duration. Because of the
* design of the timer wheel, the maximum additional percentage delay (slack) is
* 12.5%. This is only valid for timers which will end up in the second or a
* higher level of the timer wheel. For explanation of those 12.5% please check
* the detailed description about the basics of the timer wheel.
*
* The slack of timers which will end up in the first level depends on:
*
* * sleep duration (msecs)
* * HZ configuration
*
* To make sure the sleep duration with the slack is accurate enough, a slack
* value is required (because of the design of the timer wheel it is not
* possible to define a value smaller than 12.5%). The following check makes
* clear, whether the sleep duration with the defined slack and with the HZ
* configuration will meet the constraints:
*
* ``msecs >= (MSECS_PER_TICK / slack)``
*
* Examples:
*
* * ``HZ=1000`` with ``slack=25%``: ``MSECS_PER_TICK / slack = 1 / (1/4) = 4``:
* all sleep durations greater or equal 4ms will meet the constraints.
* * ``HZ=1000`` with ``slack=12.5%``: ``MSECS_PER_TICK / slack = 1 / (1/8) = 8``:
* all sleep durations greater or equal 8ms will meet the constraints.
* * ``HZ=250`` with ``slack=25%``: ``MSECS_PER_TICK / slack = 4 / (1/4) = 16``:
* all sleep durations greater or equal 16ms will meet the constraints.
* * ``HZ=250`` with ``slack=12.5%``: ``MSECS_PER_TICK / slack = 4 / (1/8) = 32``:
* all sleep durations greater or equal 32ms will meet the constraints.
*
* See also the signal aware variant msleep_interruptible().
*/
>
> But I'm still lost...
>
Hopefully no longer :)
Thanks,
Anna-Maria
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: [PATCH v2 09/15] timers: Add a warning to usleep_range_state() for wrong order of arguments
2024-10-09 12:22 ` Frederic Weisbecker
@ 2024-10-10 9:06 ` Anna-Maria Behnsen
0 siblings, 0 replies; 47+ messages in thread
From: Anna-Maria Behnsen @ 2024-10-10 9:06 UTC (permalink / raw)
To: Frederic Weisbecker
Cc: Thomas Gleixner, Jonathan Corbet, linux-kernel, Len Brown,
Rafael J. Wysocki, Andy Whitcroft, Joe Perches
Frederic Weisbecker <frederic@kernel.org> writes:
> Le Wed, Sep 11, 2024 at 07:13:35AM +0200, Anna-Maria Behnsen a écrit :
>> There is a warning in checkpatch script that triggers, when min and max
>> arguments of usleep_range_state() are in reverse order. This check does
>> only cover callsites which uses constants. Move this check into the code as
>> a WARN_ON_ONCE() to also cover callsites not using constants and get rid of
>> it in checkpatch.
>>
>> Cc: Andy Whitcroft <apw@canonical.com>
>> Cc: Joe Perches <joe@perches.com>
>> Signed-off-by: Anna-Maria Behnsen <anna-maria@linutronix.de>
>> ---
>> kernel/time/sleep_timeout.c | 2 ++
>> scripts/checkpatch.pl | 4 ----
>> 2 files changed, 2 insertions(+), 4 deletions(-)
>>
>> diff --git a/kernel/time/sleep_timeout.c b/kernel/time/sleep_timeout.c
>> index 21f412350b15..4b805d7e1903 100644
>> --- a/kernel/time/sleep_timeout.c
>> +++ b/kernel/time/sleep_timeout.c
>> @@ -364,6 +364,8 @@ void __sched usleep_range_state(unsigned long min, unsigned long max, unsigned i
>> ktime_t exp = ktime_add_us(ktime_get(), min);
>> u64 delta = (u64)(max - min) * NSEC_PER_USEC;
>>
>> + WARN_ON_ONCE(max < min);
>> +
>
> Should it try to "fix" to avoid overflow?
>
> if WARN_ON_ONCE(max < min)
> delta = 0
yes!
>> for (;;) {
>> __set_current_state(state);
>> /* Do not return before the requested sleep time has elapsed */
>> diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
>> index 39032224d504..ba3359bdd1fa 100755
>> --- a/scripts/checkpatch.pl
>> +++ b/scripts/checkpatch.pl
>> @@ -7088,10 +7088,6 @@ sub process {
>> if ($min eq $max) {
>> WARN("USLEEP_RANGE",
>> "usleep_range should not use min == max args; see Documentation/timers/timers-howto.rst\n" . "$here\n$stat\n");
>> - } elsif ($min =~ /^\d+$/ && $max =~ /^\d+$/ &&
>> - $min > $max) {
>> - WARN("USLEEP_RANGE",
>> - "usleep_range args reversed, use min then max; see Documentation/timers/timers-howto.rst\n" . "$here\n$stat\n");
>
> Perhaps it doesn't hurt to keep the static check?
I'll keep it but drop the link to the
Documentation/timers/timers-howto.rst which will be removed.
> Thanks.
>> }
>> }
>>
>>
>> --
>> 2.39.2
>>
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: [PATCH v2 13/15] powerpc/rtas: Use fsleep() to minimize additional sleep duration
2024-10-09 16:20 ` Frederic Weisbecker
@ 2024-10-10 9:27 ` Anna-Maria Behnsen
0 siblings, 0 replies; 47+ messages in thread
From: Anna-Maria Behnsen @ 2024-10-10 9:27 UTC (permalink / raw)
To: Frederic Weisbecker
Cc: Thomas Gleixner, Jonathan Corbet, linux-kernel, Len Brown,
Rafael J. Wysocki, Michael Ellerman, Nathan Lynch, linuxppc-dev
Frederic Weisbecker <frederic@kernel.org> writes:
> Le Wed, Sep 11, 2024 at 07:13:39AM +0200, Anna-Maria Behnsen a écrit :
>> When commit 38f7b7067dae ("powerpc/rtas: rtas_busy_delay() improvements")
>> was introduced, documentation about proper usage of sleep realted functions
>
> related*
>
>> was outdated.
>>
>> The commit message references the usage of a HZ=100 system. When using a
>> 20ms sleep duration on such a system and therefore using msleep(), the
>> possible additional slack will be +10ms.
>>
>> When the system is configured with HZ=100 the granularity of a jiffy and of
>> a bucket of the lowest timer wheel level is 10ms. To make sure a timer will
>> not expire early (when queueing of the timer races with an concurrent
>> update of jiffies), timers are always queued into the next bucket. This is
>> the reason for the maximal possible slack of 10ms.
>>
>> fsleep() limits the maximal possible slack to 25% by making threshold
>> between usleep_range() and msleep() HZ dependent. As soon as the accuracy
>> of msleep() is sufficient, the less expensive timer list timer based
>> sleeping function is used instead of the more expensive hrtimer based
>> usleep_range() function. The udelay() will not be used in this specific
>> usecase as the lowest sleep length is larger than 1 microsecond.
>
> Isn't udelay() for everything below 10us ?
It's larger than 1 millisecond...
>
>>
>> Use fsleep() directly instead of using an own heuristic for the best
>> sleeping mechanism to use..
>>
>> Cc: Michael Ellerman <mpe@ellerman.id.au>
>> Cc: Nathan Lynch <nathanl@linux.ibm.com>
>> Cc: linuxppc-dev@lists.ozlabs.org
>> Signed-off-by: Anna-Maria Behnsen <anna-maria@linutronix.de>
>> Acked-by: Michael Ellerman <mpe@ellerman.id.au> (powerpc)
>
> Reviewed-by: Frederic Weisbecker <frederic@kernel.org>
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: [PATCH v2 05/15] timers: Update function descriptions of sleep/delay related functions
2024-10-10 8:45 ` Anna-Maria Behnsen
@ 2024-10-10 12:36 ` Frederic Weisbecker
2024-10-11 10:20 ` Anna-Maria Behnsen
0 siblings, 1 reply; 47+ messages in thread
From: Frederic Weisbecker @ 2024-10-10 12:36 UTC (permalink / raw)
To: Anna-Maria Behnsen
Cc: Thomas Gleixner, Jonathan Corbet, linux-kernel, Len Brown,
Rafael J. Wysocki, Arnd Bergmann, linux-arch
Le Thu, Oct 10, 2024 at 10:45:03AM +0200, Anna-Maria Behnsen a écrit :
> Frederic Weisbecker <frederic@kernel.org> writes:
> > I can't say I'm less confused about these values but at least it
> > brings a bit of light in the horizon...
>
> :) This will be cleaned up in a second step all over the place as
> suggested by Thomas already in v1. But for now, the aim is only to fix
> fsleep and especially the outdated documentation of delay and sleep
> related functions.
Sure.
>
> >> */
> >>
> >> -/* 0x10c7 is 2**32 / 1000000 (rounded up) */
> >> +/**
> >> + * udelay - Inserting a delay based on microseconds with busy waiting
> >> + * @usec: requested delay in microseconds
> >> + *
> >> + * When delaying in an atomic context ndelay(), udelay() and mdelay() are the
> >> + * only valid variants of delaying/sleeping to go with.
> >> + *
> >> + * When inserting delays in non atomic context which are shorter than the time
> >> + * which is required to queue e.g. an hrtimer and to enter then the scheduler,
> >> + * it is also valuable to use udelay(). But is not simple to specify a generic
> >
> > But it is*
> >
> >> + * threshold for this which will fit for all systems, but an approximation would
> >
> > But but?
>
> change those two sentences into: But it is not simple to specify a
> generic threshold for this which will fit for all systems. An
> approximation is a threshold for all delays up to 10 microseconds.
Very good!
> >> @@ -281,7 +281,34 @@ EXPORT_SYMBOL_GPL(schedule_hrtimeout);
> >>
> >> /**
> >> * msleep - sleep safely even with waitqueue interruptions
> >> - * @msecs: Time in milliseconds to sleep for
> >> + * @msecs: Requested sleep duration in milliseconds
> >> + *
> >> + * msleep() uses jiffy based timeouts for the sleep duration. The accuracy of
> >> + * the resulting sleep duration depends on:
> >> + *
> >> + * * HZ configuration
> >> + * * sleep duration (as granularity of a bucket which collects timers increases
> >> + * with the timer wheel levels)
> >> + *
> >> + * When the timer is queued into the second level of the timer wheel the maximum
> >> + * additional delay will be 12.5%. For explanation please check the detailed
> >> + * description about the basics of the timer wheel. In case this is accurate
> >> + * enough check which sleep length is selected to make sure required accuracy is
> >> + * given. Please use therefore the following simple steps:
> >> + *
> >> + * #. Decide which slack is fine for the requested sleep duration - but do not
> >> + * use values shorter than 1/8
> >
> > I'm confused, what means 1/x for a slack value? 1/8 means 125 msecs? I'm not
> > even I understand what you mean by slack. Is it the bucket_expiry - expiry?
>
> I was confused as well and had to read it twice... I would propose to
> rephrase the whole function description:
>
>
> /**
> * msleep - sleep safely even with waitqueue interruptions
> * @msecs: Requested sleep duration in milliseconds
> *
> * msleep() uses jiffy based timeouts for the sleep duration. Because of the
> * design of the timer wheel, the maximum additional percentage delay (slack) is
> * 12.5%. This is only valid for timers which will end up in the second or a
> * higher level of the timer wheel. For explanation of those 12.5% please check
> * the detailed description about the basics of the timer wheel.
I've never realized this constant worst percentage of slack. Would be nice to mention
that somewhere in kernel/time/timer.c
However this doesn't need a second to apply. It only takes crossing levels above
0. Or am I missing something?
> *
> * The slack of timers which will end up in the first level depends on:
> *
> * * sleep duration (msecs)
> * * HZ configuration
> *
> * To make sure the sleep duration with the slack is accurate enough, a slack
> * value is required (because of the design of the timer wheel it is not
But where is it required?
> * possible to define a value smaller than 12.5%). The following check makes
> * clear, whether the sleep duration with the defined slack and with the HZ
> * configuration will meet the constraints:
> *
> * ``msecs >= (MSECS_PER_TICK / slack)``
> *
> * Examples:
> *
> * * ``HZ=1000`` with ``slack=25%``: ``MSECS_PER_TICK / slack = 1 / (1/4) = 4``:
> * all sleep durations greater or equal 4ms will meet the constraints.
> * * ``HZ=1000`` with ``slack=12.5%``: ``MSECS_PER_TICK / slack = 1 / (1/8) = 8``:
> * all sleep durations greater or equal 8ms will meet the constraints.
> * * ``HZ=250`` with ``slack=25%``: ``MSECS_PER_TICK / slack = 4 / (1/4) = 16``:
> * all sleep durations greater or equal 16ms will meet the constraints.
> * * ``HZ=250`` with ``slack=12.5%``: ``MSECS_PER_TICK / slack = 4 / (1/8) = 32``:
> * all sleep durations greater or equal 32ms will meet the constraints.
But who defines those slacks and where? I'm even more confused now...
> *
> * See also the signal aware variant msleep_interruptible().
> */
>
> >
> > But I'm still lost...
> >
>
> Hopefully no longer :)
Well...
> Thanks,
>
> Anna-Maria
>
>
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: [PATCH v2 15/15] timers/Documentation: Cleanup delay/sleep documentation
2024-09-11 5:13 ` [PATCH v2 15/15] timers/Documentation: Cleanup delay/sleep documentation Anna-Maria Behnsen
@ 2024-10-10 13:10 ` Frederic Weisbecker
0 siblings, 0 replies; 47+ messages in thread
From: Frederic Weisbecker @ 2024-10-10 13:10 UTC (permalink / raw)
To: Anna-Maria Behnsen
Cc: Thomas Gleixner, Jonathan Corbet, linux-kernel, Len Brown,
Rafael J. Wysocki
Le Wed, Sep 11, 2024 at 07:13:41AM +0200, Anna-Maria Behnsen a écrit :
> The documentation which tries to give advises how to properly inserting
advices*
> delays or sleeps is outdated. The file name is 'timers-howto.rst' which
> might be missleading as it is only about delay and sleep mechanisms and not
misleading*
> how to use timers.
>
> Update the documentation by integrating the important parts from the
> related function descriptions and move it all into a self explaining file
> with the name "delay_sleep_functions.rst".
>
> Signed-off-by: Anna-Maria Behnsen <anna-maria@linutronix.de>
> ---
> Documentation/timers/delay_sleep_functions.rst | 122 +++++++++++++++++++++++++
> Documentation/timers/index.rst | 2 +-
> Documentation/timers/timers-howto.rst | 115 -----------------------
> 3 files changed, 123 insertions(+), 116 deletions(-)
>
> diff --git a/Documentation/timers/delay_sleep_functions.rst b/Documentation/timers/delay_sleep_functions.rst
> new file mode 100644
> index 000000000000..05d7c3c8fbe8
> --- /dev/null
> +++ b/Documentation/timers/delay_sleep_functions.rst
> @@ -0,0 +1,122 @@
> +.. SPDX-License-Identifier: GPL-2.0
> +
> +Delay and sleep mechanisms
> +==========================
> +
> +This document seeks to answer the common question: "What is the
> +RightWay (TM) to insert a delay?"
> +
> +This question is most often faced by driver writers who have to
> +deal with hardware delays and who may not be the most intimately
> +familiar with the inner workings of the Linux Kernel.
> +
> +The following table gives a rough overview about the existing function
> +'families' and their limitations. This overview table does not replace the
> +reading of the function description before usage!
> +
> +.. list-table::
> + :widths: 20 20 20 20 20
> + :header-rows: 2
> +
> + * -
> + - `*delay()`
> + - `usleep_range*()`
> + - `*sleep()`
> + - `fsleep()`
> + * -
> + - busy-wait loop
> + - hrtimers based
> + - timer list timers based
> + - combines the others
> + * - Usage in atomic Context
> + - yes
> + - no
> + - no
> + - no
> + * - precise on "short intervals"
> + - yes
> + - yes
> + - depends
> + - yes
> + * - precise on "long intervals"
> + - Do not use!
> + - yes
> + - max 12.5% slack
> + - yes
> + * - interruptible variant
> + - no
> + - yes
> + - yes
> + - no
> +
> +A generic advice for non atomic contexts could be:
> +
> +#. Use `fsleep()` whenever unsure (as it combines all the advantages of the
> + others)
> +#. Use `*sleep()` whenever possible
> +#. Use `usleep_range*()` whenever accuracy of `*sleep()` is not sufficient
> +#. Use `*delay()` for very, very short delays
> +
> +Find some more detailed information about the function 'families' in the next
> +sections.
> +
> +`*delay()` family of functions
> +------------------------------
> +
> +These functions use the jiffy estimation of clock speed and will busy wait for
> +enough loop cycles to achieve the desired delay. udelay() is the basic
> +implementation and ndelay() as well as mdelay() are variants.
> +
> +These functions are mainly used to add a delay in atomic context. Please make
> +sure to ask yourself before adding a delay in atomic context: Is this really
> +required?
> +
> +.. kernel-doc:: include/asm-generic/delay.h
> + :identifiers: udelay ndelay
> +
> +.. kernel-doc:: include/linux/delay.h
> + :identifiers: mdelay
> +
> +
> +`usleep_range*()` and `*sleep()` family of functions
> +----------------------------------------------------
> +
> +These functions uses hrtimers or timer list timers to provide the requested
use*
> +sleeping duration. For a decision which function is the right one to use, take
I'm not a native speaker but perhaps "In order to decide which function..." is
better...
> +some basic information into account:
> +
> +#. hrtimers are more expensive as they are using an rb-tree (instead of hashing)
> +#. hrtimers are more expensive when the requested sleeping duration is the first
> + timer which means real hardware has to be programmed
> +#. timer list timers always providing some sort of slack as they are jiffy
provide*
> + based
> +
> +The generic advice is repeated here:
> +
> +#. Use `fsleep()` whenever unsure (as it combines all the advantages of the
> + others)
> +#. Use `*sleep()` whenever possible
> +#. Use `usleep_range*()` whenever accuracy of `*sleep()` is not sufficient
> +
> +First check fsleep() function description and to learn more about accuracy,
> +please check msleep() function description.
> +
> +
> +`usleep_range*()`
> +~~~~~~~~~~~~~~~~~
> +
> +.. kernel-doc:: include/linux/delay.h
> + :identifiers: usleep_range usleep_range_idle
> +
> +.. kernel-doc:: kernel/time/sleep_timeout.c
> + :identifiers: usleep_range_state
> +
> +
> +`*sleep()`
> +~~~~~~~~~~
> +
> +.. kernel-doc:: kernel/time/sleep_timeout.c
> + :identifiers: msleep msleep_interruptible
> +
> +.. kernel-doc:: include/linux/delay.h
> + :identifiers: ssleep fsleep
Reviewed-by: Frederic Weisbecker <frederic@kernel.org>
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: [PATCH v2 05/15] timers: Update function descriptions of sleep/delay related functions
2024-10-10 12:36 ` Frederic Weisbecker
@ 2024-10-11 10:20 ` Anna-Maria Behnsen
2024-10-11 12:22 ` Frederic Weisbecker
0 siblings, 1 reply; 47+ messages in thread
From: Anna-Maria Behnsen @ 2024-10-11 10:20 UTC (permalink / raw)
To: Frederic Weisbecker
Cc: Thomas Gleixner, Jonathan Corbet, linux-kernel, Len Brown,
Rafael J. Wysocki, Arnd Bergmann, linux-arch
Frederic Weisbecker <frederic@kernel.org> writes:
> Le Thu, Oct 10, 2024 at 10:45:03AM +0200, Anna-Maria Behnsen a écrit :
>> Frederic Weisbecker <frederic@kernel.org> writes:
>> >> @@ -281,7 +281,34 @@ EXPORT_SYMBOL_GPL(schedule_hrtimeout);
>> >>
>> >> /**
>> >> * msleep - sleep safely even with waitqueue interruptions
>> >> - * @msecs: Time in milliseconds to sleep for
>> >> + * @msecs: Requested sleep duration in milliseconds
>> >> + *
>> >> + * msleep() uses jiffy based timeouts for the sleep duration. The accuracy of
>> >> + * the resulting sleep duration depends on:
>> >> + *
>> >> + * * HZ configuration
>> >> + * * sleep duration (as granularity of a bucket which collects timers increases
>> >> + * with the timer wheel levels)
>> >> + *
>> >> + * When the timer is queued into the second level of the timer wheel the maximum
>> >> + * additional delay will be 12.5%. For explanation please check the detailed
>> >> + * description about the basics of the timer wheel. In case this is accurate
>> >> + * enough check which sleep length is selected to make sure required accuracy is
>> >> + * given. Please use therefore the following simple steps:
>> >> + *
>> >> + * #. Decide which slack is fine for the requested sleep duration - but do not
>> >> + * use values shorter than 1/8
>> >
>> > I'm confused, what means 1/x for a slack value? 1/8 means 125 msecs? I'm not
>> > even I understand what you mean by slack. Is it the bucket_expiry - expiry?
>>
>> I was confused as well and had to read it twice... I would propose to
>> rephrase the whole function description:
>>
>>
>> /**
>> * msleep - sleep safely even with waitqueue interruptions
>> * @msecs: Requested sleep duration in milliseconds
>> *
>> * msleep() uses jiffy based timeouts for the sleep duration. Because of the
>> * design of the timer wheel, the maximum additional percentage delay (slack) is
>> * 12.5%. This is only valid for timers which will end up in the second or a
>> * higher level of the timer wheel. For explanation of those 12.5% please check
>> * the detailed description about the basics of the timer wheel.
>
> I've never realized this constant worst percentage of slack. Would be nice to mention
> that somewhere in kernel/time/timer.c
Yes, we can explicitly add it (I will put it on the TODO list). It's
possible to calculate it on your own with the overview of levels and
granularity,...
> However this doesn't need a second to apply. It only takes crossing levels above
> 0. Or am I missing something?
s/the second/level 1/
more clear? Then it's the same number as used in the timer wheel
documentation.
>> *
>> * The slack of timers which will end up in the first level depends on:
>> *
Same here: s/the first level/level 0/
>> * * sleep duration (msecs)
>> * * HZ configuration
>> *
>> * To make sure the sleep duration with the slack is accurate enough, a slack
>> * value is required (because of the design of the timer wheel it is not
>
> But where is it required?
The callsite has to decide which accuracy/slack is required for their
use case (this was also part of the discussion which leads to this
queue).
>> * possible to define a value smaller than 12.5%). The following check makes
>> * clear, whether the sleep duration with the defined slack and with the HZ
>> * configuration will meet the constraints:
>> *
>> * ``msecs >= (MSECS_PER_TICK / slack)``
>> *
>> * Examples:
>> *
>> * * ``HZ=1000`` with ``slack=25%``: ``MSECS_PER_TICK / slack = 1 / (1/4) = 4``:
>> * all sleep durations greater or equal 4ms will meet the constraints.
>> * * ``HZ=1000`` with ``slack=12.5%``: ``MSECS_PER_TICK / slack = 1 / (1/8) = 8``:
>> * all sleep durations greater or equal 8ms will meet the constraints.
>> * * ``HZ=250`` with ``slack=25%``: ``MSECS_PER_TICK / slack = 4 / (1/4) = 16``:
>> * all sleep durations greater or equal 16ms will meet the constraints.
>> * * ``HZ=250`` with ``slack=12.5%``: ``MSECS_PER_TICK / slack = 4 / (1/8) = 32``:
>> * all sleep durations greater or equal 32ms will meet the constraints.
>
> But who defines those slacks and where? I'm even more confused now...
I think I know where the confusion comes from. I rephrase it once more
and turned around the calculation:
/**
* msleep - sleep safely even with waitqueue interruptions
* @msecs: Requested sleep duration in milliseconds
*
* msleep() uses jiffy based timeouts for the sleep duration. Because of the
* design of the timer wheel, the maximum additional percentage delay (slack) is
* 12.5%. This is only valid for timers which will end up in level 1 or a
* higher level of the timer wheel. For explanation of those 12.5% please check
* the detailed description about the basics of the timer wheel.
*
* The slack of timers which will end up in level 0 depends on sleep
* duration (msecs) and HZ configuration and can be calculated in the
* following way (with the timer wheel design restriction that the slack
* is not less than 12.5%):
*
* ``slack = MSECS_PER_TICK / msecs``
*
* When the allowed slack of the callsite is known, the calculation
* could be turned around to find the minimal allowed sleep duration to meet
* the constraints. For example:
*
* * ``HZ=1000`` with ``slack=25%``: ``MSECS_PER_TICK / slack = 1 / (1/4) = 4``:
* all sleep durations greater or equal 4ms will meet the constraints.
* * ``HZ=1000`` with ``slack=12.5%``: ``MSECS_PER_TICK / slack = 1 / (1/8) = 8``:
* all sleep durations greater or equal 8ms will meet the constraints.
* * ``HZ=250`` with ``slack=25%``: ``MSECS_PER_TICK / slack = 4 / (1/4) = 16``:
* all sleep durations greater or equal 16ms will meet the constraints.
* * ``HZ=250`` with ``slack=12.5%``: ``MSECS_PER_TICK / slack = 4 / (1/8) = 32``:
* all sleep durations greater or equal 32ms will meet the constraints.
*
* See also the signal aware variant msleep_interruptible().
*/
Hopefully this attempt clarifies the confusion?
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: [PATCH v2 14/15] media: anysee: Fix link to outdated sleep function documentation
2024-10-09 16:30 ` Frederic Weisbecker
@ 2024-10-11 10:28 ` Anna-Maria Behnsen
0 siblings, 0 replies; 47+ messages in thread
From: Anna-Maria Behnsen @ 2024-10-11 10:28 UTC (permalink / raw)
To: Frederic Weisbecker
Cc: Thomas Gleixner, Jonathan Corbet, linux-kernel, Len Brown,
Rafael J. Wysocki, Mauro Carvalho Chehab, linux-media, bigeasy
Frederic Weisbecker <frederic@kernel.org> writes:
> Le Wed, Sep 11, 2024 at 07:13:40AM +0200, Anna-Maria Behnsen a écrit :
>> The TODO FIXME comment references the outdated lower limit for msleep()
>> function of 20ms. As this is not right and the proper documentation of
>> msleep() is now part of the function description, remove the old stuff and
>> point to the up to date documentation.
>>
>> Cc: Mauro Carvalho Chehab <mchehab@kernel.org>
>> Cc: linux-media@vger.kernel.org
>> Signed-off-by: Anna-Maria Behnsen <anna-maria@linutronix.de>
>> ---
>> drivers/media/usb/dvb-usb-v2/anysee.c | 6 ++----
>> 1 file changed, 2 insertions(+), 4 deletions(-)
>>
>> diff --git a/drivers/media/usb/dvb-usb-v2/anysee.c b/drivers/media/usb/dvb-usb-v2/anysee.c
>> index 8699846eb416..b2f5db961245 100644
>> --- a/drivers/media/usb/dvb-usb-v2/anysee.c
>> +++ b/drivers/media/usb/dvb-usb-v2/anysee.c
>> @@ -55,10 +55,8 @@ static int anysee_ctrl_msg(struct dvb_usb_device *d,
>>
>> /* TODO FIXME: dvb_usb_generic_rw() fails rarely with error code -32
>> * (EPIPE, Broken pipe). Function supports currently msleep() as a
>> - * parameter but I would not like to use it, since according to
>> - * Documentation/timers/timers-howto.rst it should not be used such
>> - * short, under < 20ms, sleeps. Repeating failed message would be
>> - * better choice as not to add unwanted delays...
>> + * parameter. Check msleep() for details. Repeating failed message would
>> + * be better choice as not to add unwanted delays...
>
> Does the comment still matches any up-to-date worry? It passes 2000 ms which is
> 2 seconds...
I had a closer look at it: dvb_usb_generic_rw() is no longer used. The
v2 interfaces are used anyway and this uses usleep_range() instead of
msleep().
I updated the patch and also talked to Sebastian. Will send an update
with v3 which removes and updates the comments.
> Thanks.
>
>> * Fixing that correctly is one of those or both;
>> * 1) use repeat if possible
>> * 2) add suitable delay
>>
>> --
>> 2.39.2
>>
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: [PATCH v2 05/15] timers: Update function descriptions of sleep/delay related functions
2024-10-11 10:20 ` Anna-Maria Behnsen
@ 2024-10-11 12:22 ` Frederic Weisbecker
0 siblings, 0 replies; 47+ messages in thread
From: Frederic Weisbecker @ 2024-10-11 12:22 UTC (permalink / raw)
To: Anna-Maria Behnsen
Cc: Thomas Gleixner, Jonathan Corbet, linux-kernel, Len Brown,
Rafael J. Wysocki, Arnd Bergmann, linux-arch
Le Fri, Oct 11, 2024 at 12:20:20PM +0200, Anna-Maria Behnsen a écrit :
> Frederic Weisbecker <frederic@kernel.org> writes:
> > However this doesn't need a second to apply. It only takes crossing levels above
> > 0. Or am I missing something?
>
> s/the second/level 1/
>
> more clear? Then it's the same number as used in the timer wheel
> documentation.
Oh right! I was confused with second (s) and 2nd. Yes much better.
>
> >> *
> >> * The slack of timers which will end up in the first level depends on:
> >> *
>
> Same here: s/the first level/level 0/
Much better !
>
> >> * * sleep duration (msecs)
> >> * * HZ configuration
> >> *
> >> * To make sure the sleep duration with the slack is accurate enough, a slack
> >> * value is required (because of the design of the timer wheel it is not
> >
> > But where is it required?
>
> The callsite has to decide which accuracy/slack is required for their
> use case (this was also part of the discussion which leads to this
> queue).
>
> >> * possible to define a value smaller than 12.5%). The following check makes
> >> * clear, whether the sleep duration with the defined slack and with the HZ
> >> * configuration will meet the constraints:
> >> *
> >> * ``msecs >= (MSECS_PER_TICK / slack)``
> >> *
> >> * Examples:
> >> *
> >> * * ``HZ=1000`` with ``slack=25%``: ``MSECS_PER_TICK / slack = 1 / (1/4) = 4``:
> >> * all sleep durations greater or equal 4ms will meet the constraints.
> >> * * ``HZ=1000`` with ``slack=12.5%``: ``MSECS_PER_TICK / slack = 1 / (1/8) = 8``:
> >> * all sleep durations greater or equal 8ms will meet the constraints.
> >> * * ``HZ=250`` with ``slack=25%``: ``MSECS_PER_TICK / slack = 4 / (1/4) = 16``:
> >> * all sleep durations greater or equal 16ms will meet the constraints.
> >> * * ``HZ=250`` with ``slack=12.5%``: ``MSECS_PER_TICK / slack = 4 / (1/8) = 32``:
> >> * all sleep durations greater or equal 32ms will meet the constraints.
> >
> > But who defines those slacks and where? I'm even more confused now...
>
> I think I know where the confusion comes from. I rephrase it once more
> and turned around the calculation:
>
> /**
> * msleep - sleep safely even with waitqueue interruptions
> * @msecs: Requested sleep duration in milliseconds
> *
> * msleep() uses jiffy based timeouts for the sleep duration. Because of the
> * design of the timer wheel, the maximum additional percentage delay (slack) is
> * 12.5%. This is only valid for timers which will end up in level 1 or a
> * higher level of the timer wheel. For explanation of those 12.5% please check
> * the detailed description about the basics of the timer wheel.
> *
> * The slack of timers which will end up in level 0 depends on sleep
> * duration (msecs) and HZ configuration and can be calculated in the
> * following way (with the timer wheel design restriction that the slack
> * is not less than 12.5%):
> *
> * ``slack = MSECS_PER_TICK / msecs``
> *
> * When the allowed slack of the callsite is known, the calculation
> * could be turned around to find the minimal allowed sleep duration to meet
> * the constraints. For example:
> *
> * * ``HZ=1000`` with ``slack=25%``: ``MSECS_PER_TICK / slack = 1 / (1/4) = 4``:
> * all sleep durations greater or equal 4ms will meet the constraints.
> * * ``HZ=1000`` with ``slack=12.5%``: ``MSECS_PER_TICK / slack = 1 / (1/8) = 8``:
> * all sleep durations greater or equal 8ms will meet the constraints.
> * * ``HZ=250`` with ``slack=25%``: ``MSECS_PER_TICK / slack = 4 / (1/4) = 16``:
> * all sleep durations greater or equal 16ms will meet the constraints.
> * * ``HZ=250`` with ``slack=12.5%``: ``MSECS_PER_TICK / slack = 4 / (1/8) = 32``:
> * all sleep durations greater or equal 32ms will meet the constraints.
> *
> * See also the signal aware variant msleep_interruptible().
> */
>
> Hopefully this attempt clarifies the confusion?
>
Yes now it's perfectly clear!
Please add: Reviewed-by: Frederic Weisbecker <frederic@kernel.org>
Thanks.
^ permalink raw reply [flat|nested] 47+ messages in thread
end of thread, other threads:[~2024-10-11 12:22 UTC | newest]
Thread overview: 47+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-09-11 5:13 [PATCH v2 00/15] timers: Cleanup delay/sleep related mess Anna-Maria Behnsen
2024-09-11 5:13 ` [PATCH v2 01/15] MAINTAINERS: Add missing file include/linux/delay.h Anna-Maria Behnsen
2024-10-01 20:11 ` Frederic Weisbecker
2024-09-11 5:13 ` [PATCH v2 02/15] timers: Move *sleep*() and timeout functions into a separate file Anna-Maria Behnsen
2024-10-01 20:45 ` Frederic Weisbecker
2024-09-11 5:13 ` [PATCH v2 03/15] timers: Update schedule_[hr]timeout*() related function descriptions Anna-Maria Behnsen
2024-10-01 21:16 ` Frederic Weisbecker
2024-09-11 5:13 ` [PATCH v2 04/15] timers: Rename usleep_idle_range() to usleep_range_idle() Anna-Maria Behnsen
2024-09-11 5:13 ` [PATCH v2 05/15] timers: Update function descriptions of sleep/delay related functions Anna-Maria Behnsen
2024-10-06 21:49 ` Frederic Weisbecker
2024-10-10 8:45 ` Anna-Maria Behnsen
2024-10-10 12:36 ` Frederic Weisbecker
2024-10-11 10:20 ` Anna-Maria Behnsen
2024-10-11 12:22 ` Frederic Weisbecker
2024-09-11 5:13 ` [PATCH v2 06/15] delay: Rework udelay and ndelay Anna-Maria Behnsen
2024-09-23 15:40 ` Anna-Maria Behnsen
2024-10-08 14:24 ` Frederic Weisbecker
2024-09-11 5:13 ` [PATCH v2 07/15] timers: Adjust flseep() to reflect reality Anna-Maria Behnsen
2024-10-08 21:45 ` Frederic Weisbecker
2024-09-11 5:13 ` [PATCH v2 08/15] mm/damon/core: Use generic upper bound recommondation for usleep_range() Anna-Maria Behnsen
2024-10-09 12:01 ` Frederic Weisbecker
2024-09-11 5:13 ` [PATCH v2 09/15] timers: Add a warning to usleep_range_state() for wrong order of arguments Anna-Maria Behnsen
2024-09-11 6:41 ` Joe Perches
2024-09-11 7:45 ` Anna-Maria Behnsen
2024-10-09 12:22 ` Frederic Weisbecker
2024-10-10 9:06 ` Anna-Maria Behnsen
2024-09-11 5:13 ` [PATCH v2 10/15] checkpatch: Remove broken sleep/delay related checks Anna-Maria Behnsen
2024-09-11 6:44 ` Joe Perches
2024-09-11 7:41 ` Anna-Maria Behnsen
2024-10-09 12:45 ` Frederic Weisbecker
2024-09-11 5:13 ` [PATCH v2 11/15] regulator: core: Use fsleep() to get best sleep mechanism Anna-Maria Behnsen
2024-10-09 13:37 ` Frederic Weisbecker
2024-09-11 5:13 ` [PATCH v2 12/15] iopoll/regmap/phy/snd: Fix comment referencing outdated timer documentation Anna-Maria Behnsen
2024-09-11 12:08 ` Andrew Lunn
2024-10-09 16:14 ` Frederic Weisbecker
2024-09-11 5:13 ` [PATCH v2 13/15] powerpc/rtas: Use fsleep() to minimize additional sleep duration Anna-Maria Behnsen
2024-10-09 16:20 ` Frederic Weisbecker
2024-10-10 9:27 ` Anna-Maria Behnsen
2024-09-11 5:13 ` [PATCH v2 14/15] media: anysee: Fix link to outdated sleep function documentation Anna-Maria Behnsen
2024-10-09 16:30 ` Frederic Weisbecker
2024-10-11 10:28 ` Anna-Maria Behnsen
2024-09-11 5:13 ` [PATCH v2 15/15] timers/Documentation: Cleanup delay/sleep documentation Anna-Maria Behnsen
2024-10-10 13:10 ` Frederic Weisbecker
2024-09-16 20:20 ` [PATCH v2 00/15] timers: Cleanup delay/sleep related mess Christophe JAILLET
2024-09-17 5:22 ` Christophe JAILLET
2024-09-23 15:12 ` Anna-Maria Behnsen
2024-10-02 15:02 ` Thomas Gleixner
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox