Message ID | 20250304152510.2832340-9-jerome.forissier@linaro.org |
---|---|
State | New |
Headers | show |
Series | Uthreads | expand |
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
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); + }
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. Signed-off-by: Jerome Forissier <jerome.forissier@linaro.org> --- lib/Kconfig | 8 ++++++++ lib/time.c | 21 ++++++++++++++++++++- 2 files changed, 28 insertions(+), 1 deletion(-)