microbit: Allow to run the idle task within the current fiber's stack.

If there is only 1 main fiber (plus the idle fiber) then enabling this
new feature for the main fiber (using fiber_allow_run_idle_within())
will mean that no heap is needed to swap the stack out.
This commit is contained in:
Damien George 2015-09-19 11:45:45 +01:00
parent ec30695d7d
commit 9ccdd25e9f
2 changed files with 39 additions and 0 deletions

View file

@ -24,6 +24,7 @@
#define MICROBIT_FIBER_FLAG_FOB 0x01
#define MICROBIT_FIBER_FLAG_PARENT 0x02
#define MICROBIT_FIBER_FLAG_CHILD 0x04
#define MICROBIT_FIBER_FLAG_RUN_IDLE_WITHIN 0x08
/**
* Thread Context for an ARM Cortex M0 core.
@ -118,6 +119,12 @@ Fiber *create_fiber(void (*entry_fn)(void), void (*completion_fn)(void) = releas
*/
Fiber *create_fiber(void (*entry_fn)(void *), void *param, void (*completion_fn)(void *) = release_fiber);
/**
* Allow the idle thread to run within the current thread's stack frame.
* This is useful to prevent paging of the thread's stack to the heap.
*/
void fiber_allow_run_idle_within();
/**

View file

@ -226,6 +226,15 @@ void scheduler_event(MicroBitEvent evt)
}
}
/**
* Allow the idle thread to run within the current thread's stack frame.
* This is useful to prevent paging of the thread's stack to the heap.
*/
void fiber_allow_run_idle_within()
{
currentFiber->flags |= MICROBIT_FIBER_FLAG_RUN_IDLE_WITHIN;
}
/**
* Blocks the calling thread for the given period of time.
@ -622,6 +631,29 @@ void schedule()
// Otherwise, just pick the head of the run queue.
currentFiber = runQueue;
if (currentFiber == idle && oldFiber->flags & MICROBIT_FIBER_FLAG_RUN_IDLE_WITHIN)
{
// Run the idle task right here using the old fiber's stack.
// Keep idling while the runqueue is empty, or there is data to process.
do
{
uBit.systemTasks();
if(scheduler_runqueue_empty())
{
if (uBit.ble)
uBit.ble->waitForEvent();
else
__WFI();
}
}
while (runQueue == NULL || fiber_flags & MICROBIT_FLAG_DATA_READY);
// Switch to a non-idle fiber.
// If this fiber is the same as the old one then there'll be no switching at all.
currentFiber = runQueue;
}
// Swap to the context of the chosen fiber, and we're done.
// Don't bother with the overhead of switching if there's only one fiber on the runqueue!
if (currentFiber != oldFiber)