[PATCH v3 08/14] lib: time: hook uthread_schedule() into udelay()

Jerome Forissier jerome.forissier at linaro.org
Wed Mar 5 18:32:42 CET 2025



On 3/4/25 16:24, Jerome Forissier wrote:
> Introduce a uthread scheduling loop into udelay() when CONFIG_UTHREAD
> is enabled. This means that any uthread calling into udelay() may yield
> to uthread and be scheduled again later. The granunlarity of the
> scheduling loop is defined by CONFIG_UTHREAD_GRANULARITY. The lower the
> value, the tighter the loop. The default value of 10 ms was chosen by
> testing the concurrent initialization of the two USB busses of an
> i.MX93 board (introduced in a later commit). The total time is as
> follows:
> 
>   UTHREAD_GRANULARITY (us) |  "usb start" time (s)
>   -------------------------+----------------------
>                          0 |                2.426
>                       1000 |                2.448
>                      10000 |                2.512
>                     100000 |                2.992
>                     300000 |                3.407
> 
> For reference, if uthread_schedule() is not called at all in udelay()
> except once via schedule(), the "usb start" time is 4.377s and without
> UTHREAD it is 4.591 s.

Replying to myself... but I have done some more tests on the i.MX93 and
this UTHREAD_GRANULARITY delay is not good. The console drops characters
as soon as it is greater than 5 microseconds. That's after running
"spawn sleep 10" -- the console becomes buggy during 10 seconds then back
to normal. With UTHREAD_GRANULARITY=0 all is fine.

Therefore I consider dropping UTHREAD_GRANULARITY in v4 and using a tight
loop like in v2 [1].

[1] https://lists.denx.de/pipermail/u-boot/2025-February/581634.html

-- 
Jerome
> 
> Signed-off-by: Jerome Forissier <jerome.forissier at linaro.org>
> ---
>  lib/Kconfig |  8 ++++++++
>  lib/time.c  | 21 ++++++++++++++++++++-
>  2 files changed, 28 insertions(+), 1 deletion(-)
> 
> diff --git a/lib/Kconfig b/lib/Kconfig
> index 8321f20e154..40964f5bb4a 100644
> --- a/lib/Kconfig
> +++ b/lib/Kconfig
> @@ -1276,6 +1276,14 @@ config UTHREAD_STACK_SIZE
>  	  When the stack_sz argument to uthread_create() is zero then this
>  	  value is used.
>  
> +config UTHREAD_GRANULARITY
> +	int "Scheduling period for uthreads inside udelay()"
> +	depends on UTHREAD
> +	default 10000
> +	help
> +	  The delay in microseconds between calls to uthread_schedule() inside
> +	  the udelay() function.
> +
>  endmenu
>  
>  source "lib/fwu_updates/Kconfig"
> diff --git a/lib/time.c b/lib/time.c
> index d88edafb196..7c34424bf64 100644
> --- a/lib/time.c
> +++ b/lib/time.c
> @@ -17,6 +17,7 @@
>  #include <asm/global_data.h>
>  #include <asm/io.h>
>  #include <linux/delay.h>
> +#include <uthread.h>
>  
>  #ifndef CFG_WD_PERIOD
>  # define CFG_WD_PERIOD	(10 * 1000 * 1000)	/* 10 seconds default */
> @@ -190,6 +191,23 @@ void __weak __udelay(unsigned long usec)
>  
>  /* ------------------------------------------------------------------------- */
>  
> +static void do_delay(unsigned long kv)
> +{
> +#if CONFIG_IS_ENABLED(UTHREAD)
> +	ulong t0 = timer_get_us();
> +	ulong gr = CONFIG_UTHREAD_GRANULARITY;
> +
> +	if (kv < CONFIG_UTHREAD_GRANULARITY)
> +		gr = kv;
> +	while (timer_get_us() - t0 < kv) {
> +		uthread_schedule();
> +		__udelay(gr);
> +	}
> +#else
> +	__udelay(kv);
> +#endif
> +}
> +
>  void udelay(unsigned long usec)
>  {
>  	ulong kv;
> @@ -197,7 +215,8 @@ void udelay(unsigned long usec)
>  	do {
>  		schedule();
>  		kv = usec > CFG_WD_PERIOD ? CFG_WD_PERIOD : usec;
> -		__udelay(kv);
> +		do_delay(kv);
>  		usec -= kv;
>  	} while(usec);
> +
>  }


More information about the U-Boot mailing list