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:
parent
ec30695d7d
commit
9ccdd25e9f
2 changed files with 39 additions and 0 deletions
|
@ -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();
|
||||
|
||||
|
||||
|
||||
/**
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in a new issue