Introduce a uthread scheduling call into udelay() when CONFIG_UTHREAD
is enabled. This means that any uthread calling into udelay() may yield
to uthread and be scheduled again later.

TBD: check if udelay_yield is really necessary.

Signed-off-by: Jerome Forissier <jerome.foriss...@linaro.org>
---
 lib/time.c | 17 ++++++++++++++++-
 1 file changed, 16 insertions(+), 1 deletion(-)

diff --git a/lib/time.c b/lib/time.c
index d88edafb196..55e41c92210 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,10 @@ void __weak __udelay(unsigned long usec)
 
 /* ------------------------------------------------------------------------- */
 
+#if CONFIG_IS_ENABLED(UTHREAD)
+int udelay_yield;
+#endif
+
 void udelay(unsigned long usec)
 {
        ulong kv;
@@ -197,7 +202,17 @@ void udelay(unsigned long usec)
        do {
                schedule();
                kv = usec > CFG_WD_PERIOD ? CFG_WD_PERIOD : usec;
-               __udelay(kv);
+#if CONFIG_IS_ENABLED(UTHREAD)
+               if (udelay_yield == 0xCAFEDECA) {
+                       ulong t0 = timer_get_us();
+                       while (timer_get_us() < t0 + kv)
+                               uthread_schedule();
+               } else {
+#endif
+                       __udelay(kv);
+#if CONFIG_IS_ENABLED(UTHREAD)
+               }
+#endif
                usec -= kv;
        } while(usec);
 }
-- 
2.43.0

Reply via email to