* [PATCH 00/15] timers: Cleanup delay/sleep related mess
@ 2024-09-04 13:04 Anna-Maria Behnsen
2024-09-04 13:04 ` [PATCH 01/15] timers: Rename next_expiry_recalc() to be unique Anna-Maria Behnsen
` (16 more replies)
0 siblings, 17 replies; 43+ messages in thread
From: Anna-Maria Behnsen @ 2024-09-04 13:04 UTC (permalink / raw)
To: Frederic Weisbecker, Thomas Gleixner, Jonathan Corbet
Cc: linux-kernel, Len Brown, Rafael J. Wysocki, Anna-Maria Behnsen,
Peter Zijlstra, SeongJae Park, Andrew Morton, damon, linux-mm,
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:
- Minor changes (naming and typo fixes)
- 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
Cc: linux-kernel@vger.kernel.org
Cc: Len Brown <len.brown@intel.com>
Cc: Rafael J. Wysocki <rafael@kernel.org>
To: Frederic Weisbecker <frederic@kernel.org>
To: Thomas Gleixner <tglx@linutronix.de>
To: Jonathan Corbet <corbet@lwn.net>
Signed-off-by: Anna-Maria Behnsen <anna-maria@linutronix.de>
Thanks,
Anna-Maria
---
Anna-Maria Behnsen (15):
timers: Rename next_expiry_recalc() to be unique
cpu: Use already existing usleep_range()
Comments: Fix wrong singular form of jiffies
timers: Move *sleep*() and timeout functions into a separate file
timers: Rename sleep_idle_range() to sleep_range_idle()
timers: Update function descriptions of sleep/delay related functions
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/admin-guide/media/vivid.rst | 2 +-
Documentation/dev-tools/checkpatch.rst | 6 -
Documentation/timers/delay_sleep_functions.rst | 122 +++++++
Documentation/timers/index.rst | 2 +-
Documentation/timers/timers-howto.rst | 115 -------
.../sp_SP/scheduler/sched-design-CFS.rst | 2 +-
MAINTAINERS | 2 +
arch/arm/mach-versatile/spc.c | 2 +-
arch/m68k/q40/q40ints.c | 2 +-
arch/powerpc/kernel/rtas.c | 21 +-
arch/x86/kernel/cpu/mce/dev-mcelog.c | 2 +-
drivers/char/ipmi/ipmi_ssif.c | 2 +-
drivers/dma-buf/st-dma-fence.c | 2 +-
drivers/gpu/drm/i915/gem/i915_gem_wait.c | 2 +-
drivers/gpu/drm/i915/gt/selftest_execlists.c | 4 +-
drivers/gpu/drm/i915/i915_utils.c | 2 +-
drivers/gpu/drm/v3d/v3d_bo.c | 2 +-
drivers/isdn/mISDN/dsp_cmx.c | 2 +-
drivers/media/usb/dvb-usb-v2/anysee.c | 6 +-
drivers/net/ethernet/marvell/mvmdio.c | 2 +-
drivers/regulator/core.c | 33 +-
fs/xfs/xfs_buf.h | 2 +-
include/asm-generic/delay.h | 46 ++-
include/linux/delay.h | 79 ++++-
include/linux/iopoll.h | 24 +-
include/linux/jiffies.h | 2 +-
include/linux/phy.h | 7 +-
include/linux/regmap.h | 18 +-
include/linux/timekeeper_internal.h | 2 +-
kernel/cpu.c | 2 +-
kernel/time/Makefile | 2 +-
kernel/time/alarmtimer.c | 2 +-
kernel/time/clockevents.c | 2 +-
kernel/time/hrtimer.c | 122 +------
kernel/time/posix-timers.c | 4 +-
kernel/time/sleep_timeout.c | 363 +++++++++++++++++++++
kernel/time/timer.c | 210 +-----------
lib/Kconfig.debug | 2 +-
mm/damon/core.c | 5 +-
net/batman-adv/types.h | 2 +-
scripts/checkpatch.pl | 38 ---
sound/soc/sof/ops.h | 6 +-
42 files changed, 668 insertions(+), 607 deletions(-)
^ permalink raw reply [flat|nested] 43+ messages in thread
* [PATCH 01/15] timers: Rename next_expiry_recalc() to be unique
2024-09-04 13:04 [PATCH 00/15] timers: Cleanup delay/sleep related mess Anna-Maria Behnsen
@ 2024-09-04 13:04 ` Anna-Maria Behnsen
2024-09-06 13:25 ` Frederic Weisbecker
2024-09-08 18:58 ` [tip: timers/core] " tip-bot2 for Anna-Maria Behnsen
2024-09-04 13:04 ` [PATCH 02/15] cpu: Use already existing usleep_range() Anna-Maria Behnsen
` (15 subsequent siblings)
16 siblings, 2 replies; 43+ messages in thread
From: Anna-Maria Behnsen @ 2024-09-04 13:04 UTC (permalink / raw)
To: Frederic Weisbecker, Thomas Gleixner, Jonathan Corbet
Cc: linux-kernel, Len Brown, Rafael J. Wysocki, Anna-Maria Behnsen
next_expiry_recalc is the name of a function as well as the name of a
struct member of struct timer_base. This might lead to confusion.
Rename next_expiry_recalc() to timer_recalc_next_expiry(). No functional
change.
Signed-off-by: Anna-Maria Behnsen <anna-maria@linutronix.de>
---
kernel/time/timer.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/kernel/time/timer.c b/kernel/time/timer.c
index 311ea459b976..5e021a2d8d61 100644
--- a/kernel/time/timer.c
+++ b/kernel/time/timer.c
@@ -1900,7 +1900,7 @@ static int next_pending_bucket(struct timer_base *base, unsigned offset,
*
* Store next expiry time in base->next_expiry.
*/
-static void next_expiry_recalc(struct timer_base *base)
+static void timer_recalc_next_expiry(struct timer_base *base)
{
unsigned long clk, next, adj;
unsigned lvl, offset = 0;
@@ -2009,7 +2009,7 @@ static unsigned long next_timer_interrupt(struct timer_base *base,
unsigned long basej)
{
if (base->next_expiry_recalc)
- next_expiry_recalc(base);
+ timer_recalc_next_expiry(base);
/*
* Move next_expiry for the empty base into the future to prevent an
@@ -2413,7 +2413,7 @@ static inline void __run_timers(struct timer_base *base)
* jiffies to avoid endless requeuing to current jiffies.
*/
base->clk++;
- next_expiry_recalc(base);
+ timer_recalc_next_expiry(base);
while (levels--)
expire_timers(base, heads + levels);
--
2.39.2
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [PATCH 02/15] cpu: Use already existing usleep_range()
2024-09-04 13:04 [PATCH 00/15] timers: Cleanup delay/sleep related mess Anna-Maria Behnsen
2024-09-04 13:04 ` [PATCH 01/15] timers: Rename next_expiry_recalc() to be unique Anna-Maria Behnsen
@ 2024-09-04 13:04 ` Anna-Maria Behnsen
2024-09-06 13:27 ` Frederic Weisbecker
2024-09-08 18:58 ` [tip: timers/core] " tip-bot2 for Anna-Maria Behnsen
2024-09-04 13:04 ` [PATCH 03/15] Comments: Fix wrong singular form of jiffies Anna-Maria Behnsen
` (14 subsequent siblings)
16 siblings, 2 replies; 43+ messages in thread
From: Anna-Maria Behnsen @ 2024-09-04 13:04 UTC (permalink / raw)
To: Frederic Weisbecker, Thomas Gleixner, Jonathan Corbet
Cc: linux-kernel, Len Brown, Rafael J. Wysocki, Anna-Maria Behnsen,
Peter Zijlstra
usleep_range() is a wrapper arount usleep_range_state() which hands in
TASK_UNTINTERRUPTIBLE as state argument.
Use already exising wrapper usleep_range(). No functional change.
Cc: Peter Zijlstra <peterz@infradead.org>
Signed-off-by: Anna-Maria Behnsen <anna-maria@linutronix.de>
---
kernel/cpu.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/kernel/cpu.c b/kernel/cpu.c
index 1209ddaec026..031a2c15481b 100644
--- a/kernel/cpu.c
+++ b/kernel/cpu.c
@@ -330,7 +330,7 @@ static bool cpuhp_wait_for_sync_state(unsigned int cpu, enum cpuhp_sync_state st
/* Poll for one millisecond */
arch_cpuhp_sync_state_poll();
} else {
- usleep_range_state(USEC_PER_MSEC, 2 * USEC_PER_MSEC, TASK_UNINTERRUPTIBLE);
+ usleep_range(USEC_PER_MSEC, 2 * USEC_PER_MSEC);
}
sync = atomic_read(st);
}
--
2.39.2
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [PATCH 03/15] Comments: Fix wrong singular form of jiffies
2024-09-04 13:04 [PATCH 00/15] timers: Cleanup delay/sleep related mess Anna-Maria Behnsen
2024-09-04 13:04 ` [PATCH 01/15] timers: Rename next_expiry_recalc() to be unique Anna-Maria Behnsen
2024-09-04 13:04 ` [PATCH 02/15] cpu: Use already existing usleep_range() Anna-Maria Behnsen
@ 2024-09-04 13:04 ` Anna-Maria Behnsen
2024-09-05 8:42 ` Geert Uytterhoeven
2024-09-08 18:58 ` [tip: timers/core] treewide: Fix wrong singular form of jiffies in comments tip-bot2 for Anna-Maria Behnsen
2024-09-04 13:04 ` [PATCH 04/15] timers: Move *sleep*() and timeout functions into a separate file Anna-Maria Behnsen
` (13 subsequent siblings)
16 siblings, 2 replies; 43+ messages in thread
From: Anna-Maria Behnsen @ 2024-09-04 13:04 UTC (permalink / raw)
To: Frederic Weisbecker, Thomas Gleixner, Jonathan Corbet
Cc: linux-kernel, Len Brown, Rafael J. Wysocki, Anna-Maria Behnsen
There are several comments all over the place, which uses a wrong singular
form of jiffies.
Replace 'jiffie' by 'jiffy'. No functional change.
Signed-off-by: Anna-Maria Behnsen <anna-maria@linutronix.de>
---
Documentation/admin-guide/media/vivid.rst | 2 +-
Documentation/timers/timers-howto.rst | 2 +-
.../translations/sp_SP/scheduler/sched-design-CFS.rst | 2 +-
arch/arm/mach-versatile/spc.c | 2 +-
arch/m68k/q40/q40ints.c | 2 +-
arch/x86/kernel/cpu/mce/dev-mcelog.c | 2 +-
drivers/char/ipmi/ipmi_ssif.c | 2 +-
drivers/dma-buf/st-dma-fence.c | 2 +-
drivers/gpu/drm/i915/gem/i915_gem_wait.c | 2 +-
drivers/gpu/drm/i915/gt/selftest_execlists.c | 4 ++--
drivers/gpu/drm/i915/i915_utils.c | 2 +-
drivers/gpu/drm/v3d/v3d_bo.c | 2 +-
drivers/isdn/mISDN/dsp_cmx.c | 2 +-
drivers/net/ethernet/marvell/mvmdio.c | 2 +-
fs/xfs/xfs_buf.h | 2 +-
include/linux/jiffies.h | 2 +-
include/linux/timekeeper_internal.h | 2 +-
kernel/time/alarmtimer.c | 2 +-
kernel/time/clockevents.c | 2 +-
kernel/time/hrtimer.c | 2 +-
kernel/time/posix-timers.c | 4 ++--
kernel/time/timer.c | 12 ++++++------
lib/Kconfig.debug | 2 +-
net/batman-adv/types.h | 2 +-
24 files changed, 31 insertions(+), 31 deletions(-)
diff --git a/Documentation/admin-guide/media/vivid.rst b/Documentation/admin-guide/media/vivid.rst
index 1306f19ecb5a..c9d301ab46a3 100644
--- a/Documentation/admin-guide/media/vivid.rst
+++ b/Documentation/admin-guide/media/vivid.rst
@@ -328,7 +328,7 @@ and an HDMI input, one input for each input type. Those are described in more
detail below.
Special attention has been given to the rate at which new frames become
-available. The jitter will be around 1 jiffie (that depends on the HZ
+available. The jitter will be around 1 jiffy (that depends on the HZ
configuration of your kernel, so usually 1/100, 1/250 or 1/1000 of a second),
but the long-term behavior is exactly following the framerate. So a
framerate of 59.94 Hz is really different from 60 Hz. If the framerate
diff --git a/Documentation/timers/timers-howto.rst b/Documentation/timers/timers-howto.rst
index 5c169e3d29a8..ef7a4652ccc9 100644
--- a/Documentation/timers/timers-howto.rst
+++ b/Documentation/timers/timers-howto.rst
@@ -19,7 +19,7 @@ it really need to delay in atomic context?" If so...
ATOMIC CONTEXT:
You must use the `*delay` family of functions. These
- functions use the jiffie estimation of clock speed
+ functions use the jiffy estimation of clock speed
and will busy wait for enough loop cycles to achieve
the desired delay:
diff --git a/Documentation/translations/sp_SP/scheduler/sched-design-CFS.rst b/Documentation/translations/sp_SP/scheduler/sched-design-CFS.rst
index 90a153cad4e8..731c266beb1a 100644
--- a/Documentation/translations/sp_SP/scheduler/sched-design-CFS.rst
+++ b/Documentation/translations/sp_SP/scheduler/sched-design-CFS.rst
@@ -109,7 +109,7 @@ para que se ejecute, y la tarea en ejecución es interrumpida.
==================================
CFS usa una granularidad de nanosegundos y no depende de ningún
-jiffie o detalles como HZ. De este modo, el gestor de tareas CFS no tiene
+jiffy o detalles como HZ. De este modo, el gestor de tareas CFS no tiene
noción de "ventanas de tiempo" de la forma en que tenía el gestor de
tareas previo, y tampoco tiene heurísticos. Únicamente hay un parámetro
central ajustable (se ha de cambiar en CONFIG_SCHED_DEBUG):
diff --git a/arch/arm/mach-versatile/spc.c b/arch/arm/mach-versatile/spc.c
index 5e44170e1a9a..790092734cf6 100644
--- a/arch/arm/mach-versatile/spc.c
+++ b/arch/arm/mach-versatile/spc.c
@@ -73,7 +73,7 @@
/*
* Even though the SPC takes max 3-5 ms to complete any OPP/COMMS
- * operation, the operation could start just before jiffie is about
+ * operation, the operation could start just before jiffy is about
* to be incremented. So setting timeout value of 20ms = 2jiffies@100Hz
*/
#define TIMEOUT_US 20000
diff --git a/arch/m68k/q40/q40ints.c b/arch/m68k/q40/q40ints.c
index 10f1f294e91f..14b774b9d308 100644
--- a/arch/m68k/q40/q40ints.c
+++ b/arch/m68k/q40/q40ints.c
@@ -106,7 +106,7 @@ void __init q40_init_IRQ(void)
* this stuff doesn't really belong here..
*/
-int ql_ticks; /* 200Hz ticks since last jiffie */
+int ql_ticks; /* 200Hz ticks since last jiffy */
static int sound_ticks;
#define SVOL 45
diff --git a/arch/x86/kernel/cpu/mce/dev-mcelog.c b/arch/x86/kernel/cpu/mce/dev-mcelog.c
index a05ac0716ecf..a3aa0199222e 100644
--- a/arch/x86/kernel/cpu/mce/dev-mcelog.c
+++ b/arch/x86/kernel/cpu/mce/dev-mcelog.c
@@ -314,7 +314,7 @@ static ssize_t mce_chrdev_write(struct file *filp, const char __user *ubuf,
/*
* Need to give user space some time to set everything up,
- * so do it a jiffie or two later everywhere.
+ * so do it a jiffy or two later everywhere.
*/
schedule_timeout(2);
diff --git a/drivers/char/ipmi/ipmi_ssif.c b/drivers/char/ipmi/ipmi_ssif.c
index 96ad571d041a..e093028391af 100644
--- a/drivers/char/ipmi/ipmi_ssif.c
+++ b/drivers/char/ipmi/ipmi_ssif.c
@@ -980,7 +980,7 @@ static void msg_written_handler(struct ssif_info *ssif_info, int result,
ipmi_ssif_unlock_cond(ssif_info, flags);
start_get(ssif_info);
} else {
- /* Wait a jiffie then request the next message */
+ /* Wait a jiffy then request the next message */
ssif_info->waiting_alert = true;
ssif_info->retries_left = SSIF_RECV_RETRIES;
if (!ssif_info->stopping)
diff --git a/drivers/dma-buf/st-dma-fence.c b/drivers/dma-buf/st-dma-fence.c
index 6a1bfcd0cc21..cf2ce3744ce6 100644
--- a/drivers/dma-buf/st-dma-fence.c
+++ b/drivers/dma-buf/st-dma-fence.c
@@ -402,7 +402,7 @@ static int test_wait_timeout(void *arg)
if (dma_fence_wait_timeout(wt.f, false, 2) == -ETIME) {
if (timer_pending(&wt.timer)) {
- pr_notice("Timer did not fire within the jiffie!\n");
+ pr_notice("Timer did not fire within the jiffy!\n");
err = 0; /* not our fault! */
} else {
pr_err("Wait reported incomplete after timeout\n");
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_wait.c b/drivers/gpu/drm/i915/gem/i915_gem_wait.c
index d4b918fb11ce..1f55e62044a4 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_wait.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_wait.c
@@ -266,7 +266,7 @@ i915_gem_wait_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
if (ret == -ETIME && !nsecs_to_jiffies(args->timeout_ns))
args->timeout_ns = 0;
- /* Asked to wait beyond the jiffie/scheduler precision? */
+ /* Asked to wait beyond the jiffy/scheduler precision? */
if (ret == -ETIME && args->timeout_ns)
ret = -EAGAIN;
}
diff --git a/drivers/gpu/drm/i915/gt/selftest_execlists.c b/drivers/gpu/drm/i915/gt/selftest_execlists.c
index 4202df5b8c12..222ca7c44951 100644
--- a/drivers/gpu/drm/i915/gt/selftest_execlists.c
+++ b/drivers/gpu/drm/i915/gt/selftest_execlists.c
@@ -93,7 +93,7 @@ static int wait_for_reset(struct intel_engine_cs *engine,
return -EINVAL;
}
- /* Give the request a jiffie to complete after flushing the worker */
+ /* Give the request a jiffy to complete after flushing the worker */
if (i915_request_wait(rq, 0,
max(0l, (long)(timeout - jiffies)) + 1) < 0) {
pr_err("%s: hanging request %llx:%lld did not complete\n",
@@ -3426,7 +3426,7 @@ static int live_preempt_timeout(void *arg)
cpu_relax();
saved_timeout = engine->props.preempt_timeout_ms;
- engine->props.preempt_timeout_ms = 1; /* in ms, -> 1 jiffie */
+ engine->props.preempt_timeout_ms = 1; /* in ms, -> 1 jiffy */
i915_request_get(rq);
i915_request_add(rq);
diff --git a/drivers/gpu/drm/i915/i915_utils.c b/drivers/gpu/drm/i915/i915_utils.c
index 6f9e7b354b54..f2ba51c20e97 100644
--- a/drivers/gpu/drm/i915/i915_utils.c
+++ b/drivers/gpu/drm/i915/i915_utils.c
@@ -110,7 +110,7 @@ void set_timer_ms(struct timer_list *t, unsigned long timeout)
* Paranoia to make sure the compiler computes the timeout before
* loading 'jiffies' as jiffies is volatile and may be updated in
* the background by a timer tick. All to reduce the complexity
- * of the addition and reduce the risk of losing a jiffie.
+ * of the addition and reduce the risk of losing a jiffy.
*/
barrier();
diff --git a/drivers/gpu/drm/v3d/v3d_bo.c b/drivers/gpu/drm/v3d/v3d_bo.c
index a165cbcdd27b..9eafe53a8f41 100644
--- a/drivers/gpu/drm/v3d/v3d_bo.c
+++ b/drivers/gpu/drm/v3d/v3d_bo.c
@@ -279,7 +279,7 @@ v3d_wait_bo_ioctl(struct drm_device *dev, void *data,
else
args->timeout_ns = 0;
- /* Asked to wait beyond the jiffie/scheduler precision? */
+ /* Asked to wait beyond the jiffy/scheduler precision? */
if (ret == -ETIME && args->timeout_ns)
ret = -EAGAIN;
diff --git a/drivers/isdn/mISDN/dsp_cmx.c b/drivers/isdn/mISDN/dsp_cmx.c
index 61cb45c5d0d8..53fad9487574 100644
--- a/drivers/isdn/mISDN/dsp_cmx.c
+++ b/drivers/isdn/mISDN/dsp_cmx.c
@@ -82,7 +82,7 @@
* - has multiple clocks.
* - has no usable clock due to jitter or packet loss (VoIP).
* In this case the system's clock is used. The clock resolution depends on
- * the jiffie resolution.
+ * the jiffy resolution.
*
* If a member joins a conference:
*
diff --git a/drivers/net/ethernet/marvell/mvmdio.c b/drivers/net/ethernet/marvell/mvmdio.c
index 9190eff6c0bb..e1d003fdbc2e 100644
--- a/drivers/net/ethernet/marvell/mvmdio.c
+++ b/drivers/net/ethernet/marvell/mvmdio.c
@@ -104,7 +104,7 @@ static int orion_mdio_wait_ready(const struct orion_mdio_ops *ops,
return 0;
} else {
/* wait_event_timeout does not guarantee a delay of at
- * least one whole jiffie, so timeout must be no less
+ * least one whole jiffy, so timeout must be no less
* than two.
*/
timeout = max(usecs_to_jiffies(MVMDIO_SMI_TIMEOUT), 2);
diff --git a/fs/xfs/xfs_buf.h b/fs/xfs/xfs_buf.h
index b1580644501f..209a389f2abc 100644
--- a/fs/xfs/xfs_buf.h
+++ b/fs/xfs/xfs_buf.h
@@ -210,7 +210,7 @@ struct xfs_buf {
* success the write is considered to be failed permanently and the
* iodone handler will take appropriate action.
*
- * For retry timeouts, we record the jiffie of the first failure. This
+ * For retry timeouts, we record the jiffy of the first failure. This
* means that we can change the retry timeout for buffers already under
* I/O and thus avoid getting stuck in a retry loop with a long timeout.
*
diff --git a/include/linux/jiffies.h b/include/linux/jiffies.h
index d9f1435a5a13..1220f0fbe5bf 100644
--- a/include/linux/jiffies.h
+++ b/include/linux/jiffies.h
@@ -418,7 +418,7 @@ extern unsigned long preset_lpj;
#define NSEC_CONVERSION ((unsigned long)((((u64)1 << NSEC_JIFFIE_SC) +\
TICK_NSEC -1) / (u64)TICK_NSEC))
/*
- * The maximum jiffie value is (MAX_INT >> 1). Here we translate that
+ * The maximum jiffy value is (MAX_INT >> 1). Here we translate that
* into seconds. The 64-bit case will overflow if we are not careful,
* so use the messy SH_DIV macro to do it. Still all constants.
*/
diff --git a/include/linux/timekeeper_internal.h b/include/linux/timekeeper_internal.h
index 84ff2844df2a..902c20ef495a 100644
--- a/include/linux/timekeeper_internal.h
+++ b/include/linux/timekeeper_internal.h
@@ -73,7 +73,7 @@ struct tk_read_base {
* @overflow_seen: Overflow warning flag (DEBUG_TIMEKEEPING)
*
* Note: For timespec(64) based interfaces wall_to_monotonic is what
- * we need to add to xtime (or xtime corrected for sub jiffie times)
+ * we need to add to xtime (or xtime corrected for sub jiffy times)
* to get to monotonic time. Monotonic is pegged at zero at system
* boot time, so wall_to_monotonic will be negative, however, we will
* ALWAYS keep the tv_nsec part positive so we can use the usual
diff --git a/kernel/time/alarmtimer.c b/kernel/time/alarmtimer.c
index 76bd4fda3472..8bf888641694 100644
--- a/kernel/time/alarmtimer.c
+++ b/kernel/time/alarmtimer.c
@@ -493,7 +493,7 @@ static u64 __alarm_forward_now(struct alarm *alarm, ktime_t interval, bool throt
* promised in the context of posix_timer_fn() never
* materialized, but someone should really work on it.
*
- * To prevent DOS fake @now to be 1 jiffie out which keeps
+ * To prevent DOS fake @now to be 1 jiffy out which keeps
* the overrun accounting correct but creates an
* inconsistency vs. timer_gettime(2).
*/
diff --git a/kernel/time/clockevents.c b/kernel/time/clockevents.c
index 60a6484831b1..78c7bd64d0dd 100644
--- a/kernel/time/clockevents.c
+++ b/kernel/time/clockevents.c
@@ -190,7 +190,7 @@ int clockevents_tick_resume(struct clock_event_device *dev)
#ifdef CONFIG_GENERIC_CLOCKEVENTS_MIN_ADJUST
-/* Limit min_delta to a jiffie */
+/* Limit min_delta to a jiffy */
#define MIN_DELTA_LIMIT (NSEC_PER_SEC / HZ)
/**
diff --git a/kernel/time/hrtimer.c b/kernel/time/hrtimer.c
index a023946f8558..e834b2bd83df 100644
--- a/kernel/time/hrtimer.c
+++ b/kernel/time/hrtimer.c
@@ -1177,7 +1177,7 @@ static inline ktime_t hrtimer_update_lowres(struct hrtimer *timer, ktime_t tim,
/*
* CONFIG_TIME_LOW_RES indicates that the system has no way to return
* granular time values. For relative timers we add hrtimer_resolution
- * (i.e. one jiffie) to prevent short timeouts.
+ * (i.e. one jiffy) to prevent short timeouts.
*/
timer->is_rel = mode & HRTIMER_MODE_REL;
if (timer->is_rel)
diff --git a/kernel/time/posix-timers.c b/kernel/time/posix-timers.c
index 1cc830ef93a7..4576aaed13b2 100644
--- a/kernel/time/posix-timers.c
+++ b/kernel/time/posix-timers.c
@@ -339,14 +339,14 @@ static enum hrtimer_restart posix_timer_fn(struct hrtimer *timer)
* change to the signal handling code.
*
* For now let timers with an interval less than a
- * jiffie expire every jiffie and recheck for a
+ * jiffy expire every jiffy and recheck for a
* valid signal handler.
*
* This avoids interrupt starvation in case of a
* very small interval, which would expire the
* timer immediately again.
*
- * Moving now ahead of time by one jiffie tricks
+ * Moving now ahead of time by one jiffy tricks
* hrtimer_forward() to expire the timer later,
* while it still maintains the overrun accuracy
* for the price of a slight inconsistency in the
diff --git a/kernel/time/timer.c b/kernel/time/timer.c
index 5e021a2d8d61..2b38f3035a3e 100644
--- a/kernel/time/timer.c
+++ b/kernel/time/timer.c
@@ -365,7 +365,7 @@ static unsigned long round_jiffies_common(unsigned long j, int cpu,
rem = j % HZ;
/*
- * If the target jiffie is just after a whole second (which can happen
+ * If the target jiffy is just after a whole second (which can happen
* due to delays of the timer irq, long irq off times etc etc) then
* we should round down to the whole second, not up. Use 1/4th second
* as cutoff for this rounding as an extreme upper bound for this.
@@ -1930,7 +1930,7 @@ static void timer_recalc_next_expiry(struct timer_base *base)
* bits are zero, we look at the next level as is. If not we
* need to advance it by one because that's going to be the
* next expiring bucket in that level. base->clk is the next
- * expiring jiffie. So in case of:
+ * expiring jiffy. So in case of:
*
* LVL5 LVL4 LVL3 LVL2 LVL1 LVL0
* 0 0 0 0 0 0
@@ -1995,7 +1995,7 @@ static u64 cmp_next_hrtimer_event(u64 basem, u64 expires)
return basem;
/*
- * Round up to the next jiffie. High resolution timers are
+ * Round up to the next jiffy. High resolution timers are
* off, so the hrtimers are expired in the tick and we need to
* make sure that this tick really expires the timer to avoid
* a ping pong of the nohz stop code.
@@ -2254,7 +2254,7 @@ static inline u64 __get_next_timer_interrupt(unsigned long basej, u64 basem,
base_global, &tevt);
/*
- * If the next event is only one jiffie ahead there is no need to call
+ * If the next event is only one jiffy ahead there is no need to call
* timer migration hierarchy related functions. The value for the next
* global timer in @tevt struct equals then KTIME_MAX. This is also
* true, when the timer base is idle.
@@ -2486,11 +2486,11 @@ static void run_local_timers(void)
* updated. When this update is missed, this isn't a
* problem, as an IPI is executed nevertheless when the CPU
* was idle before. When the CPU wasn't idle but the update
- * is missed, then the timer would expire one jiffie late -
+ * is missed, then the timer would expire one jiffy late -
* bad luck.
*
* Those unlikely corner cases where the worst outcome is only a
- * one jiffie delay or a superfluous raise of the softirq are
+ * one jiffy delay or a superfluous raise of the softirq are
* not that expensive as doing the check always while holding
* the lock.
*
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index a30c03a66172..a40aa606cd04 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -97,7 +97,7 @@ config BOOT_PRINTK_DELAY
using "boot_delay=N".
It is likely that you would also need to use "lpj=M" to preset
- the "loops per jiffie" value.
+ the "loops per jiffy" value.
See a previous boot log for the "lpj" value to use for your
system, and then set "lpj=M" before setting "boot_delay=N".
NOTE: Using this option may adversely affect SMP systems.
diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h
index 00840d5784fe..04f6398b3a40 100644
--- a/net/batman-adv/types.h
+++ b/net/batman-adv/types.h
@@ -287,7 +287,7 @@ struct batadv_frag_table_entry {
/** @lock: lock to protect the list of fragments */
spinlock_t lock;
- /** @timestamp: time (jiffie) of last received fragment */
+ /** @timestamp: time (jiffy) of last received fragment */
unsigned long timestamp;
/** @seqno: sequence number of the fragments in the list */
--
2.39.2
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [PATCH 04/15] timers: Move *sleep*() and timeout functions into a separate file
2024-09-04 13:04 [PATCH 00/15] timers: Cleanup delay/sleep related mess Anna-Maria Behnsen
` (2 preceding siblings ...)
2024-09-04 13:04 ` [PATCH 03/15] Comments: Fix wrong singular form of jiffies Anna-Maria Behnsen
@ 2024-09-04 13:04 ` Anna-Maria Behnsen
2024-09-06 13:42 ` Frederic Weisbecker
2024-09-08 18:58 ` [tip: timers/core] " tip-bot2 for Anna-Maria Behnsen
2024-09-04 13:04 ` [PATCH 05/15] timers: Rename sleep_idle_range() to sleep_range_idle() Anna-Maria Behnsen
` (12 subsequent siblings)
16 siblings, 2 replies; 43+ messages in thread
From: Anna-Maria Behnsen @ 2024-09-04 13:04 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(). While at it also add not listed
include/linux/delay.h to the MAINTAINTERS file.
Signed-off-by: Anna-Maria Behnsen <anna-maria@linutronix.de>
---
MAINTAINERS | 2 +
kernel/time/Makefile | 2 +-
kernel/time/hrtimer.c | 120 -----------------
kernel/time/sleep_timeout.c | 320 ++++++++++++++++++++++++++++++++++++++++++++
kernel/time/timer.c | 192 --------------------------
5 files changed, 323 insertions(+), 313 deletions(-)
diff --git a/MAINTAINERS b/MAINTAINERS
index 42decde38320..e9cb09990e2a 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -10010,10 +10010,12 @@ 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
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..9ecbce7da537
--- /dev/null
+++ b/kernel/time/sleep_timeout.c
@@ -0,0 +1,320 @@
+// 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] 43+ messages in thread
* [PATCH 05/15] timers: Rename sleep_idle_range() to sleep_range_idle()
2024-09-04 13:04 [PATCH 00/15] timers: Cleanup delay/sleep related mess Anna-Maria Behnsen
` (3 preceding siblings ...)
2024-09-04 13:04 ` [PATCH 04/15] timers: Move *sleep*() and timeout functions into a separate file Anna-Maria Behnsen
@ 2024-09-04 13:04 ` Anna-Maria Behnsen
2024-09-06 13:45 ` Frederic Weisbecker
` (2 more replies)
2024-09-04 13:04 ` [PATCH 06/15] timers: Update function descriptions of sleep/delay related functions Anna-Maria Behnsen
` (11 subsequent siblings)
16 siblings, 3 replies; 43+ messages in thread
From: Anna-Maria Behnsen @ 2024-09-04 13:04 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
sleep_idle_range() is a variant of sleep_range(). Both are using
sleep_range_state() as a base. To be able to find all the related functions
in one go, rename it sleep_idle_range() to sleep_range_idle().
No functional change.
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>
---
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] 43+ messages in thread
* [PATCH 06/15] timers: Update function descriptions of sleep/delay related functions
2024-09-04 13:04 [PATCH 00/15] timers: Cleanup delay/sleep related mess Anna-Maria Behnsen
` (4 preceding siblings ...)
2024-09-04 13:04 ` [PATCH 05/15] timers: Rename sleep_idle_range() to sleep_range_idle() Anna-Maria Behnsen
@ 2024-09-04 13:04 ` Anna-Maria Behnsen
2024-09-04 14:30 ` Arnd Bergmann
2024-09-05 6:59 ` Thomas Gleixner
2024-09-04 13:04 ` [PATCH 07/15] timers: Adjust flseep() to reflect reality Anna-Maria Behnsen
` (10 subsequent siblings)
16 siblings, 2 replies; 43+ messages in thread
From: Anna-Maria Behnsen @ 2024-09-04 13:04 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>
---
include/asm-generic/delay.h | 46 ++++++++++++++++++++++++++++++++++-----
include/linux/delay.h | 48 ++++++++++++++++++++++++++++++----------
kernel/time/sleep_timeout.c | 53 ++++++++++++++++++++++++++++++++++++++++-----
3 files changed, 123 insertions(+), 24 deletions(-)
diff --git a/include/asm-generic/delay.h b/include/asm-generic/delay.h
index e448ac61430c..76531ea7597a 100644
--- a/include/asm-generic/delay.h
+++ b/include/asm-generic/delay.h
@@ -11,12 +11,37 @@ extern void __ndelay(unsigned long nsecs);
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.
+/**
+ * udelay - Inserting a delay based on microseconds with busy waiting
+ * @n: 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.
+ *
+ * Impelementation details for udelay() only:
+ *
+ * * 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)
*/
-
-/* 0x10c7 is 2**32 / 1000000 (rounded up) */
#define udelay(n) \
({ \
if (__builtin_constant_p(n)) { \
@@ -29,7 +54,16 @@ extern void __delay(unsigned long loops);
} \
})
-/* 0x5 is 2**32 / 1000000000 (rounded up) */
+/**
+ * ndelay - Inserting a delay based on nanoseconds with busy waiting
+ * @n: requested delay in nanoseconds
+ *
+ * See udelay() for basic information about ndelay() and it's variants.
+ *
+ * Impelmentation details for ndelay():
+ *
+ * * 0x5 is 2**32 / 1000000000 (rounded up)
+ */
#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 9ecbce7da537..1ebd8429a64a 100644
--- a/kernel/time/sleep_timeout.c
+++ b/kernel/time/sleep_timeout.c
@@ -267,7 +267,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 jiffie 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)
{
@@ -280,7 +307,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)
{
@@ -298,11 +333,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] 43+ messages in thread
* [PATCH 07/15] timers: Adjust flseep() to reflect reality
2024-09-04 13:04 [PATCH 00/15] timers: Cleanup delay/sleep related mess Anna-Maria Behnsen
` (5 preceding siblings ...)
2024-09-04 13:04 ` [PATCH 06/15] timers: Update function descriptions of sleep/delay related functions Anna-Maria Behnsen
@ 2024-09-04 13:04 ` Anna-Maria Behnsen
2024-09-04 13:04 ` [PATCH 08/15] mm/damon/core: Use generic upper bound recommondation for usleep_range() Anna-Maria Behnsen
` (9 subsequent siblings)
16 siblings, 0 replies; 43+ messages in thread
From: Anna-Maria Behnsen @ 2024-09-04 13:04 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] 43+ messages in thread
* [PATCH 08/15] mm/damon/core: Use generic upper bound recommondation for usleep_range()
2024-09-04 13:04 [PATCH 00/15] timers: Cleanup delay/sleep related mess Anna-Maria Behnsen
` (6 preceding siblings ...)
2024-09-04 13:04 ` [PATCH 07/15] timers: Adjust flseep() to reflect reality Anna-Maria Behnsen
@ 2024-09-04 13:04 ` Anna-Maria Behnsen
2024-09-06 16:31 ` SeongJae Park
2024-09-04 13:04 ` [PATCH 09/15] timers: Add a warning to usleep_range_state() for wrong order of arguments Anna-Maria Behnsen
` (8 subsequent siblings)
16 siblings, 1 reply; 43+ messages in thread
From: Anna-Maria Behnsen @ 2024-09-04 13:04 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>
---
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] 43+ messages in thread
* [PATCH 09/15] timers: Add a warning to usleep_range_state() for wrong order of arguments
2024-09-04 13:04 [PATCH 00/15] timers: Cleanup delay/sleep related mess Anna-Maria Behnsen
` (7 preceding siblings ...)
2024-09-04 13:04 ` [PATCH 08/15] mm/damon/core: Use generic upper bound recommondation for usleep_range() Anna-Maria Behnsen
@ 2024-09-04 13:04 ` Anna-Maria Behnsen
2024-09-04 13:05 ` [PATCH 10/15] checkpatch: Remove broken sleep/delay related checks Anna-Maria Behnsen
` (7 subsequent siblings)
16 siblings, 0 replies; 43+ messages in thread
From: Anna-Maria Behnsen @ 2024-09-04 13:04 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 1ebd8429a64a..e028e9b4b113 100644
--- a/kernel/time/sleep_timeout.c
+++ b/kernel/time/sleep_timeout.c
@@ -351,6 +351,8 @@ void __sched usleep_range_state(unsigned long min, unsigned long max,
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] 43+ messages in thread
* [PATCH 10/15] checkpatch: Remove broken sleep/delay related checks
2024-09-04 13:04 [PATCH 00/15] timers: Cleanup delay/sleep related mess Anna-Maria Behnsen
` (8 preceding siblings ...)
2024-09-04 13:04 ` [PATCH 09/15] timers: Add a warning to usleep_range_state() for wrong order of arguments Anna-Maria Behnsen
@ 2024-09-04 13:05 ` Anna-Maria Behnsen
2024-09-05 1:28 ` Joe Perches
2024-09-04 13:05 ` [PATCH 11/15] regulator: core: Use fsleep() to get best sleep mechanism Anna-Maria Behnsen
` (6 subsequent siblings)
16 siblings, 1 reply; 43+ messages in thread
From: Anna-Maria Behnsen @ 2024-09-04 13:05 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: The message is simply wrong. msleep() will not
sleep (and never did it before) for at least
20ms. This threshold cannot be hard coded as it
depends on the required accuracy and also on HZ
(jiffie granularity and timer wheel bucket/level
granularity). See msleep() and also the
USLEEP_RANGE_UPPER_BOUND value.
Remove all broken checks. Remove also no longer required checkpatch
documentation section about USLEEP_RANGE.
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>
---
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] 43+ messages in thread
* [PATCH 11/15] regulator: core: Use fsleep() to get best sleep mechanism
2024-09-04 13:04 [PATCH 00/15] timers: Cleanup delay/sleep related mess Anna-Maria Behnsen
` (9 preceding siblings ...)
2024-09-04 13:05 ` [PATCH 10/15] checkpatch: Remove broken sleep/delay related checks Anna-Maria Behnsen
@ 2024-09-04 13:05 ` Anna-Maria Behnsen
2024-09-04 13:28 ` Mark Brown
2024-09-04 13:05 ` [PATCH 12/15] iopoll/regmap/phy/snd: Fix comment referencing outdated timer documentation Anna-Maria Behnsen
` (5 subsequent siblings)
16 siblings, 1 reply; 43+ messages in thread
From: Anna-Maria Behnsen @ 2024-09-04 13:05 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() to choose the best mechanism.
Cc: Liam Girdwood <lgirdwood@gmail.com>
Cc: Mark Brown <broonie@kernel.org>
Signed-off-by: Anna-Maria Behnsen <anna-maria@linutronix.de>
---
drivers/regulator/core.c | 33 ++++-----------------------------
1 file changed, 4 insertions(+), 29 deletions(-)
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index 7674b7f2df14..155c3e3ab3f1 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -2671,39 +2671,14 @@ static int regulator_ena_gpio_ctrl(struct regulator_dev *rdev, bool enable)
* _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:
+ * For details please refere to fsleep() function description.
*
- * Documentation/timers/timers-howto.rst
- *
- * The assumption here is that these regulator operations will never used in
+ * The assumption here is that these regulator operations are never used in
* atomic context and therefore sleeping functions can be used.
*/
-static void _regulator_delay_helper(unsigned int delay)
+static inline 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);
+ fsleep(delay);
}
/**
--
2.39.2
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [PATCH 12/15] iopoll/regmap/phy/snd: Fix comment referencing outdated timer documentation
2024-09-04 13:04 [PATCH 00/15] timers: Cleanup delay/sleep related mess Anna-Maria Behnsen
` (10 preceding siblings ...)
2024-09-04 13:05 ` [PATCH 11/15] regulator: core: Use fsleep() to get best sleep mechanism Anna-Maria Behnsen
@ 2024-09-04 13:05 ` Anna-Maria Behnsen
2024-09-04 14:03 ` Andrew Lunn
2024-09-04 13:05 ` [PATCH 13/15] powerpc/rtas: Use fsleep() to minimize additional sleep duration Anna-Maria Behnsen
` (4 subsequent siblings)
16 siblings, 1 reply; 43+ messages in thread
From: Anna-Maria Behnsen @ 2024-09-04 13:05 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.
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>
---
include/linux/iopoll.h | 24 ++++++++++++------------
include/linux/phy.h | 7 ++++---
include/linux/regmap.h | 18 +++++++++---------
sound/soc/sof/ops.h | 6 +++---
4 files changed, 28 insertions(+), 27 deletions(-)
diff --git a/include/linux/iopoll.h b/include/linux/iopoll.h
index 19a7b00baff4..34b52ab2e394 100644
--- a/include/linux/iopoll.h
+++ b/include/linux/iopoll.h
@@ -19,9 +19,9 @@
* @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
@@ -64,9 +64,9 @@
* @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
@@ -119,9 +119,9 @@
* @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
@@ -140,9 +140,9 @@
* @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
diff --git a/include/linux/phy.h b/include/linux/phy.h
index 6b7d40d49129..b09490e08365 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -1374,11 +1374,12 @@ 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
* 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..85de129a9e02 100644
--- a/include/linux/regmap.h
+++ b/include/linux/regmap.h
@@ -106,9 +106,9 @@ 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
@@ -133,9 +133,9 @@ 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
@@ -177,9 +177,9 @@ 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
diff --git a/sound/soc/sof/ops.h b/sound/soc/sof/ops.h
index 2584621c3b2d..b1b8253aefad 100644
--- a/sound/soc/sof/ops.h
+++ b/sound/soc/sof/ops.h
@@ -597,9 +597,9 @@ 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
--
2.39.2
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [PATCH 13/15] powerpc/rtas: Use fsleep() to minimize additional sleep duration
2024-09-04 13:04 [PATCH 00/15] timers: Cleanup delay/sleep related mess Anna-Maria Behnsen
` (11 preceding siblings ...)
2024-09-04 13:05 ` [PATCH 12/15] iopoll/regmap/phy/snd: Fix comment referencing outdated timer documentation Anna-Maria Behnsen
@ 2024-09-04 13:05 ` Anna-Maria Behnsen
2024-09-05 12:24 ` Michael Ellerman
2024-09-04 13:05 ` [PATCH 14/15] media: anysee: Fix link to outdated sleep function documentation Anna-Maria Behnsen
` (3 subsequent siblings)
16 siblings, 1 reply; 43+ messages in thread
From: Anna-Maria Behnsen @ 2024-09-04 13:05 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>
---
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..0794ca28e51e 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 a way longer than requested independent of HZ
+ * configuration, use fsleep(). See fsleep() for detailes 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] 43+ messages in thread
* [PATCH 14/15] media: anysee: Fix link to outdated sleep function documentation
2024-09-04 13:04 [PATCH 00/15] timers: Cleanup delay/sleep related mess Anna-Maria Behnsen
` (12 preceding siblings ...)
2024-09-04 13:05 ` [PATCH 13/15] powerpc/rtas: Use fsleep() to minimize additional sleep duration Anna-Maria Behnsen
@ 2024-09-04 13:05 ` Anna-Maria Behnsen
2024-09-04 13:05 ` [PATCH 15/15] timers/Documentation: Cleanup delay/sleep documentation Anna-Maria Behnsen
` (2 subsequent siblings)
16 siblings, 0 replies; 43+ messages in thread
From: Anna-Maria Behnsen @ 2024-09-04 13:05 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] 43+ messages in thread
* [PATCH 15/15] timers/Documentation: Cleanup delay/sleep documentation
2024-09-04 13:04 [PATCH 00/15] timers: Cleanup delay/sleep related mess Anna-Maria Behnsen
` (13 preceding siblings ...)
2024-09-04 13:05 ` [PATCH 14/15] media: anysee: Fix link to outdated sleep function documentation Anna-Maria Behnsen
@ 2024-09-04 13:05 ` Anna-Maria Behnsen
2024-09-04 14:44 ` [PATCH 00/15] timers: Cleanup delay/sleep related mess Rafael J. Wysocki
2024-10-17 14:19 ` (subset) " Mark Brown
16 siblings, 0 replies; 43+ messages in thread
From: Anna-Maria Behnsen @ 2024-09-04 13:05 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] 43+ messages in thread
* Re: [PATCH 11/15] regulator: core: Use fsleep() to get best sleep mechanism
2024-09-04 13:05 ` [PATCH 11/15] regulator: core: Use fsleep() to get best sleep mechanism Anna-Maria Behnsen
@ 2024-09-04 13:28 ` Mark Brown
2024-09-05 8:24 ` Anna-Maria Behnsen
0 siblings, 1 reply; 43+ messages in thread
From: Mark Brown @ 2024-09-04 13:28 UTC (permalink / raw)
To: Anna-Maria Behnsen
Cc: Frederic Weisbecker, Thomas Gleixner, Jonathan Corbet,
linux-kernel, Len Brown, Rafael J. Wysocki, Liam Girdwood
[-- Attachment #1: Type: text/plain, Size: 708 bytes --]
On Wed, Sep 04, 2024 at 03:05:01PM +0200, Anna-Maria Behnsen wrote:
> _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().
> - * Delay for the requested amount of time as per the guidelines in:
> + * For details please refere to fsleep() function description.
> -static void _regulator_delay_helper(unsigned int delay)
> +static inline void _regulator_delay_helper(unsigned int delay)
Gien that this just becomes a trivial wrapper for fsleep() why not just
replace all the calls with fsleep() and remove the function entirely?
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [PATCH 12/15] iopoll/regmap/phy/snd: Fix comment referencing outdated timer documentation
2024-09-04 13:05 ` [PATCH 12/15] iopoll/regmap/phy/snd: Fix comment referencing outdated timer documentation Anna-Maria Behnsen
@ 2024-09-04 14:03 ` Andrew Lunn
2024-09-05 8:15 ` Anna-Maria Behnsen
0 siblings, 1 reply; 43+ messages in thread
From: Andrew Lunn @ 2024-09-04 14:03 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
> diff --git a/include/linux/phy.h b/include/linux/phy.h
> index 6b7d40d49129..b09490e08365 100644
> --- a/include/linux/phy.h
> +++ b/include/linux/phy.h
> @@ -1374,11 +1374,12 @@ 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
I know it is not in scope for what you are trying to fix, but there
should be a : after Returns
* Returns: 0 on success and -ETIMEDOUT upon a timeout. In either
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Andrew
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [PATCH 06/15] timers: Update function descriptions of sleep/delay related functions
2024-09-04 13:04 ` [PATCH 06/15] timers: Update function descriptions of sleep/delay related functions Anna-Maria Behnsen
@ 2024-09-04 14:30 ` Arnd Bergmann
2024-09-05 6:59 ` Thomas Gleixner
1 sibling, 0 replies; 43+ messages in thread
From: Arnd Bergmann @ 2024-09-04 14:30 UTC (permalink / raw)
To: Anna-Maria Gleixner, Frederic Weisbecker, Thomas Gleixner,
Jonathan Corbet
Cc: linux-kernel, Len Brown, Rafael J . Wysocki, Linux-Arch
On Wed, Sep 4, 2024, at 13:04, Anna-Maria Behnsen wrote:
> 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>
> ---
> include/asm-generic/delay.h | 46 ++++++++++++++++++++++++++++++++++-----
> include/linux/delay.h | 48 ++++++++++++++++++++++++++++++----------
> kernel/time/sleep_timeout.c | 53 ++++++++++++++++++++++++++++++++++++++++-----
> 3 files changed, 123 insertions(+), 24 deletions(-)
Acked-by: Arnd Bergmann <arnd@arndb.de> # asm-generic
Arnd
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [PATCH 00/15] timers: Cleanup delay/sleep related mess
2024-09-04 13:04 [PATCH 00/15] timers: Cleanup delay/sleep related mess Anna-Maria Behnsen
` (14 preceding siblings ...)
2024-09-04 13:05 ` [PATCH 15/15] timers/Documentation: Cleanup delay/sleep documentation Anna-Maria Behnsen
@ 2024-09-04 14:44 ` Rafael J. Wysocki
2024-10-17 14:19 ` (subset) " Mark Brown
16 siblings, 0 replies; 43+ messages in thread
From: Rafael J. Wysocki @ 2024-09-04 14:44 UTC (permalink / raw)
To: Anna-Maria Behnsen
Cc: Frederic Weisbecker, Thomas Gleixner, Jonathan Corbet,
linux-kernel, Len Brown, Rafael J. Wysocki, Peter Zijlstra,
SeongJae Park, Andrew Morton, damon, linux-mm, 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 Wed, Sep 4, 2024 at 3:05 PM Anna-Maria Behnsen
<anna-maria@linutronix.de> wrote:
>
> 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:
>
> - Minor changes (naming and typo fixes)
>
> - 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
>
> Cc: linux-kernel@vger.kernel.org
> Cc: Len Brown <len.brown@intel.com>
> Cc: Rafael J. Wysocki <rafael@kernel.org>
> To: Frederic Weisbecker <frederic@kernel.org>
> To: Thomas Gleixner <tglx@linutronix.de>
> To: Jonathan Corbet <corbet@lwn.net>
> Signed-off-by: Anna-Maria Behnsen <anna-maria@linutronix.de>
>
> Thanks,
>
> Anna-Maria
>
> ---
> Anna-Maria Behnsen (15):
> timers: Rename next_expiry_recalc() to be unique
> cpu: Use already existing usleep_range()
> Comments: Fix wrong singular form of jiffies
> timers: Move *sleep*() and timeout functions into a separate file
> timers: Rename sleep_idle_range() to sleep_range_idle()
> timers: Update function descriptions of sleep/delay related functions
> 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
I like the changes, so
Acked-by: Rafael J. Wysocki <rafael@kernel.org>
for the series.
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [PATCH 10/15] checkpatch: Remove broken sleep/delay related checks
2024-09-04 13:05 ` [PATCH 10/15] checkpatch: Remove broken sleep/delay related checks Anna-Maria Behnsen
@ 2024-09-05 1:28 ` Joe Perches
2024-09-05 8:04 ` Anna-Maria Behnsen
0 siblings, 1 reply; 43+ messages in thread
From: Joe Perches @ 2024-09-05 1:28 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-04 at 15:05 +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().
[]
> - Check: ($1 < 20)
> Message: "msleep < 20ms can sleep for up to 20ms;
> see Documentation/timers/timers-howto.rst\n"
> Why is the check broken: The message is simply wrong. msleep() will not
> sleep (and never did it before)
While it might have changed, the "never did it before" is
not correct.
https://lore.kernel.org/all/15327.1186166232@lwn.net/
> Remove all broken checks. Remove also no longer required checkpatch
> documentation section about USLEEP_RANGE.
It'd be useful to remove the appropriate now unnecessary
verbose sections from Documentation/dev-tools/checkpatch.rst
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [PATCH 06/15] timers: Update function descriptions of sleep/delay related functions
2024-09-04 13:04 ` [PATCH 06/15] timers: Update function descriptions of sleep/delay related functions Anna-Maria Behnsen
2024-09-04 14:30 ` Arnd Bergmann
@ 2024-09-05 6:59 ` Thomas Gleixner
2024-09-05 16:07 ` Thomas Gleixner
1 sibling, 1 reply; 43+ messages in thread
From: Thomas Gleixner @ 2024-09-05 6:59 UTC (permalink / raw)
To: Anna-Maria Behnsen, Frederic Weisbecker, Jonathan Corbet
Cc: linux-kernel, Len Brown, Rafael J. Wysocki, Anna-Maria Behnsen,
Arnd Bergmann, linux-arch, Andrew Morton, Nathan Chancellor,
Nick Desaulniers
On Wed, Sep 04 2024 at 15:04, Anna-Maria Behnsen wrote:
> +/**
> + * udelay - Inserting a delay based on microseconds with busy waiting
> + * @n: requested delay in microseconds
....
> + * Impelementation details for udelay() only:
Implementation
> + * * 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)
> */
That spello aside, I don't see how this information is interesting for
the user of udelay(). It's really a implementation detail and the user
does not care about this piece of art at all.
Though that made me look at this voodoo and the magic constants in
detail. The division was added in a87e553fabe8 ("asm-generic: delay.h
fix udelay and ndelay for 8 bit args") to work around a compiler which
is upset about the comparision even when __builtin_constant_p(arg) is
false:
warning: comparison is always false due to limited range of data type
The changelog is silent about the compiler version. I assume it's clang
because clang still complains on a plain (n) > 20000 when udelay() is
invoked with a u8 variable as argument:
warning: result of comparison of constant 20000 with
expression of type 'unsigned char' is always false
[-Wtautological-constant-out-of-range-compare]
while gcc does not care.
The change log explains further that type casting 'n' in the comparison
does not cure it. Contemporary clang seems to be less stupid and
if ((unsigned long)(n) >= 20000) \
compiles just fine. Though assumed that some older clang version failed
and is still allowed to be used for compiling the kernel we have to work
around it.
However, instead of proliferating this voodoo can we please convert it
into something comprehensible?
/*
* The microseconds delay multiplicator is used to convert a constant
* microseconds value to a <INSERT COHERENT EXPLANATION>.
*/
#define UDELAY_CONST_MULT ((unsigned long)DIV_ROUND_UP(1ULL << 32, USEC_PER_SEC))
/*
* The maximum constant udelay value picked out of thin air
* to avoid <INSERT COHERENT EXPLANATION>.
*/
#define UDELAY_CONST_MAX 20000
/**
* udelay - .....
*/
static __always_inline void udelay(unsigned long usec)
{
/*
* <INSERT COHERENT EXPLANATION> for this construct
*/
if (__builtin_constant_p(usec)) {
if (usec >= UDELAY_CONST_MAX)
__bad_udelay();
else
__const_udelay(usec * UDELAY_CONST_MULT);
} else {
__udelay(usec);
}
}
Both gcc and clang optimize this correctly with -O2. If there are
ancient compilers which fail to do so: *shrug*.
> + * See udelay() for basic information about ndelay() and it's variants.
> + *
> + * Impelmentation details for ndelay():
vs.
> + * Impelementation details for udelay() only:
above. Can you please make your mind up which mis-spelled variant to
pick? :)
> /**
> * 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).
Returns: The remaining ...
Thanks,
tglx
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [PATCH 10/15] checkpatch: Remove broken sleep/delay related checks
2024-09-05 1:28 ` Joe Perches
@ 2024-09-05 8:04 ` Anna-Maria Behnsen
0 siblings, 0 replies; 43+ messages in thread
From: Anna-Maria Behnsen @ 2024-09-05 8:04 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-04 at 15:05 +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().
> []
>> - Check: ($1 < 20)
>> Message: "msleep < 20ms can sleep for up to 20ms;
>> see Documentation/timers/timers-howto.rst\n"
>> Why is the check broken: The message is simply wrong. msleep() will not
>> sleep (and never did it before)
>
> While it might have changed, the "never did it before" is
> not correct.
>
> https://lore.kernel.org/all/15327.1186166232@lwn.net/
Thanks for the fast reply!
Yes you are right. I wasn't able to read properly and had in my mind
that it says that msleep will sleep at least 20ms when I was writing
this "never did it before" - my fault.
The point I want to make here is that those 20ms cannot be hard coded,
as this is HZ dependent (same thing as it was before). I will rephrase
it to:
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. Remove also no longer required checkpatch
>> documentation section about USLEEP_RANGE.
>
> It'd be useful to remove the appropriate now unnecessary
> verbose sections from Documentation/dev-tools/checkpatch.rst
Maybe my coffee does not do it's job yet - which part should I remove? I
already remove the USLEEP_RANGE part. For MSLEEP and LONG_UDELAY there
wasn't anything documented.
Or should I rephrase the commit message somehow?
Thanks,
Anna-Maria
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [PATCH 12/15] iopoll/regmap/phy/snd: Fix comment referencing outdated timer documentation
2024-09-04 14:03 ` Andrew Lunn
@ 2024-09-05 8:15 ` Anna-Maria Behnsen
0 siblings, 0 replies; 43+ messages in thread
From: Anna-Maria Behnsen @ 2024-09-05 8:15 UTC (permalink / raw)
To: Andrew Lunn
Cc: Frederic Weisbecker, Thomas Gleixner, Jonathan Corbet,
linux-kernel, Len Brown, Rafael J. Wysocki, Heiner Kallweit,
Jaroslav Kysela, Takashi Iwai, netdev, linux-sound
Andrew Lunn <andrew@lunn.ch> writes:
>> diff --git a/include/linux/phy.h b/include/linux/phy.h
>> index 6b7d40d49129..b09490e08365 100644
>> --- a/include/linux/phy.h
>> +++ b/include/linux/phy.h
>> @@ -1374,11 +1374,12 @@ 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
>
> I know it is not in scope for what you are trying to fix, but there
> should be a : after Returns
>
> * Returns: 0 on success and -ETIMEDOUT upon a timeout. In either
I have to do a v2 of the series anyway. So if it helps, I can add the
missing colon after "Returns" in all those function descriptions I touch
and expand the commit message by:
While at it fix missing colon after "Returns" in function description
as well.
> Reviewed-by: Andrew Lunn <andrew@lunn.ch>
>
> Andrew
Thanks,
Anna-Maria
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [PATCH 11/15] regulator: core: Use fsleep() to get best sleep mechanism
2024-09-04 13:28 ` Mark Brown
@ 2024-09-05 8:24 ` Anna-Maria Behnsen
0 siblings, 0 replies; 43+ messages in thread
From: Anna-Maria Behnsen @ 2024-09-05 8:24 UTC (permalink / raw)
To: Mark Brown
Cc: Frederic Weisbecker, Thomas Gleixner, Jonathan Corbet,
linux-kernel, Len Brown, Rafael J. Wysocki, Liam Girdwood
Mark Brown <broonie@kernel.org> writes:
> On Wed, Sep 04, 2024 at 03:05:01PM +0200, Anna-Maria Behnsen wrote:
>> _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().
>
>> - * Delay for the requested amount of time as per the guidelines in:
>> + * For details please refere to fsleep() function description.
>
>> -static void _regulator_delay_helper(unsigned int delay)
>> +static inline void _regulator_delay_helper(unsigned int delay)
>
> Gien that this just becomes a trivial wrapper for fsleep() why not just
> replace all the calls with fsleep() and remove the function entirely?
Nothing to say against it! I will change it.
Thanks,
Anna-Maria
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [PATCH 03/15] Comments: Fix wrong singular form of jiffies
2024-09-04 13:04 ` [PATCH 03/15] Comments: Fix wrong singular form of jiffies Anna-Maria Behnsen
@ 2024-09-05 8:42 ` Geert Uytterhoeven
2024-09-08 18:58 ` [tip: timers/core] treewide: Fix wrong singular form of jiffies in comments tip-bot2 for Anna-Maria Behnsen
1 sibling, 0 replies; 43+ messages in thread
From: Geert Uytterhoeven @ 2024-09-05 8:42 UTC (permalink / raw)
To: Anna-Maria Behnsen
Cc: Frederic Weisbecker, Thomas Gleixner, Jonathan Corbet,
linux-kernel, Len Brown, Rafael J. Wysocki
On Wed, Sep 4, 2024 at 3:09 PM Anna-Maria Behnsen
<anna-maria@linutronix.de> wrote:
> There are several comments all over the place, which uses a wrong singular
> form of jiffies.
>
> Replace 'jiffie' by 'jiffy'. No functional change.
>
> Signed-off-by: Anna-Maria Behnsen <anna-maria@linutronix.de>
> arch/m68k/q40/q40ints.c | 2 +-
Acked-by: Geert Uytterhoeven <geert@linux-m68k.org> # m68k
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org
In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [PATCH 13/15] powerpc/rtas: Use fsleep() to minimize additional sleep duration
2024-09-04 13:05 ` [PATCH 13/15] powerpc/rtas: Use fsleep() to minimize additional sleep duration Anna-Maria Behnsen
@ 2024-09-05 12:24 ` Michael Ellerman
0 siblings, 0 replies; 43+ messages in thread
From: Michael Ellerman @ 2024-09-05 12:24 UTC (permalink / raw)
To: Anna-Maria Behnsen, Frederic Weisbecker, Thomas Gleixner,
Jonathan Corbet
Cc: linux-kernel, Len Brown, Rafael J. Wysocki, Anna-Maria Behnsen,
Nathan Lynch, linuxppc-dev
Anna-Maria Behnsen <anna-maria@linutronix.de> writes:
> When commit 38f7b7067dae ("powerpc/rtas: rtas_busy_delay() improvements")
> was introduced, documentation about proper usage of sleep realted functions
> was outdated.
>
...
> Use fsleep() directly instead of using an own heuristic for the best
> sleeping mechanism to use..
Thanks for tidying this up. I only learnt about fsleep() in the last ~year.
Two minor nits ...
> diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c
> index f7e86e09c49f..0794ca28e51e 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 a way longer than requested independent of HZ
"not be way longer" reads better I think?
> + * configuration, use fsleep(). See fsleep() for detailes of
^
details
> + * used sleeping functions.
> */
> - if (ms <= 20)
> - usleep_range(ms * 100, ms * 1000);
> - else
> - msleep(ms);
> + fsleep(ms * 1000);
> break;
> case RTAS_BUSY:
> ret = true;
Acked-by: Michael Ellerman <mpe@ellerman.id.au> (powerpc)
cheers
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [PATCH 06/15] timers: Update function descriptions of sleep/delay related functions
2024-09-05 6:59 ` Thomas Gleixner
@ 2024-09-05 16:07 ` Thomas Gleixner
2024-09-05 19:49 ` Anna-Maria Behnsen
0 siblings, 1 reply; 43+ messages in thread
From: Thomas Gleixner @ 2024-09-05 16:07 UTC (permalink / raw)
To: Anna-Maria Behnsen, Frederic Weisbecker, Jonathan Corbet
Cc: linux-kernel, Len Brown, Rafael J. Wysocki, Anna-Maria Behnsen,
Arnd Bergmann, linux-arch, Andrew Morton, Nathan Chancellor,
Nick Desaulniers
On Thu, Sep 05 2024 at 08:59, Thomas Gleixner wrote:
> On Wed, Sep 04 2024 at 15:04, Anna-Maria Behnsen wrote:
> However, instead of proliferating this voodoo can we please convert it
> into something comprehensible?
>
> /*
> * The microseconds delay multiplicator is used to convert a constant
> * microseconds value to a <INSERT COHERENT EXPLANATION>.
> */
> #define UDELAY_CONST_MULT ((unsigned long)DIV_ROUND_UP(1ULL << 32, USEC_PER_SEC))
>
> /*
> * The maximum constant udelay value picked out of thin air
> * to avoid <INSERT COHERENT EXPLANATION>.
> */
> #define UDELAY_CONST_MAX 20000
>
> /**
> * udelay - .....
> */
> static __always_inline void udelay(unsigned long usec)
> {
> /*
> * <INSERT COHERENT EXPLANATION> for this construct
> */
> if (__builtin_constant_p(usec)) {
> if (usec >= UDELAY_CONST_MAX)
> __bad_udelay();
> else
> __const_udelay(usec * UDELAY_CONST_MULT);
> } else {
> __udelay(usec);
And of course a these magic numeric constants have been copied all over
the place. git grep '__const_udelay(' arch/ .... Just SH managed to use
0x10c6 instead of 0x10c7.
ARM has it's own udelay implementation:
#define udelay(n) \
(__builtin_constant_p(n) ? \
((n) > (MAX_UDELAY_MS * 1000) ? __bad_udelay() : \
__const_udelay((n) * UDELAY_MULT)) : \
__udelay(n))
Amazingly this uses the same comparison construct which was in the
generic udelay implementation... Same for arc, m68k and microblaze.
Plus the default implementation for mdelay() in linux/delay.h:
#define mdelay(n) (\
(__builtin_constant_p(n) && (n)<=MAX_UDELAY_MS) ? udelay((n)*1000) : \
({unsigned long __ms=(n); while (__ms--) udelay(1000);}))
Oh well....
What's truly amazing is that all __udelay() implementations, which
invoke __const_udelay() under the hood, do:
__const_udelay(usec * 0x10c7);
So we have an arbitrary range limit for constants, which makes the build
fail. But the variable based udelays can hand in whatever they want and
__udelay() happily ignores it including the possible multiplication
overflow.
That's all really consistently copy and pasted voodoo. The other
architecture implementations are not much better in that regard. The
main difference is their cutoff value for __const_udelay() and the
multiplication factors.
The below uncompiled and untested pile is an attempt to consolidate this
mess as far as it goes. There is probably more to mop up, but for a
start this makes already sense.
Thanks,
tglx
---
arch/Kconfig | 3
arch/arc/include/asm/delay.h | 43 ------------
arch/arm64/Kconfig | 1
arch/arm64/lib/delay.c | 29 --------
arch/csky/Kconfig | 1
arch/csky/lib/delay.c | 22 ------
arch/loongarch/Kconfig | 1
arch/loongarch/include/asm/delay.h | 16 ----
arch/loongarch/lib/delay.c | 23 ------
arch/microblaze/Kconfig | 1
arch/microblaze/include/asm/delay.h | 48 --------------
arch/mips/Kconfig | 1
arch/mips/include/asm/delay.h | 18 ++---
arch/mips/lib/delay.c | 29 +-------
arch/nios2/Kconfig | 1
arch/nios2/lib/delay.c | 22 ------
arch/openrisc/Kconfig | 1
arch/openrisc/lib/delay.c | 22 ------
arch/sh/Kconfig | 1
arch/sh/kernel/sh_ksyms_32.c | 4 -
arch/sh/lib/delay.c | 23 +-----
arch/x86/Kconfig | 1
arch/x86/include/asm/delay.h | 9 ++
arch/x86/lib/delay.c | 23 ------
arch/x86/um/delay.c | 24 -------
include/asm-generic/delay.h | 120 +++++++++++++++++++++++++++---------
26 files changed, 145 insertions(+), 342 deletions(-)
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -55,6 +55,9 @@ config HOTPLUG_PARALLEL
bool
select HOTPLUG_SPLIT_STARTUP
+config GENERIC_DELAY
+ bool
+
config GENERIC_ENTRY
bool
--- a/arch/arc/include/asm/delay.h
+++ b/arch/arc/include/asm/delay.h
@@ -14,11 +14,6 @@
#ifndef __ASM_ARC_UDELAY_H
#define __ASM_ARC_UDELAY_H
-#include <asm-generic/types.h>
-#include <asm/param.h> /* HZ */
-
-extern unsigned long loops_per_jiffy;
-
static inline void __delay(unsigned long loops)
{
__asm__ __volatile__(
@@ -27,43 +22,11 @@ static inline void __delay(unsigned long
" nop \n"
"1: \n"
:
- : "r"(loops)
- : "lp_count");
+ : "r"(loops)
+ : "lp_count");
}
-extern void __bad_udelay(void);
-
-/*
- * Normal Math for computing loops in "N" usecs
- * -we have precomputed @loops_per_jiffy
- * -1 sec has HZ jiffies
- * loops per "N" usecs = ((loops_per_jiffy * HZ / 1000000) * N)
- *
- * Approximate Division by multiplication:
- * -Mathematically if we multiply and divide a number by same value the
- * result remains unchanged: In this case, we use 2^32
- * -> (loops_per_N_usec * 2^32 ) / 2^32
- * -> (((loops_per_jiffy * HZ / 1000000) * N) * 2^32) / 2^32
- * -> (loops_per_jiffy * HZ * N * 4295) / 2^32
- *
- * -Divide by 2^32 is very simply right shift by 32
- * -We simply need to ensure that the multiply per above eqn happens in
- * 64-bit precision (if CPU doesn't support it - gcc can emaulate it)
- */
-
-static inline void __udelay(unsigned long usecs)
-{
- unsigned long loops;
-
- /* (u64) cast ensures 64 bit MPY - real or emulated
- * HZ * 4295 is pre-evaluated by gcc - hence only 2 mpy ops
- */
- loops = ((u64) usecs * 4295 * HZ * loops_per_jiffy) >> 32;
-
- __delay(loops);
-}
+#include <asm-generic/delay.h>
-#define udelay(n) (__builtin_constant_p(n) ? ((n) > 20000 ? __bad_udelay() \
- : __udelay(n)) : __udelay(n))
#endif /* __ASM_ARC_UDELAY_H */
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -138,6 +138,7 @@ config ARM64
select GENERIC_CPU_AUTOPROBE
select GENERIC_CPU_DEVICES
select GENERIC_CPU_VULNERABILITIES
+ select GENERIC_DELAY
select GENERIC_EARLY_IOREMAP
select GENERIC_IDLE_POLL_SETUP
select GENERIC_IOREMAP
--- a/arch/arm64/lib/delay.c
+++ b/arch/arm64/lib/delay.c
@@ -15,13 +15,8 @@
#include <clocksource/arm_arch_timer.h>
-#define USECS_TO_CYCLES(time_usecs) \
- xloops_to_cycles((time_usecs) * 0x10C7UL)
-
-static inline unsigned long xloops_to_cycles(unsigned long xloops)
-{
- return (xloops * loops_per_jiffy * HZ) >> 32;
-}
+#define USECS_TO_CYCLES(time_usecs) \
+ (usec * DELAY_MULT_LPJ * UDELAY_MULT) >> UDELAY_SHIFT)
void __delay(unsigned long cycles)
{
@@ -37,7 +32,7 @@ void __delay(unsigned long cycles)
wfit(end);
while ((get_cycles() - start) < cycles)
wfet(end);
- } else if (arch_timer_evtstrm_available()) {
+ } else if (arch_timer_evtstrm_available()) {
const cycles_t timer_evt_period =
USECS_TO_CYCLES(ARCH_TIMER_EVT_STREAM_PERIOD_US);
@@ -49,21 +44,3 @@ void __delay(unsigned long cycles)
cpu_relax();
}
EXPORT_SYMBOL(__delay);
-
-inline void __const_udelay(unsigned long xloops)
-{
- __delay(xloops_to_cycles(xloops));
-}
-EXPORT_SYMBOL(__const_udelay);
-
-void __udelay(unsigned long usecs)
-{
- __const_udelay(usecs * 0x10C7UL); /* 2**32 / 1000000 (rounded up) */
-}
-EXPORT_SYMBOL(__udelay);
-
-void __ndelay(unsigned long nsecs)
-{
- __const_udelay(nsecs * 0x5UL); /* 2**32 / 1000000000 (rounded up) */
-}
-EXPORT_SYMBOL(__ndelay);
--- a/arch/csky/Kconfig
+++ b/arch/csky/Kconfig
@@ -48,6 +48,7 @@ config CSKY
select DMA_DIRECT_REMAP
select IRQ_DOMAIN
select DW_APB_TIMER_OF
+ select GENERIC_DELAY
select GENERIC_IOREMAP
select GENERIC_LIB_ASHLDI3
select GENERIC_LIB_ASHRDI3
--- a/arch/csky/lib/delay.c
+++ b/arch/csky/lib/delay.c
@@ -15,25 +15,3 @@ void __aligned(8) __delay(unsigned long
: "0"(loops));
}
EXPORT_SYMBOL(__delay);
-
-void __const_udelay(unsigned long xloops)
-{
- unsigned long long loops;
-
- loops = (unsigned long long)xloops * loops_per_jiffy * HZ;
-
- __delay(loops >> 32);
-}
-EXPORT_SYMBOL(__const_udelay);
-
-void __udelay(unsigned long usecs)
-{
- __const_udelay(usecs * 0x10C7UL); /* 2**32 / 1000000 (rounded up) */
-}
-EXPORT_SYMBOL(__udelay);
-
-void __ndelay(unsigned long nsecs)
-{
- __const_udelay(nsecs * 0x5UL); /* 2**32 / 1000000000 (rounded up) */
-}
-EXPORT_SYMBOL(__ndelay);
--- a/arch/loongarch/Kconfig
+++ b/arch/loongarch/Kconfig
@@ -82,6 +82,7 @@ config LOONGARCH
select GENERIC_CMOS_UPDATE
select GENERIC_CPU_AUTOPROBE
select GENERIC_CPU_DEVICES
+ select GENERIC_DELAY
select GENERIC_ENTRY
select GENERIC_GETTIMEOFDAY
select GENERIC_IOREMAP if !ARCH_IOREMAP
--- a/arch/loongarch/include/asm/delay.h
+++ b/arch/loongarch/include/asm/delay.h
@@ -7,20 +7,8 @@
#include <linux/param.h>
-extern void __delay(unsigned long cycles);
-extern void __ndelay(unsigned long ns);
-extern void __udelay(unsigned long us);
+#define DELAY_LPJ_MULT lpj_fine
-#define ndelay(ns) __ndelay(ns)
-#define udelay(us) __udelay(us)
-
-/* make sure "usecs *= ..." in udelay do not overflow. */
-#if HZ >= 1000
-#define MAX_UDELAY_MS 1
-#elif HZ <= 200
-#define MAX_UDELAY_MS 5
-#else
-#define MAX_UDELAY_MS (1000 / HZ)
-#endif
+#include <asm-generic/delay.h>
#endif /* _ASM_DELAY_H */
--- a/arch/loongarch/lib/delay.c
+++ b/arch/loongarch/lib/delay.c
@@ -17,26 +17,3 @@ void __delay(unsigned long cycles)
cpu_relax();
}
EXPORT_SYMBOL(__delay);
-
-/*
- * Division by multiplication: you don't have to worry about
- * loss of precision.
- *
- * Use only for very small delays ( < 1 msec). Should probably use a
- * lookup table, really, as the multiplications take much too long with
- * short delays. This is a "reasonable" implementation, though (and the
- * first constant multiplications gets optimized away if the delay is
- * a constant)
- */
-
-void __udelay(unsigned long us)
-{
- __delay((us * 0x000010c7ull * HZ * lpj_fine) >> 32);
-}
-EXPORT_SYMBOL(__udelay);
-
-void __ndelay(unsigned long ns)
-{
- __delay((ns * 0x00000005ull * HZ * lpj_fine) >> 32);
-}
-EXPORT_SYMBOL(__ndelay);
--- a/arch/microblaze/Kconfig
+++ b/arch/microblaze/Kconfig
@@ -16,6 +16,7 @@ config MICROBLAZE
select DMA_DIRECT_REMAP
select GENERIC_ATOMIC64
select GENERIC_CPU_DEVICES
+ select GENERIC_DELAY
select GENERIC_IDLE_POLL_SETUP
select GENERIC_IRQ_PROBE
select GENERIC_IRQ_SHOW
--- a/arch/microblaze/include/asm/delay.h
+++ b/arch/microblaze/include/asm/delay.h
@@ -33,53 +33,9 @@ static inline void __delay(unsigned long
* (which corresponds to ~3800 bogomips at HZ = 100).
* -- paulus
*/
-#define __MAX_UDELAY (226050910UL/HZ) /* maximum udelay argument */
-#define __MAX_NDELAY (4294967295UL/HZ) /* maximum ndelay argument */
-extern unsigned long loops_per_jiffy;
+#define UDELAY_ARCH_MULT (19 * 226)
-static inline void __udelay(unsigned int x)
-{
-
- unsigned long long tmp =
- (unsigned long long)x * (unsigned long long)loops_per_jiffy \
- * 226LL;
- unsigned loops = tmp >> 32;
-
-/*
- __asm__("mulxuu %0,%1,%2" : "=r" (loops) :
- "r" (x), "r" (loops_per_jiffy * 226));
-*/
- __delay(loops);
-}
-
-extern void __bad_udelay(void); /* deliberately undefined */
-extern void __bad_ndelay(void); /* deliberately undefined */
-
-#define udelay(n) \
- ({ \
- if (__builtin_constant_p(n)) { \
- if ((n) / __MAX_UDELAY >= 1) \
- __bad_udelay(); \
- else \
- __udelay((n) * (19 * HZ)); \
- } else { \
- __udelay((n) * (19 * HZ)); \
- } \
- })
-
-#define ndelay(n) \
- ({ \
- if (__builtin_constant_p(n)) { \
- if ((n) / __MAX_NDELAY >= 1) \
- __bad_ndelay(); \
- else \
- __udelay((n) * HZ); \
- } else { \
- __udelay((n) * HZ); \
- } \
- })
-
-#define muldiv(a, b, c) (((a)*(b))/(c))
+#include <asm-generic/delay.h>
#endif /* _ASM_MICROBLAZE_DELAY_H */
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -34,6 +34,7 @@ config MIPS
select GENERIC_ATOMIC64 if !64BIT
select GENERIC_CMOS_UPDATE
select GENERIC_CPU_AUTOPROBE
+ select GENERIC_DELAY if !CAVIUM_OCTEON_SOC
select GENERIC_GETTIMEOFDAY
select GENERIC_IOMAP
select GENERIC_IRQ_PROBE
--- a/arch/mips/include/asm/delay.h
+++ b/arch/mips/include/asm/delay.h
@@ -11,22 +11,22 @@
#ifndef _ASM_DELAY_H
#define _ASM_DELAY_H
-#include <linux/param.h>
+#ifdef CONFIG GENERIC_DELAY
+void __delay_loops(unsigned long long delay);
+#define __delay_loops __delay_loops
+#define DELAY_MULT_LPJ 1
+#define UDELAY_ARCH_SHIFT 0
+
+#include <asm-generic/delay.h>
+
+#else
extern void __delay(unsigned long loops);
extern void __ndelay(unsigned long ns);
extern void __udelay(unsigned long us);
#define ndelay(ns) __ndelay(ns)
#define udelay(us) __udelay(us)
-
-/* make sure "usecs *= ..." in udelay do not overflow. */
-#if HZ >= 1000
-#define MAX_UDELAY_MS 1
-#elif HZ <= 200
-#define MAX_UDELAY_MS 5
-#else
-#define MAX_UDELAY_MS (1000 / HZ)
#endif
#endif /* _ASM_DELAY_H */
--- a/arch/mips/lib/delay.c
+++ b/arch/mips/lib/delay.c
@@ -38,31 +38,12 @@ void __delay(unsigned long loops)
}
EXPORT_SYMBOL(__delay);
-/*
- * Division by multiplication: you don't have to worry about
- * loss of precision.
- *
- * Use only for very small delays ( < 1 msec). Should probably use a
- * lookup table, really, as the multiplications take much too long with
- * short delays. This is a "reasonable" implementation, though (and the
- * first constant multiplications gets optimized away if the delay is
- * a constant)
- */
-
-void __udelay(unsigned long us)
-{
- unsigned int lpj = raw_current_cpu_data.udelay_val;
-
- __delay((us * 0x000010c7ull * HZ * lpj) >> 32);
-}
-EXPORT_SYMBOL(__udelay);
-
-void __ndelay(unsigned long ns)
+void __delay_loops(unsigned long long delay)
{
- unsigned int lpj = raw_current_cpu_data.udelay_val;
+ unsigned long lpj = raw_current_cpu_data.udelay_val;
+ unsigned long xloops = (delay * lpj) >> 32;
- __delay((ns * 0x00000005ull * HZ * lpj) >> 32);
+ __delay(++xloops);
}
-EXPORT_SYMBOL(__ndelay);
-
+EXPORT_SYMBOL(__delay_loops);
#endif
--- a/arch/nios2/Kconfig
+++ b/arch/nios2/Kconfig
@@ -12,6 +12,7 @@ config NIOS2
select TIMER_OF
select GENERIC_ATOMIC64
select GENERIC_CPU_DEVICES
+ select GENERIC_DELAY
select GENERIC_IRQ_PROBE
select GENERIC_IRQ_SHOW
select HAVE_ARCH_TRACEHOOK
--- a/arch/nios2/lib/delay.c
+++ b/arch/nios2/lib/delay.c
@@ -16,25 +16,3 @@ void __delay(unsigned long cycles)
cpu_relax();
}
EXPORT_SYMBOL(__delay);
-
-void __const_udelay(unsigned long xloops)
-{
- u64 loops;
-
- loops = (u64)xloops * loops_per_jiffy * HZ;
-
- __delay(loops >> 32);
-}
-EXPORT_SYMBOL(__const_udelay);
-
-void __udelay(unsigned long usecs)
-{
- __const_udelay(usecs * 0x10C7UL); /* 2**32 / 1000000 (rounded up) */
-}
-EXPORT_SYMBOL(__udelay);
-
-void __ndelay(unsigned long nsecs)
-{
- __const_udelay(nsecs * 0x5UL); /* 2**32 / 1000000000 (rounded up) */
-}
-EXPORT_SYMBOL(__ndelay);
--- a/arch/openrisc/Kconfig
+++ b/arch/openrisc/Kconfig
@@ -17,6 +17,7 @@ config OPENRISC
select GPIOLIB
select HAVE_ARCH_TRACEHOOK
select SPARSE_IRQ
+ select GENERIC_DELAY
select GENERIC_IRQ_CHIP
select GENERIC_IRQ_PROBE
select GENERIC_IRQ_SHOW
--- a/arch/openrisc/lib/delay.c
+++ b/arch/openrisc/lib/delay.c
@@ -35,25 +35,3 @@ void __delay(unsigned long cycles)
cpu_relax();
}
EXPORT_SYMBOL(__delay);
-
-inline void __const_udelay(unsigned long xloops)
-{
- unsigned long long loops;
-
- loops = (unsigned long long)xloops * loops_per_jiffy * HZ;
-
- __delay(loops >> 32);
-}
-EXPORT_SYMBOL(__const_udelay);
-
-void __udelay(unsigned long usecs)
-{
- __const_udelay(usecs * 0x10C7UL); /* 2**32 / 1000000 (rounded up) */
-}
-EXPORT_SYMBOL(__udelay);
-
-void __ndelay(unsigned long nsecs)
-{
- __const_udelay(nsecs * 0x5UL); /* 2**32 / 1000000000 (rounded up) */
-}
-EXPORT_SYMBOL(__ndelay);
--- a/arch/sh/Kconfig
+++ b/arch/sh/Kconfig
@@ -18,6 +18,7 @@ config SUPERH
select DMA_DECLARE_COHERENT
select GENERIC_ATOMIC64
select GENERIC_CMOS_UPDATE if SH_SH03 || SH_DREAMCAST
+ select GENERIC_DELAY
select GENERIC_IDLE_POLL_SETUP
select GENERIC_IRQ_SHOW
select GENERIC_LIB_ASHLDI3
--- a/arch/sh/kernel/sh_ksyms_32.c
+++ b/arch/sh/kernel/sh_ksyms_32.c
@@ -12,9 +12,7 @@ EXPORT_SYMBOL(memcpy);
EXPORT_SYMBOL(memset);
EXPORT_SYMBOL(memmove);
EXPORT_SYMBOL(__copy_user);
-EXPORT_SYMBOL(__udelay);
-EXPORT_SYMBOL(__ndelay);
-EXPORT_SYMBOL(__const_udelay);
+EXPORT_SYMBOL(__delay_loops);
EXPORT_SYMBOL(strlen);
EXPORT_SYMBOL(csum_partial);
EXPORT_SYMBOL(csum_partial_copy_generic);
--- a/arch/sh/lib/delay.c
+++ b/arch/sh/lib/delay.c
@@ -30,25 +30,10 @@ void __delay(unsigned long loops)
: "t");
}
-inline void __const_udelay(unsigned long xloops)
+void __delay_loops(unsigned long long delay)
{
- xloops *= 4;
- __asm__("dmulu.l %0, %2\n\t"
- "sts mach, %0"
- : "=r" (xloops)
- : "0" (xloops),
- "r" (cpu_data[raw_smp_processor_id()].loops_per_jiffy * (HZ/4))
- : "macl", "mach");
- __delay(++xloops);
-}
-
-void __udelay(unsigned long usecs)
-{
- __const_udelay(usecs * 0x000010c6); /* 2**32 / 1000000 */
-}
+ unsigned long lpj = cpu_data[raw_smp_processor_id()].loops_per_jiffy;
+ unsigned long xloops = (delay * lpj) >> 32;
-void __ndelay(unsigned long nsecs)
-{
- __const_udelay(nsecs * 0x00000005);
+ __delay(++xloops);
}
-
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -156,6 +156,7 @@ config X86
select GENERIC_CPU_AUTOPROBE
select GENERIC_CPU_DEVICES
select GENERIC_CPU_VULNERABILITIES
+ select GENERIC_DELAY
select GENERIC_EARLY_IOREMAP
select GENERIC_ENTRY
select GENERIC_IOMAP
--- a/arch/x86/include/asm/delay.h
+++ b/arch/x86/include/asm/delay.h
@@ -2,9 +2,16 @@
#ifndef _ASM_X86_DELAY_H
#define _ASM_X86_DELAY_H
-#include <asm-generic/delay.h>
#include <linux/init.h>
+void __delay_loops(unsigned long long delay);
+
+#define __delay_loops __delay_loops
+#define DELAY_MULT_LPJ 1
+#define UDELAY_ARCH_SHIFT 0
+
+#include <asm-generic/delay.h>
+
void __init use_tsc_delay(void);
void __init use_tpause_delay(void);
void use_mwaitx_delay(void);
--- a/arch/x86/lib/delay.c
+++ b/arch/x86/lib/delay.c
@@ -204,28 +204,11 @@ void __delay(unsigned long loops)
}
EXPORT_SYMBOL(__delay);
-noinline void __const_udelay(unsigned long xloops)
+void __delay_loops(unsigned long long delay)
{
unsigned long lpj = this_cpu_read(cpu_info.loops_per_jiffy) ? : loops_per_jiffy;
- int d0;
-
- xloops *= 4;
- asm("mull %%edx"
- :"=d" (xloops), "=&a" (d0)
- :"1" (xloops), "0" (lpj * (HZ / 4)));
+ unsigned long xloops = (delay * lpj) >> 32;
__delay(++xloops);
}
-EXPORT_SYMBOL(__const_udelay);
-
-void __udelay(unsigned long usecs)
-{
- __const_udelay(usecs * 0x000010c7); /* 2**32 / 1000000 (rounded up) */
-}
-EXPORT_SYMBOL(__udelay);
-
-void __ndelay(unsigned long nsecs)
-{
- __const_udelay(nsecs * 0x00005); /* 2**32 / 1000000000 (rounded up) */
-}
-EXPORT_SYMBOL(__ndelay);
+EXPORT_SYMBOL(__delay_loops);
--- a/arch/x86/um/delay.c
+++ b/arch/x86/um/delay.c
@@ -30,28 +30,10 @@ void __delay(unsigned long loops)
}
EXPORT_SYMBOL(__delay);
-inline void __const_udelay(unsigned long xloops)
+void __delay_loops(unsigned long long delay)
{
- int d0;
-
- xloops *= 4;
- asm("mull %%edx"
- : "=d" (xloops), "=&a" (d0)
- : "1" (xloops), "0"
- (loops_per_jiffy * (HZ/4)));
+ unsigned long xloops = (delay * loops_per_jiffy) >> 32;
__delay(++xloops);
}
-EXPORT_SYMBOL(__const_udelay);
-
-void __udelay(unsigned long usecs)
-{
- __const_udelay(usecs * 0x000010c7); /* 2**32 / 1000000 (rounded up) */
-}
-EXPORT_SYMBOL(__udelay);
-
-void __ndelay(unsigned long nsecs)
-{
- __const_udelay(nsecs * 0x00005); /* 2**32 / 1000000000 (rounded up) */
-}
-EXPORT_SYMBOL(__ndelay);
+EXPORT_SYMBOL(__delay_loops);
--- a/include/asm-generic/delay.h
+++ b/include/asm-generic/delay.h
@@ -2,44 +2,104 @@
#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);
-extern void __udelay(unsigned long usecs);
-extern void __ndelay(unsigned long nsecs);
-extern void __const_udelay(unsigned long xloops);
extern void __delay(unsigned long loops);
+#ifdef CONFIG_GENERIC_UDELAY
+#ifndef UDELAY_ARCH_MULT
+# define UDELAY_ARCH_MULT 1ULL
+#endif
+
+#ifdef UDELAY_ARCH_SHIFT
+# define UDELAY_SHIFT UDELAY_ARCH_SHIFT
+#else
+# define UDELAY_SHIFT 32
+#endif
+
+#define __UDELAY_MULT ((unsigned long long)UDELAY_ARCH_MULT * HZ)
+#define UDELAY_MULT ((unsigned long)DIV_ROUND_UP(__UDELAY_MULT << 32, USEC_PER_SEC))
+#define NDELAY_MULT DIV_ROUND_UP(UDELAY_MULT, NSEC_PER_USEC)
+
/*
- * 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.
+ * Generous upper bound for loops per jiffy assuming a maximal CPU
+ * frequency of 8GHz and 1 cycle per loop.
*/
+#define LPJ_MAX ((8ULL * NSEC_PER_SEC) / HZ)
-/* 0x10c7 is 2**32 / 1000000 (rounded up) */
-#define udelay(n) \
- ({ \
- if (__builtin_constant_p(n)) { \
- if ((n) / 20000 >= 1) \
- __bad_udelay(); \
- else \
- __const_udelay((n) * 0x10c7ul); \
- } else { \
- __udelay(n); \
- } \
- })
-
-/* 0x5 is 2**32 / 1000000000 (rounded up) */
-#define ndelay(n) \
- ({ \
- if (__builtin_constant_p(n)) { \
- if ((n) / 20000 >= 1) \
- __bad_ndelay(); \
- else \
- __const_udelay((n) * 5ul); \
- } else { \
- __ndelay(n); \
- } \
- })
+/*
+ * The maximum usec value depends on the multiplication factor and the
+ * maximum upper bound for loops_per_jiffy to guarantee that there is
+ * no multiplication overflow when __delay_loops() multiplies the
+ * argument with the actual loops_per_jiffy value.
+ */
+#define UDELAY_CONST_MAX (unsigned long)(U64_MAX / (LPJ_MAX * UDELAY_MULT))
+#define NDELAY_CONST_MAX (UDELAY_CONST_MAX * NSEC_PER_USEC)
+
+#ifndef DELAY_MULT_LPJ
+#define DELAY_MULT_LPJ loops_per_jiffy
+#endif
+
+#ifndef __delay_loops
+#define __delay_loops(x) __delay(x)
+#endif
+
+static __always_inline void __udelay(unsigned long usec)
+{
+ /* FIXME: Add a debug sanity check for usec > UDELAY_CONST_MAX */
+ __delay_loops((usec * DELAY_MULT_LPJ * UDELAY_MULT) >> UDELAY_SHIFT);
+}
+
+static __always_inline void __ndelay(unsigned long nsec)
+{
+ /* FIXME: Add a debug sanity check for usec > NDELAY_CONST_MAX */
+ __delay_loops((nsec * DELAY_MULT_LPJ * NDELAY_MULT) >> UDELAY_SHIFT);
+}
+
+#define __const_udelay_wrapper(usec, mult) __udelay(usec)
+#define __const_ndelay_wrapper(usec, mult) __ndelay(usec)
+
+#else
+/* Does any of this make sense? No. */
+#define UDELAY_CONST_MULT ((unsigned long)DIV_ROUND_UP((1ULL << 32), USEC_PER_SEC))
+#define NDELAY_CONST_MULT (UDELAY_CONST_MULT / NSEC_PER_USEC)
+#define UDELAY_CONST_MAX 20000
+#define NDELAY_CONST_MAX 20000
+extern void __const_udelay(unsigned long xloops);
+extern void __udelay(unsigned long usecs);
+extern void __ndelay(unsigned long nsecs);
+#define __const_udelay_wrapper(usec) __const_udelay(usec * UDELAY_CONST_MULT)
+#define __const_ndelay_wrapper(nsec) __const_udelay(nsec * NDELAY_CONST_MULT)
+#endif
+
+static __always_inline void _udelay(unsigned long usec)
+{
+ if (__builtin_constant_p(usec)) {
+ if (usec >= UDELAY_CONST_MAX)
+ __bad_udelay();
+ else
+ __const_udelay_wrapper(usec);
+ } else {
+ __udelay(usec);
+ }
+}
+#define udelay(x) _udelay(x)
+
+static __always_inline void _ndelay(unsigned long usec)
+{
+ if (__builtin_constant_p(usec)) {
+ if (usec >= NDELAY_CONST_MAX)
+ __bad_ndelay();
+ else
+ __const_ndelay_wrapper(usec);
+ } else {
+ __ndelay(usec);
+ }
+}
+#define ndelay(x) _ndelay(x)
#endif /* __ASM_GENERIC_DELAY_H */
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [PATCH 06/15] timers: Update function descriptions of sleep/delay related functions
2024-09-05 16:07 ` Thomas Gleixner
@ 2024-09-05 19:49 ` Anna-Maria Behnsen
0 siblings, 0 replies; 43+ messages in thread
From: Anna-Maria Behnsen @ 2024-09-05 19:49 UTC (permalink / raw)
To: Thomas Gleixner, Frederic Weisbecker, Jonathan Corbet
Cc: linux-kernel, Len Brown, Rafael J. Wysocki, Arnd Bergmann,
linux-arch, Andrew Morton, Nathan Chancellor, Nick Desaulniers
Thomas Gleixner <tglx@linutronix.de> writes:
> On Thu, Sep 05 2024 at 08:59, Thomas Gleixner wrote:
>> On Wed, Sep 04 2024 at 15:04, Anna-Maria Behnsen wrote:
>> However, instead of proliferating this voodoo can we please convert it
>> into something comprehensible?
>>
>> /*
>> * The microseconds delay multiplicator is used to convert a constant
>> * microseconds value to a <INSERT COHERENT EXPLANATION>.
>> */
>> #define UDELAY_CONST_MULT ((unsigned long)DIV_ROUND_UP(1ULL << 32, USEC_PER_SEC))
>>
>> /*
>> * The maximum constant udelay value picked out of thin air
>> * to avoid <INSERT COHERENT EXPLANATION>.
>> */
>> #define UDELAY_CONST_MAX 20000
>>
>> /**
>> * udelay - .....
>> */
>> static __always_inline void udelay(unsigned long usec)
>> {
>> /*
>> * <INSERT COHERENT EXPLANATION> for this construct
>> */
>> if (__builtin_constant_p(usec)) {
>> if (usec >= UDELAY_CONST_MAX)
>> __bad_udelay();
>> else
>> __const_udelay(usec * UDELAY_CONST_MULT);
>> } else {
>> __udelay(usec);
>
> And of course a these magic numeric constants have been copied all over
> the place. git grep '__const_udelay(' arch/ .... Just SH managed to use
> 0x10c6 instead of 0x10c7.
>
> ARM has it's own udelay implementation:
>
> #define udelay(n) \
> (__builtin_constant_p(n) ? \
> ((n) > (MAX_UDELAY_MS * 1000) ? __bad_udelay() : \
> __const_udelay((n) * UDELAY_MULT)) : \
> __udelay(n))
>
> Amazingly this uses the same comparison construct which was in the
> generic udelay implementation... Same for arc, m68k and microblaze.
>
> Plus the default implementation for mdelay() in linux/delay.h:
>
> #define mdelay(n) (\
> (__builtin_constant_p(n) && (n)<=MAX_UDELAY_MS) ? udelay((n)*1000) : \
> ({unsigned long __ms=(n); while (__ms--) udelay(1000);}))
>
> Oh well....
>
> What's truly amazing is that all __udelay() implementations, which
> invoke __const_udelay() under the hood, do:
>
> __const_udelay(usec * 0x10c7);
>
> So we have an arbitrary range limit for constants, which makes the build
> fail. But the variable based udelays can hand in whatever they want and
> __udelay() happily ignores it including the possible multiplication
> overflow.
>
> That's all really consistently copy and pasted voodoo. The other
> architecture implementations are not much better in that regard. The
> main difference is their cutoff value for __const_udelay() and the
> multiplication factors.
>
> The below uncompiled and untested pile is an attempt to consolidate this
> mess as far as it goes. There is probably more to mop up, but for a
> start this makes already sense.
Thanks for the first step of dissection of the mess! I'll take a closer
look at it soon.
But as it's in tree since some more days than just one, can we please
make this cleanup on top of the original queue and get the fsleep() and
outdated documentation thing fixed soon? You made a proposal in the
previous answer to convert it into something comprehensible. If there
are no concerns, I would integrate it and prepare a v2 for the queue.
Thanks,
Anna-Maria
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [PATCH 01/15] timers: Rename next_expiry_recalc() to be unique
2024-09-04 13:04 ` [PATCH 01/15] timers: Rename next_expiry_recalc() to be unique Anna-Maria Behnsen
@ 2024-09-06 13:25 ` Frederic Weisbecker
2024-09-08 18:58 ` [tip: timers/core] " tip-bot2 for Anna-Maria Behnsen
1 sibling, 0 replies; 43+ messages in thread
From: Frederic Weisbecker @ 2024-09-06 13:25 UTC (permalink / raw)
To: Anna-Maria Behnsen
Cc: Thomas Gleixner, Jonathan Corbet, linux-kernel, Len Brown,
Rafael J. Wysocki
Le Wed, Sep 04, 2024 at 03:04:51PM +0200, Anna-Maria Behnsen a écrit :
> next_expiry_recalc is the name of a function as well as the name of a
> struct member of struct timer_base. This might lead to confusion.
>
> Rename next_expiry_recalc() to timer_recalc_next_expiry(). No functional
> change.
>
> Signed-off-by: Anna-Maria Behnsen <anna-maria@linutronix.de>
Reviewed-by: Frederic Weisbecker <frederic@kernel.org>
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [PATCH 02/15] cpu: Use already existing usleep_range()
2024-09-04 13:04 ` [PATCH 02/15] cpu: Use already existing usleep_range() Anna-Maria Behnsen
@ 2024-09-06 13:27 ` Frederic Weisbecker
2024-09-08 18:58 ` [tip: timers/core] " tip-bot2 for Anna-Maria Behnsen
1 sibling, 0 replies; 43+ messages in thread
From: Frederic Weisbecker @ 2024-09-06 13:27 UTC (permalink / raw)
To: Anna-Maria Behnsen
Cc: Thomas Gleixner, Jonathan Corbet, linux-kernel, Len Brown,
Rafael J. Wysocki, Peter Zijlstra
Le Wed, Sep 04, 2024 at 03:04:52PM +0200, Anna-Maria Behnsen a écrit :
> usleep_range() is a wrapper arount usleep_range_state() which hands in
> TASK_UNTINTERRUPTIBLE as state argument.
>
> Use already exising wrapper usleep_range(). No functional change.
>
> Cc: Peter Zijlstra <peterz@infradead.org>
> Signed-off-by: Anna-Maria Behnsen <anna-maria@linutronix.de>
Reviewed-by: Frederic Weisbecker <frederic@kernel.org>
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [PATCH 04/15] timers: Move *sleep*() and timeout functions into a separate file
2024-09-04 13:04 ` [PATCH 04/15] timers: Move *sleep*() and timeout functions into a separate file Anna-Maria Behnsen
@ 2024-09-06 13:42 ` Frederic Weisbecker
2024-09-09 8:10 ` Anna-Maria Behnsen
2024-09-08 18:58 ` [tip: timers/core] " tip-bot2 for Anna-Maria Behnsen
1 sibling, 1 reply; 43+ messages in thread
From: Frederic Weisbecker @ 2024-09-06 13:42 UTC (permalink / raw)
To: Anna-Maria Behnsen
Cc: Thomas Gleixner, Jonathan Corbet, linux-kernel, Len Brown,
Rafael J. Wysocki
Le Wed, Sep 04, 2024 at 03:04:54PM +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(). While at it also add not listed
> include/linux/delay.h to the MAINTAINTERS file.
I don't mind sometimes having several logical changes within a same
patch if that makes sense but the delay is MAINTAINERS is pretty off-topic
and should move to its own patch.
>
> Signed-off-by: Anna-Maria Behnsen <anna-maria@linutronix.de>
For the rest:
Acked-by: Frederic Weisbecker <frederic@kernel.org>
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [PATCH 05/15] timers: Rename sleep_idle_range() to sleep_range_idle()
2024-09-04 13:04 ` [PATCH 05/15] timers: Rename sleep_idle_range() to sleep_range_idle() Anna-Maria Behnsen
@ 2024-09-06 13:45 ` Frederic Weisbecker
2024-09-06 16:25 ` SeongJae Park
2024-09-08 18:58 ` [tip: timers/core] " tip-bot2 for Anna-Maria Behnsen
2 siblings, 0 replies; 43+ messages in thread
From: Frederic Weisbecker @ 2024-09-06 13:45 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 04, 2024 at 03:04:55PM +0200, Anna-Maria Behnsen a écrit :
> sleep_idle_range() is a variant of sleep_range(). Both are using
> sleep_range_state() as a base. To be able to find all the related functions
> in one go, rename it sleep_idle_range() to sleep_range_idle().
>
> No functional change.
>
> 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: Frederic Weisbecker <frederic@kernel.org>
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [PATCH 05/15] timers: Rename sleep_idle_range() to sleep_range_idle()
2024-09-04 13:04 ` [PATCH 05/15] timers: Rename sleep_idle_range() to sleep_range_idle() Anna-Maria Behnsen
2024-09-06 13:45 ` Frederic Weisbecker
@ 2024-09-06 16:25 ` SeongJae Park
2024-09-08 18:58 ` [tip: timers/core] " tip-bot2 for Anna-Maria Behnsen
2 siblings, 0 replies; 43+ messages in thread
From: SeongJae Park @ 2024-09-06 16:25 UTC (permalink / raw)
To: Anna-Maria Behnsen
Cc: SeongJae Park, Frederic Weisbecker, Thomas Gleixner,
Jonathan Corbet, linux-kernel, Len Brown, Rafael J. Wysocki,
Andrew Morton, damon, linux-mm
On Wed, 04 Sep 2024 15:04:55 +0200 Anna-Maria Behnsen <anna-maria@linutronix.de> wrote:
> sleep_idle_range() is a variant of sleep_range(). Both are using
> sleep_range_state() as a base. To be able to find all the related functions
> in one go, rename it sleep_idle_range() to sleep_range_idle().
Nit. s/sleep_/usleep_/?
>
> No functional change.
>
> 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>
> ---
> 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 */
Other than the trivial nit,
Reviewed-by: SeongJae Park <sj@kernel.org>
Thanks,
SJ
>
> --
> 2.39.2
>
>
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [PATCH 08/15] mm/damon/core: Use generic upper bound recommondation for usleep_range()
2024-09-04 13:04 ` [PATCH 08/15] mm/damon/core: Use generic upper bound recommondation for usleep_range() Anna-Maria Behnsen
@ 2024-09-06 16:31 ` SeongJae Park
0 siblings, 0 replies; 43+ messages in thread
From: SeongJae Park @ 2024-09-06 16:31 UTC (permalink / raw)
To: Anna-Maria Behnsen
Cc: SeongJae Park, Frederic Weisbecker, Thomas Gleixner,
Jonathan Corbet, linux-kernel, Len Brown, Rafael J. Wysocki,
Andrew Morton, damon, linux-mm
On Wed, 04 Sep 2024 15:04:58 +0200 Anna-Maria Behnsen <anna-maria@linutronix.de> wrote:
> 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>
Thanks,
SJ
> ---
> 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 [flat|nested] 43+ messages in thread
* [tip: timers/core] timers: Rename sleep_idle_range() to sleep_range_idle()
2024-09-04 13:04 ` [PATCH 05/15] timers: Rename sleep_idle_range() to sleep_range_idle() Anna-Maria Behnsen
2024-09-06 13:45 ` Frederic Weisbecker
2024-09-06 16:25 ` SeongJae Park
@ 2024-09-08 18:58 ` tip-bot2 for Anna-Maria Behnsen
2 siblings, 0 replies; 43+ messages in thread
From: tip-bot2 for Anna-Maria Behnsen @ 2024-09-08 18:58 UTC (permalink / raw)
To: linux-tip-commits
Cc: Anna-Maria Behnsen, Thomas Gleixner, Frederic Weisbecker, x86,
linux-kernel
The following commit has been merged into the timers/core branch of tip:
Commit-ID: ad4890d40229151c3455b47d9c142def8105644c
Gitweb: https://git.kernel.org/tip/ad4890d40229151c3455b47d9c142def8105644c
Author: Anna-Maria Behnsen <anna-maria@linutronix.de>
AuthorDate: Wed, 04 Sep 2024 15:04:55 +02:00
Committer: Thomas Gleixner <tglx@linutronix.de>
CommitterDate: Sun, 08 Sep 2024 20:47:41 +02:00
timers: Rename sleep_idle_range() to sleep_range_idle()
sleep_idle_range() is a variant of sleep_range(). Both are using
sleep_range_state() as a base. To be able to find all the related functions
in one go, rename it sleep_idle_range() to sleep_range_idle().
No functional change.
Signed-off-by: Anna-Maria Behnsen <anna-maria@linutronix.de>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Frederic Weisbecker <frederic@kernel.org>
Link: https://lore.kernel.org/all/20240904-devel-anna-maria-b4-timers-flseep-v1-5-e98760256370@linutronix.de
---
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 ff9cda9..2bc586a 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 7a87628..94fe2f1 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 */
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [tip: timers/core] timers: Move *sleep*() and timeout functions into a separate file
2024-09-04 13:04 ` [PATCH 04/15] timers: Move *sleep*() and timeout functions into a separate file Anna-Maria Behnsen
2024-09-06 13:42 ` Frederic Weisbecker
@ 2024-09-08 18:58 ` tip-bot2 for Anna-Maria Behnsen
1 sibling, 0 replies; 43+ messages in thread
From: tip-bot2 for Anna-Maria Behnsen @ 2024-09-08 18:58 UTC (permalink / raw)
To: linux-tip-commits
Cc: Anna-Maria Behnsen, Thomas Gleixner, Frederic Weisbecker, x86,
linux-kernel
The following commit has been merged into the timers/core branch of tip:
Commit-ID: 0a40ec99477045a1ff5fc3e7597169a66b09db00
Gitweb: https://git.kernel.org/tip/0a40ec99477045a1ff5fc3e7597169a66b09db00
Author: Anna-Maria Behnsen <anna-maria@linutronix.de>
AuthorDate: Wed, 04 Sep 2024 15:04:54 +02:00
Committer: Thomas Gleixner <tglx@linutronix.de>
CommitterDate: Sun, 08 Sep 2024 20:47:40 +02:00
timers: Move *sleep*() and timeout functions into a separate file
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(). While at it also add not listed
include/linux/delay.h to the MAINTAINTERS file.
Signed-off-by: Anna-Maria Behnsen <anna-maria@linutronix.de>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Acked-by: Frederic Weisbecker <frederic@kernel.org>
Link: https://lore.kernel.org/all/20240904-devel-anna-maria-b4-timers-flseep-v1-4-e98760256370@linutronix.de
---
MAINTAINERS | 2 +-
kernel/time/Makefile | 2 +-
kernel/time/hrtimer.c | 120 +-------------
kernel/time/sleep_timeout.c | 320 +++++++++++++++++++++++++++++++++++-
kernel/time/timer.c | 192 +---------------------
5 files changed, 323 insertions(+), 313 deletions(-)
create mode 100644 kernel/time/sleep_timeout.c
diff --git a/MAINTAINERS b/MAINTAINERS
index 42decde..e9cb099 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -10010,10 +10010,12 @@ 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
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 4af2a26..fe0ae82 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 e834b2b..2750ce6 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 0000000..9ecbce7
--- /dev/null
+++ b/kernel/time/sleep_timeout.c
@@ -0,0 +1,320 @@
+// 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 2b38f30..bb53d22 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);
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [tip: timers/core] cpu: Use already existing usleep_range()
2024-09-04 13:04 ` [PATCH 02/15] cpu: Use already existing usleep_range() Anna-Maria Behnsen
2024-09-06 13:27 ` Frederic Weisbecker
@ 2024-09-08 18:58 ` tip-bot2 for Anna-Maria Behnsen
1 sibling, 0 replies; 43+ messages in thread
From: tip-bot2 for Anna-Maria Behnsen @ 2024-09-08 18:58 UTC (permalink / raw)
To: linux-tip-commits
Cc: Anna-Maria Behnsen, Thomas Gleixner, Frederic Weisbecker, x86,
linux-kernel
The following commit has been merged into the timers/core branch of tip:
Commit-ID: 662a1bfb907cd850da4de9b871640ad47a355bc0
Gitweb: https://git.kernel.org/tip/662a1bfb907cd850da4de9b871640ad47a355bc0
Author: Anna-Maria Behnsen <anna-maria@linutronix.de>
AuthorDate: Wed, 04 Sep 2024 15:04:52 +02:00
Committer: Thomas Gleixner <tglx@linutronix.de>
CommitterDate: Sun, 08 Sep 2024 20:47:40 +02:00
cpu: Use already existing usleep_range()
usleep_range() is a wrapper arount usleep_range_state() which hands in
TASK_UNTINTERRUPTIBLE as state argument.
Use already exising wrapper usleep_range(). No functional change.
Signed-off-by: Anna-Maria Behnsen <anna-maria@linutronix.de>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Frederic Weisbecker <frederic@kernel.org>
Link: https://lore.kernel.org/all/20240904-devel-anna-maria-b4-timers-flseep-v1-2-e98760256370@linutronix.de
---
kernel/cpu.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/kernel/cpu.c b/kernel/cpu.c
index 1209dda..031a2c1 100644
--- a/kernel/cpu.c
+++ b/kernel/cpu.c
@@ -330,7 +330,7 @@ static bool cpuhp_wait_for_sync_state(unsigned int cpu, enum cpuhp_sync_state st
/* Poll for one millisecond */
arch_cpuhp_sync_state_poll();
} else {
- usleep_range_state(USEC_PER_MSEC, 2 * USEC_PER_MSEC, TASK_UNINTERRUPTIBLE);
+ usleep_range(USEC_PER_MSEC, 2 * USEC_PER_MSEC);
}
sync = atomic_read(st);
}
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [tip: timers/core] treewide: Fix wrong singular form of jiffies in comments
2024-09-04 13:04 ` [PATCH 03/15] Comments: Fix wrong singular form of jiffies Anna-Maria Behnsen
2024-09-05 8:42 ` Geert Uytterhoeven
@ 2024-09-08 18:58 ` tip-bot2 for Anna-Maria Behnsen
1 sibling, 0 replies; 43+ messages in thread
From: tip-bot2 for Anna-Maria Behnsen @ 2024-09-08 18:58 UTC (permalink / raw)
To: linux-tip-commits
Cc: Anna-Maria Behnsen, Thomas Gleixner, Geert Uytterhoeven, x86,
linux-kernel
The following commit has been merged into the timers/core branch of tip:
Commit-ID: bd7c8ff9fef4b21a97f9b30a7364845ee6eaaf23
Gitweb: https://git.kernel.org/tip/bd7c8ff9fef4b21a97f9b30a7364845ee6eaaf23
Author: Anna-Maria Behnsen <anna-maria@linutronix.de>
AuthorDate: Wed, 04 Sep 2024 15:04:53 +02:00
Committer: Thomas Gleixner <tglx@linutronix.de>
CommitterDate: Sun, 08 Sep 2024 20:47:40 +02:00
treewide: Fix wrong singular form of jiffies in comments
There are several comments all over the place, which uses a wrong singular
form of jiffies.
Replace 'jiffie' by 'jiffy'. No functional change.
Signed-off-by: Anna-Maria Behnsen <anna-maria@linutronix.de>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Acked-by: Geert Uytterhoeven <geert@linux-m68k.org> # m68k
Link: https://lore.kernel.org/all/20240904-devel-anna-maria-b4-timers-flseep-v1-3-e98760256370@linutronix.de
---
Documentation/admin-guide/media/vivid.rst | 2 +-
Documentation/timers/timers-howto.rst | 2 +-
Documentation/translations/sp_SP/scheduler/sched-design-CFS.rst | 2 +-
arch/arm/mach-versatile/spc.c | 2 +-
arch/m68k/q40/q40ints.c | 2 +-
arch/x86/kernel/cpu/mce/dev-mcelog.c | 2 +-
drivers/char/ipmi/ipmi_ssif.c | 2 +-
drivers/dma-buf/st-dma-fence.c | 2 +-
drivers/gpu/drm/i915/gem/i915_gem_wait.c | 2 +-
drivers/gpu/drm/i915/gt/selftest_execlists.c | 4 ++--
drivers/gpu/drm/i915/i915_utils.c | 2 +-
drivers/gpu/drm/v3d/v3d_bo.c | 2 +-
drivers/isdn/mISDN/dsp_cmx.c | 2 +-
drivers/net/ethernet/marvell/mvmdio.c | 2 +-
fs/xfs/xfs_buf.h | 2 +-
include/linux/jiffies.h | 2 +-
include/linux/timekeeper_internal.h | 2 +-
kernel/time/alarmtimer.c | 2 +-
kernel/time/clockevents.c | 2 +-
kernel/time/hrtimer.c | 2 +-
kernel/time/posix-timers.c | 4 ++--
kernel/time/timer.c | 12 ++++++------
lib/Kconfig.debug | 2 +-
net/batman-adv/types.h | 2 +-
24 files changed, 31 insertions(+), 31 deletions(-)
diff --git a/Documentation/admin-guide/media/vivid.rst b/Documentation/admin-guide/media/vivid.rst
index 1306f19..c9d301a 100644
--- a/Documentation/admin-guide/media/vivid.rst
+++ b/Documentation/admin-guide/media/vivid.rst
@@ -328,7 +328,7 @@ and an HDMI input, one input for each input type. Those are described in more
detail below.
Special attention has been given to the rate at which new frames become
-available. The jitter will be around 1 jiffie (that depends on the HZ
+available. The jitter will be around 1 jiffy (that depends on the HZ
configuration of your kernel, so usually 1/100, 1/250 or 1/1000 of a second),
but the long-term behavior is exactly following the framerate. So a
framerate of 59.94 Hz is really different from 60 Hz. If the framerate
diff --git a/Documentation/timers/timers-howto.rst b/Documentation/timers/timers-howto.rst
index 5c169e3..ef7a465 100644
--- a/Documentation/timers/timers-howto.rst
+++ b/Documentation/timers/timers-howto.rst
@@ -19,7 +19,7 @@ it really need to delay in atomic context?" If so...
ATOMIC CONTEXT:
You must use the `*delay` family of functions. These
- functions use the jiffie estimation of clock speed
+ functions use the jiffy estimation of clock speed
and will busy wait for enough loop cycles to achieve
the desired delay:
diff --git a/Documentation/translations/sp_SP/scheduler/sched-design-CFS.rst b/Documentation/translations/sp_SP/scheduler/sched-design-CFS.rst
index 90a153c..731c266 100644
--- a/Documentation/translations/sp_SP/scheduler/sched-design-CFS.rst
+++ b/Documentation/translations/sp_SP/scheduler/sched-design-CFS.rst
@@ -109,7 +109,7 @@ para que se ejecute, y la tarea en ejecución es interrumpida.
==================================
CFS usa una granularidad de nanosegundos y no depende de ningún
-jiffie o detalles como HZ. De este modo, el gestor de tareas CFS no tiene
+jiffy o detalles como HZ. De este modo, el gestor de tareas CFS no tiene
noción de "ventanas de tiempo" de la forma en que tenía el gestor de
tareas previo, y tampoco tiene heurísticos. Únicamente hay un parámetro
central ajustable (se ha de cambiar en CONFIG_SCHED_DEBUG):
diff --git a/arch/arm/mach-versatile/spc.c b/arch/arm/mach-versatile/spc.c
index 5e44170..7900927 100644
--- a/arch/arm/mach-versatile/spc.c
+++ b/arch/arm/mach-versatile/spc.c
@@ -73,7 +73,7 @@
/*
* Even though the SPC takes max 3-5 ms to complete any OPP/COMMS
- * operation, the operation could start just before jiffie is about
+ * operation, the operation could start just before jiffy is about
* to be incremented. So setting timeout value of 20ms = 2jiffies@100Hz
*/
#define TIMEOUT_US 20000
diff --git a/arch/m68k/q40/q40ints.c b/arch/m68k/q40/q40ints.c
index 10f1f29..14b774b 100644
--- a/arch/m68k/q40/q40ints.c
+++ b/arch/m68k/q40/q40ints.c
@@ -106,7 +106,7 @@ void __init q40_init_IRQ(void)
* this stuff doesn't really belong here..
*/
-int ql_ticks; /* 200Hz ticks since last jiffie */
+int ql_ticks; /* 200Hz ticks since last jiffy */
static int sound_ticks;
#define SVOL 45
diff --git a/arch/x86/kernel/cpu/mce/dev-mcelog.c b/arch/x86/kernel/cpu/mce/dev-mcelog.c
index a05ac07..a3aa019 100644
--- a/arch/x86/kernel/cpu/mce/dev-mcelog.c
+++ b/arch/x86/kernel/cpu/mce/dev-mcelog.c
@@ -314,7 +314,7 @@ static ssize_t mce_chrdev_write(struct file *filp, const char __user *ubuf,
/*
* Need to give user space some time to set everything up,
- * so do it a jiffie or two later everywhere.
+ * so do it a jiffy or two later everywhere.
*/
schedule_timeout(2);
diff --git a/drivers/char/ipmi/ipmi_ssif.c b/drivers/char/ipmi/ipmi_ssif.c
index 96ad571..e093028 100644
--- a/drivers/char/ipmi/ipmi_ssif.c
+++ b/drivers/char/ipmi/ipmi_ssif.c
@@ -980,7 +980,7 @@ static void msg_written_handler(struct ssif_info *ssif_info, int result,
ipmi_ssif_unlock_cond(ssif_info, flags);
start_get(ssif_info);
} else {
- /* Wait a jiffie then request the next message */
+ /* Wait a jiffy then request the next message */
ssif_info->waiting_alert = true;
ssif_info->retries_left = SSIF_RECV_RETRIES;
if (!ssif_info->stopping)
diff --git a/drivers/dma-buf/st-dma-fence.c b/drivers/dma-buf/st-dma-fence.c
index 6a1bfcd..cf2ce37 100644
--- a/drivers/dma-buf/st-dma-fence.c
+++ b/drivers/dma-buf/st-dma-fence.c
@@ -402,7 +402,7 @@ static int test_wait_timeout(void *arg)
if (dma_fence_wait_timeout(wt.f, false, 2) == -ETIME) {
if (timer_pending(&wt.timer)) {
- pr_notice("Timer did not fire within the jiffie!\n");
+ pr_notice("Timer did not fire within the jiffy!\n");
err = 0; /* not our fault! */
} else {
pr_err("Wait reported incomplete after timeout\n");
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_wait.c b/drivers/gpu/drm/i915/gem/i915_gem_wait.c
index d4b918f..1f55e62 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_wait.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_wait.c
@@ -266,7 +266,7 @@ i915_gem_wait_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
if (ret == -ETIME && !nsecs_to_jiffies(args->timeout_ns))
args->timeout_ns = 0;
- /* Asked to wait beyond the jiffie/scheduler precision? */
+ /* Asked to wait beyond the jiffy/scheduler precision? */
if (ret == -ETIME && args->timeout_ns)
ret = -EAGAIN;
}
diff --git a/drivers/gpu/drm/i915/gt/selftest_execlists.c b/drivers/gpu/drm/i915/gt/selftest_execlists.c
index 4202df5..222ca7c 100644
--- a/drivers/gpu/drm/i915/gt/selftest_execlists.c
+++ b/drivers/gpu/drm/i915/gt/selftest_execlists.c
@@ -93,7 +93,7 @@ static int wait_for_reset(struct intel_engine_cs *engine,
return -EINVAL;
}
- /* Give the request a jiffie to complete after flushing the worker */
+ /* Give the request a jiffy to complete after flushing the worker */
if (i915_request_wait(rq, 0,
max(0l, (long)(timeout - jiffies)) + 1) < 0) {
pr_err("%s: hanging request %llx:%lld did not complete\n",
@@ -3426,7 +3426,7 @@ static int live_preempt_timeout(void *arg)
cpu_relax();
saved_timeout = engine->props.preempt_timeout_ms;
- engine->props.preempt_timeout_ms = 1; /* in ms, -> 1 jiffie */
+ engine->props.preempt_timeout_ms = 1; /* in ms, -> 1 jiffy */
i915_request_get(rq);
i915_request_add(rq);
diff --git a/drivers/gpu/drm/i915/i915_utils.c b/drivers/gpu/drm/i915/i915_utils.c
index 6f9e7b3..f2ba51c 100644
--- a/drivers/gpu/drm/i915/i915_utils.c
+++ b/drivers/gpu/drm/i915/i915_utils.c
@@ -110,7 +110,7 @@ void set_timer_ms(struct timer_list *t, unsigned long timeout)
* Paranoia to make sure the compiler computes the timeout before
* loading 'jiffies' as jiffies is volatile and may be updated in
* the background by a timer tick. All to reduce the complexity
- * of the addition and reduce the risk of losing a jiffie.
+ * of the addition and reduce the risk of losing a jiffy.
*/
barrier();
diff --git a/drivers/gpu/drm/v3d/v3d_bo.c b/drivers/gpu/drm/v3d/v3d_bo.c
index a165cbc..9eafe53 100644
--- a/drivers/gpu/drm/v3d/v3d_bo.c
+++ b/drivers/gpu/drm/v3d/v3d_bo.c
@@ -279,7 +279,7 @@ v3d_wait_bo_ioctl(struct drm_device *dev, void *data,
else
args->timeout_ns = 0;
- /* Asked to wait beyond the jiffie/scheduler precision? */
+ /* Asked to wait beyond the jiffy/scheduler precision? */
if (ret == -ETIME && args->timeout_ns)
ret = -EAGAIN;
diff --git a/drivers/isdn/mISDN/dsp_cmx.c b/drivers/isdn/mISDN/dsp_cmx.c
index 61cb45c..53fad94 100644
--- a/drivers/isdn/mISDN/dsp_cmx.c
+++ b/drivers/isdn/mISDN/dsp_cmx.c
@@ -82,7 +82,7 @@
* - has multiple clocks.
* - has no usable clock due to jitter or packet loss (VoIP).
* In this case the system's clock is used. The clock resolution depends on
- * the jiffie resolution.
+ * the jiffy resolution.
*
* If a member joins a conference:
*
diff --git a/drivers/net/ethernet/marvell/mvmdio.c b/drivers/net/ethernet/marvell/mvmdio.c
index 9190eff..e1d003f 100644
--- a/drivers/net/ethernet/marvell/mvmdio.c
+++ b/drivers/net/ethernet/marvell/mvmdio.c
@@ -104,7 +104,7 @@ static int orion_mdio_wait_ready(const struct orion_mdio_ops *ops,
return 0;
} else {
/* wait_event_timeout does not guarantee a delay of at
- * least one whole jiffie, so timeout must be no less
+ * least one whole jiffy, so timeout must be no less
* than two.
*/
timeout = max(usecs_to_jiffies(MVMDIO_SMI_TIMEOUT), 2);
diff --git a/fs/xfs/xfs_buf.h b/fs/xfs/xfs_buf.h
index b158064..209a389 100644
--- a/fs/xfs/xfs_buf.h
+++ b/fs/xfs/xfs_buf.h
@@ -210,7 +210,7 @@ struct xfs_buf {
* success the write is considered to be failed permanently and the
* iodone handler will take appropriate action.
*
- * For retry timeouts, we record the jiffie of the first failure. This
+ * For retry timeouts, we record the jiffy of the first failure. This
* means that we can change the retry timeout for buffers already under
* I/O and thus avoid getting stuck in a retry loop with a long timeout.
*
diff --git a/include/linux/jiffies.h b/include/linux/jiffies.h
index d9f1435..1220f0f 100644
--- a/include/linux/jiffies.h
+++ b/include/linux/jiffies.h
@@ -418,7 +418,7 @@ extern unsigned long preset_lpj;
#define NSEC_CONVERSION ((unsigned long)((((u64)1 << NSEC_JIFFIE_SC) +\
TICK_NSEC -1) / (u64)TICK_NSEC))
/*
- * The maximum jiffie value is (MAX_INT >> 1). Here we translate that
+ * The maximum jiffy value is (MAX_INT >> 1). Here we translate that
* into seconds. The 64-bit case will overflow if we are not careful,
* so use the messy SH_DIV macro to do it. Still all constants.
*/
diff --git a/include/linux/timekeeper_internal.h b/include/linux/timekeeper_internal.h
index 84ff284..902c20e 100644
--- a/include/linux/timekeeper_internal.h
+++ b/include/linux/timekeeper_internal.h
@@ -73,7 +73,7 @@ struct tk_read_base {
* @overflow_seen: Overflow warning flag (DEBUG_TIMEKEEPING)
*
* Note: For timespec(64) based interfaces wall_to_monotonic is what
- * we need to add to xtime (or xtime corrected for sub jiffie times)
+ * we need to add to xtime (or xtime corrected for sub jiffy times)
* to get to monotonic time. Monotonic is pegged at zero at system
* boot time, so wall_to_monotonic will be negative, however, we will
* ALWAYS keep the tv_nsec part positive so we can use the usual
diff --git a/kernel/time/alarmtimer.c b/kernel/time/alarmtimer.c
index 76bd4fd..8bf8886 100644
--- a/kernel/time/alarmtimer.c
+++ b/kernel/time/alarmtimer.c
@@ -493,7 +493,7 @@ static u64 __alarm_forward_now(struct alarm *alarm, ktime_t interval, bool throt
* promised in the context of posix_timer_fn() never
* materialized, but someone should really work on it.
*
- * To prevent DOS fake @now to be 1 jiffie out which keeps
+ * To prevent DOS fake @now to be 1 jiffy out which keeps
* the overrun accounting correct but creates an
* inconsistency vs. timer_gettime(2).
*/
diff --git a/kernel/time/clockevents.c b/kernel/time/clockevents.c
index 60a6484..78c7bd6 100644
--- a/kernel/time/clockevents.c
+++ b/kernel/time/clockevents.c
@@ -190,7 +190,7 @@ int clockevents_tick_resume(struct clock_event_device *dev)
#ifdef CONFIG_GENERIC_CLOCKEVENTS_MIN_ADJUST
-/* Limit min_delta to a jiffie */
+/* Limit min_delta to a jiffy */
#define MIN_DELTA_LIMIT (NSEC_PER_SEC / HZ)
/**
diff --git a/kernel/time/hrtimer.c b/kernel/time/hrtimer.c
index a023946..e834b2b 100644
--- a/kernel/time/hrtimer.c
+++ b/kernel/time/hrtimer.c
@@ -1177,7 +1177,7 @@ static inline ktime_t hrtimer_update_lowres(struct hrtimer *timer, ktime_t tim,
/*
* CONFIG_TIME_LOW_RES indicates that the system has no way to return
* granular time values. For relative timers we add hrtimer_resolution
- * (i.e. one jiffie) to prevent short timeouts.
+ * (i.e. one jiffy) to prevent short timeouts.
*/
timer->is_rel = mode & HRTIMER_MODE_REL;
if (timer->is_rel)
diff --git a/kernel/time/posix-timers.c b/kernel/time/posix-timers.c
index 1cc830e..4576aae 100644
--- a/kernel/time/posix-timers.c
+++ b/kernel/time/posix-timers.c
@@ -339,14 +339,14 @@ static enum hrtimer_restart posix_timer_fn(struct hrtimer *timer)
* change to the signal handling code.
*
* For now let timers with an interval less than a
- * jiffie expire every jiffie and recheck for a
+ * jiffy expire every jiffy and recheck for a
* valid signal handler.
*
* This avoids interrupt starvation in case of a
* very small interval, which would expire the
* timer immediately again.
*
- * Moving now ahead of time by one jiffie tricks
+ * Moving now ahead of time by one jiffy tricks
* hrtimer_forward() to expire the timer later,
* while it still maintains the overrun accuracy
* for the price of a slight inconsistency in the
diff --git a/kernel/time/timer.c b/kernel/time/timer.c
index 5e021a2..2b38f30 100644
--- a/kernel/time/timer.c
+++ b/kernel/time/timer.c
@@ -365,7 +365,7 @@ static unsigned long round_jiffies_common(unsigned long j, int cpu,
rem = j % HZ;
/*
- * If the target jiffie is just after a whole second (which can happen
+ * If the target jiffy is just after a whole second (which can happen
* due to delays of the timer irq, long irq off times etc etc) then
* we should round down to the whole second, not up. Use 1/4th second
* as cutoff for this rounding as an extreme upper bound for this.
@@ -1930,7 +1930,7 @@ static void timer_recalc_next_expiry(struct timer_base *base)
* bits are zero, we look at the next level as is. If not we
* need to advance it by one because that's going to be the
* next expiring bucket in that level. base->clk is the next
- * expiring jiffie. So in case of:
+ * expiring jiffy. So in case of:
*
* LVL5 LVL4 LVL3 LVL2 LVL1 LVL0
* 0 0 0 0 0 0
@@ -1995,7 +1995,7 @@ static u64 cmp_next_hrtimer_event(u64 basem, u64 expires)
return basem;
/*
- * Round up to the next jiffie. High resolution timers are
+ * Round up to the next jiffy. High resolution timers are
* off, so the hrtimers are expired in the tick and we need to
* make sure that this tick really expires the timer to avoid
* a ping pong of the nohz stop code.
@@ -2254,7 +2254,7 @@ static inline u64 __get_next_timer_interrupt(unsigned long basej, u64 basem,
base_global, &tevt);
/*
- * If the next event is only one jiffie ahead there is no need to call
+ * If the next event is only one jiffy ahead there is no need to call
* timer migration hierarchy related functions. The value for the next
* global timer in @tevt struct equals then KTIME_MAX. This is also
* true, when the timer base is idle.
@@ -2486,11 +2486,11 @@ static void run_local_timers(void)
* updated. When this update is missed, this isn't a
* problem, as an IPI is executed nevertheless when the CPU
* was idle before. When the CPU wasn't idle but the update
- * is missed, then the timer would expire one jiffie late -
+ * is missed, then the timer would expire one jiffy late -
* bad luck.
*
* Those unlikely corner cases where the worst outcome is only a
- * one jiffie delay or a superfluous raise of the softirq are
+ * one jiffy delay or a superfluous raise of the softirq are
* not that expensive as doing the check always while holding
* the lock.
*
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index a30c03a..a40aa60 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -97,7 +97,7 @@ config BOOT_PRINTK_DELAY
using "boot_delay=N".
It is likely that you would also need to use "lpj=M" to preset
- the "loops per jiffie" value.
+ the "loops per jiffy" value.
See a previous boot log for the "lpj" value to use for your
system, and then set "lpj=M" before setting "boot_delay=N".
NOTE: Using this option may adversely affect SMP systems.
diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h
index 00840d5..04f6398 100644
--- a/net/batman-adv/types.h
+++ b/net/batman-adv/types.h
@@ -287,7 +287,7 @@ struct batadv_frag_table_entry {
/** @lock: lock to protect the list of fragments */
spinlock_t lock;
- /** @timestamp: time (jiffie) of last received fragment */
+ /** @timestamp: time (jiffy) of last received fragment */
unsigned long timestamp;
/** @seqno: sequence number of the fragments in the list */
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [tip: timers/core] timers: Rename next_expiry_recalc() to be unique
2024-09-04 13:04 ` [PATCH 01/15] timers: Rename next_expiry_recalc() to be unique Anna-Maria Behnsen
2024-09-06 13:25 ` Frederic Weisbecker
@ 2024-09-08 18:58 ` tip-bot2 for Anna-Maria Behnsen
1 sibling, 0 replies; 43+ messages in thread
From: tip-bot2 for Anna-Maria Behnsen @ 2024-09-08 18:58 UTC (permalink / raw)
To: linux-tip-commits
Cc: Anna-Maria Behnsen, Thomas Gleixner, Frederic Weisbecker, x86,
linux-kernel
The following commit has been merged into the timers/core branch of tip:
Commit-ID: fe90c5ba88ad43d42acefb21b57df837be86a61a
Gitweb: https://git.kernel.org/tip/fe90c5ba88ad43d42acefb21b57df837be86a61a
Author: Anna-Maria Behnsen <anna-maria@linutronix.de>
AuthorDate: Wed, 04 Sep 2024 15:04:51 +02:00
Committer: Thomas Gleixner <tglx@linutronix.de>
CommitterDate: Sun, 08 Sep 2024 20:47:40 +02:00
timers: Rename next_expiry_recalc() to be unique
next_expiry_recalc is the name of a function as well as the name of a
struct member of struct timer_base. This might lead to confusion.
Rename next_expiry_recalc() to timer_recalc_next_expiry(). No functional
change.
Signed-off-by: Anna-Maria Behnsen <anna-maria@linutronix.de>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Frederic Weisbecker <frederic@kernel.org>
Link: https://lore.kernel.org/all/20240904-devel-anna-maria-b4-timers-flseep-v1-1-e98760256370@linutronix.de
---
kernel/time/timer.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/kernel/time/timer.c b/kernel/time/timer.c
index 311ea45..5e021a2 100644
--- a/kernel/time/timer.c
+++ b/kernel/time/timer.c
@@ -1900,7 +1900,7 @@ static int next_pending_bucket(struct timer_base *base, unsigned offset,
*
* Store next expiry time in base->next_expiry.
*/
-static void next_expiry_recalc(struct timer_base *base)
+static void timer_recalc_next_expiry(struct timer_base *base)
{
unsigned long clk, next, adj;
unsigned lvl, offset = 0;
@@ -2009,7 +2009,7 @@ static unsigned long next_timer_interrupt(struct timer_base *base,
unsigned long basej)
{
if (base->next_expiry_recalc)
- next_expiry_recalc(base);
+ timer_recalc_next_expiry(base);
/*
* Move next_expiry for the empty base into the future to prevent an
@@ -2413,7 +2413,7 @@ static inline void __run_timers(struct timer_base *base)
* jiffies to avoid endless requeuing to current jiffies.
*/
base->clk++;
- next_expiry_recalc(base);
+ timer_recalc_next_expiry(base);
while (levels--)
expire_timers(base, heads + levels);
^ permalink raw reply related [flat|nested] 43+ messages in thread
* Re: [PATCH 04/15] timers: Move *sleep*() and timeout functions into a separate file
2024-09-06 13:42 ` Frederic Weisbecker
@ 2024-09-09 8:10 ` Anna-Maria Behnsen
2024-09-09 12:11 ` Thomas Gleixner
0 siblings, 1 reply; 43+ messages in thread
From: Anna-Maria Behnsen @ 2024-09-09 8:10 UTC (permalink / raw)
To: Frederic Weisbecker
Cc: Thomas Gleixner, Jonathan Corbet, linux-kernel, Len Brown,
Rafael J. Wysocki
Frederic Weisbecker <frederic@kernel.org> writes:
> Le Wed, Sep 04, 2024 at 03:04:54PM +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(). While at it also add not listed
>> include/linux/delay.h to the MAINTAINTERS file.
>
> I don't mind sometimes having several logical changes within a same
> patch if that makes sense but the delay is MAINTAINERS is pretty off-topic
> and should move to its own patch.
Ack. But, I was too slow to provide a v2. It's already applied in
tip. Should we change tip, or is ok for you?
Thanks,
Anna-Maria
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [PATCH 04/15] timers: Move *sleep*() and timeout functions into a separate file
2024-09-09 8:10 ` Anna-Maria Behnsen
@ 2024-09-09 12:11 ` Thomas Gleixner
0 siblings, 0 replies; 43+ messages in thread
From: Thomas Gleixner @ 2024-09-09 12:11 UTC (permalink / raw)
To: Anna-Maria Behnsen, Frederic Weisbecker
Cc: Jonathan Corbet, linux-kernel, Len Brown, Rafael J. Wysocki
On Mon, Sep 09 2024 at 10:10, Anna-Maria Behnsen wrote:
> Frederic Weisbecker <frederic@kernel.org> writes:
>> I don't mind sometimes having several logical changes within a same
>> patch if that makes sense but the delay is MAINTAINERS is pretty off-topic
>> and should move to its own patch.
>
> Ack. But, I was too slow to provide a v2. It's already applied in
> tip. Should we change tip, or is ok for you?
Zapped it already
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: (subset) [PATCH 00/15] timers: Cleanup delay/sleep related mess
2024-09-04 13:04 [PATCH 00/15] timers: Cleanup delay/sleep related mess Anna-Maria Behnsen
` (15 preceding siblings ...)
2024-09-04 14:44 ` [PATCH 00/15] timers: Cleanup delay/sleep related mess Rafael J. Wysocki
@ 2024-10-17 14:19 ` Mark Brown
16 siblings, 0 replies; 43+ messages in thread
From: Mark Brown @ 2024-10-17 14:19 UTC (permalink / raw)
To: Frederic Weisbecker, Thomas Gleixner, Jonathan Corbet,
Anna-Maria Behnsen
Cc: linux-kernel, Len Brown, Rafael J. Wysocki, Peter Zijlstra,
SeongJae Park, Andrew Morton, damon, linux-mm, Arnd Bergmann,
linux-arch, Heiner Kallweit, David S. Miller, Andy Whitcroft,
Joe Perches, Dwaipayan Ray, Liam Girdwood, Andrew Lunn,
Jaroslav Kysela, Takashi Iwai, netdev, linux-sound,
Michael Ellerman, Nathan Lynch, linuxppc-dev,
Mauro Carvalho Chehab, linux-media
On Wed, 04 Sep 2024 15:04:50 +0200, Anna-Maria Behnsen wrote:
> 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:
>
> [...]
Applied to
https://git.kernel.org/pub/scm/linux/kernel/git/broonie/regulator.git for-next
Thanks!
[11/15] regulator: core: Use fsleep() to get best sleep mechanism
commit: f20669fbcf99d0e15e94fb50929bb1c41618e197
All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying
to this mail.
Thanks,
Mark
^ permalink raw reply [flat|nested] 43+ messages in thread
end of thread, other threads:[~2024-10-17 14:20 UTC | newest]
Thread overview: 43+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-09-04 13:04 [PATCH 00/15] timers: Cleanup delay/sleep related mess Anna-Maria Behnsen
2024-09-04 13:04 ` [PATCH 01/15] timers: Rename next_expiry_recalc() to be unique Anna-Maria Behnsen
2024-09-06 13:25 ` Frederic Weisbecker
2024-09-08 18:58 ` [tip: timers/core] " tip-bot2 for Anna-Maria Behnsen
2024-09-04 13:04 ` [PATCH 02/15] cpu: Use already existing usleep_range() Anna-Maria Behnsen
2024-09-06 13:27 ` Frederic Weisbecker
2024-09-08 18:58 ` [tip: timers/core] " tip-bot2 for Anna-Maria Behnsen
2024-09-04 13:04 ` [PATCH 03/15] Comments: Fix wrong singular form of jiffies Anna-Maria Behnsen
2024-09-05 8:42 ` Geert Uytterhoeven
2024-09-08 18:58 ` [tip: timers/core] treewide: Fix wrong singular form of jiffies in comments tip-bot2 for Anna-Maria Behnsen
2024-09-04 13:04 ` [PATCH 04/15] timers: Move *sleep*() and timeout functions into a separate file Anna-Maria Behnsen
2024-09-06 13:42 ` Frederic Weisbecker
2024-09-09 8:10 ` Anna-Maria Behnsen
2024-09-09 12:11 ` Thomas Gleixner
2024-09-08 18:58 ` [tip: timers/core] " tip-bot2 for Anna-Maria Behnsen
2024-09-04 13:04 ` [PATCH 05/15] timers: Rename sleep_idle_range() to sleep_range_idle() Anna-Maria Behnsen
2024-09-06 13:45 ` Frederic Weisbecker
2024-09-06 16:25 ` SeongJae Park
2024-09-08 18:58 ` [tip: timers/core] " tip-bot2 for Anna-Maria Behnsen
2024-09-04 13:04 ` [PATCH 06/15] timers: Update function descriptions of sleep/delay related functions Anna-Maria Behnsen
2024-09-04 14:30 ` Arnd Bergmann
2024-09-05 6:59 ` Thomas Gleixner
2024-09-05 16:07 ` Thomas Gleixner
2024-09-05 19:49 ` Anna-Maria Behnsen
2024-09-04 13:04 ` [PATCH 07/15] timers: Adjust flseep() to reflect reality Anna-Maria Behnsen
2024-09-04 13:04 ` [PATCH 08/15] mm/damon/core: Use generic upper bound recommondation for usleep_range() Anna-Maria Behnsen
2024-09-06 16:31 ` SeongJae Park
2024-09-04 13:04 ` [PATCH 09/15] timers: Add a warning to usleep_range_state() for wrong order of arguments Anna-Maria Behnsen
2024-09-04 13:05 ` [PATCH 10/15] checkpatch: Remove broken sleep/delay related checks Anna-Maria Behnsen
2024-09-05 1:28 ` Joe Perches
2024-09-05 8:04 ` Anna-Maria Behnsen
2024-09-04 13:05 ` [PATCH 11/15] regulator: core: Use fsleep() to get best sleep mechanism Anna-Maria Behnsen
2024-09-04 13:28 ` Mark Brown
2024-09-05 8:24 ` Anna-Maria Behnsen
2024-09-04 13:05 ` [PATCH 12/15] iopoll/regmap/phy/snd: Fix comment referencing outdated timer documentation Anna-Maria Behnsen
2024-09-04 14:03 ` Andrew Lunn
2024-09-05 8:15 ` Anna-Maria Behnsen
2024-09-04 13:05 ` [PATCH 13/15] powerpc/rtas: Use fsleep() to minimize additional sleep duration Anna-Maria Behnsen
2024-09-05 12:24 ` Michael Ellerman
2024-09-04 13:05 ` [PATCH 14/15] media: anysee: Fix link to outdated sleep function documentation Anna-Maria Behnsen
2024-09-04 13:05 ` [PATCH 15/15] timers/Documentation: Cleanup delay/sleep documentation Anna-Maria Behnsen
2024-09-04 14:44 ` [PATCH 00/15] timers: Cleanup delay/sleep related mess Rafael J. Wysocki
2024-10-17 14:19 ` (subset) " Mark Brown
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox