[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Minios-devel] [UNIKRAFT PATCH v4 6/7] plat/common: Implement generic_timer_cpu_block_until



This function will be used when system enter sleep and need wakeup
in a specific time. For ns_to_ticks precision, we limited the max
sleep time to 3600 seconds.

Signed-off-by: Wei Chen <wei.chen@xxxxxxx>
Signed-off-by: Jianyong Wu <jianyong.wu@xxxxxxx>
Signed-off-by: Jia He <justin.he@xxxxxxx>
---
 plat/common/arm/time.c | 45 ++++++++++++++++++++++++++++++++++++------
 1 file changed, 39 insertions(+), 6 deletions(-)

diff --git a/plat/common/arm/time.c b/plat/common/arm/time.c
index aa9bd42..8f278cb 100644
--- a/plat/common/arm/time.c
+++ b/plat/common/arm/time.c
@@ -256,6 +256,43 @@ static uint64_t generic_timer_epochoffset(void)
        return 0;
 }
 
+/*
+ * Returns early if any interrupts are serviced, or if the requested delay is
+ * too short. Must be called with interrupts disabled, will enable interrupts
+ * "atomically" during idle loop.
+ *
+ * This function must be called only from the scheduler. It will screw
+ * your system if you do otherwise. And, there is no reason you
+ * actually want to use it anywhere else. THIS IS NOT A YIELD or any
+ * kind of mutex_lock. It will simply halt the cpu, not allowing any
+ * other thread to execute.
+ */
+static void generic_timer_cpu_block_until(uint64_t until_ns)
+{
+       uint64_t now_ns, until_ticks;
+
+       UK_ASSERT(ukplat_lcpu_irqs_disabled());
+
+       /* Record current ns and until_ticks for timer */
+       now_ns = ukplat_monotonic_clock();
+       until_ticks = generic_timer_get_ticks()
+                               + ns_to_ticks(until_ns - now_ns);
+
+       if (now_ns < until_ns) {
+               generic_timer_update_compare(until_ticks);
+               generic_timer_enable();
+               generic_timer_unmask_irq();
+               __asm__ __volatile__("wfi");
+               generic_timer_mask_irq();
+
+               /* Give the IRQ handler a chance to handle whatever woke
+                * us up
+                */
+               ukplat_lcpu_enable_irq();
+               ukplat_lcpu_disable_irq();
+       }
+}
+
 static int generic_timer_init(int fdt_timer)
 {
        /* Get counter frequency from DTB or register */
@@ -290,7 +327,7 @@ static int generic_timer_irq_handler(void *arg __unused)
 {
        /*
         * We just mask the IRQ here, the scheduler will call
-        * generic_timer_cpu_block, and then unmask the IRQ.
+        * generic_timer_cpu_block_until, and then unmask the IRQ.
         */
        generic_timer_mask_irq();
 
@@ -302,12 +339,8 @@ unsigned long sched_have_pending_events;
 
 void time_block_until(__snsec until)
 {
-       /*
-        * TODO:
-        * As we haven't support interrupt on Arm, so we just
-        * use busy polling for now.
-        */
        while ((__snsec) ukplat_monotonic_clock() < until) {
+               generic_timer_cpu_block_until(until);
                if (__uk_test_and_clear_bit(0, &sched_have_pending_events))
                        break;
        }
-- 
2.17.1


_______________________________________________
Minios-devel mailing list
Minios-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/minios-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.