-
Notifications
You must be signed in to change notification settings - Fork 143
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[fiber] Add cooperative, stackful fibers
- Loading branch information
Showing
16 changed files
with
1,128 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
/* | ||
* Copyright (c) 2020, Erik Henriksson | ||
* | ||
* This file is part of the modm project. | ||
* | ||
* This Source Code Form is subject to the terms of the Mozilla Public | ||
* License, v. 2.0. If a copy of the MPL was not distributed with this | ||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. | ||
*/ | ||
// ---------------------------------------------------------------------------- | ||
|
||
#include "fiber/fiber.hpp" | ||
#include "fiber/scheduler.hpp" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
/* | ||
* Copyright (c) 2020, Erik Henriksson | ||
* Copyright (c) 2021, Niklas Hauser | ||
* | ||
* This file is part of the modm project. | ||
* | ||
* This Source Code Form is subject to the terms of the Mozilla Public | ||
* License, v. 2.0. If a copy of the MPL was not distributed with this | ||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. | ||
*/ | ||
// ---------------------------------------------------------------------------- | ||
|
||
#pragma once | ||
|
||
#include <stdint.h> | ||
#include <stddef.h> | ||
#include <modm/architecture/utils.hpp> | ||
|
||
#ifdef __cplusplus | ||
extern "C" | ||
{ | ||
#endif | ||
|
||
struct modm_context_t | ||
{ | ||
uintptr_t sp; | ||
size_t stack_size; | ||
}; | ||
|
||
/// Prepares the stack to jump into function with arg and call end on return | ||
modm_context_t | ||
modm_context_init(uintptr_t stack, uintptr_t arg, uintptr_t fn, uintptr_t end); | ||
|
||
/// Switches control from the main context to the user context. | ||
void | ||
modm_context_start(uintptr_t sp); | ||
|
||
/// Jumps from the "from" user context to the "to" user context. | ||
void | ||
modm_context_jump(uintptr_t* from_sp, uintptr_t to_sp); | ||
|
||
/// Switches control back to the main context from the user context. | ||
void __attribute__((noreturn)) | ||
modm_context_end(); | ||
|
||
#ifdef __cplusplus | ||
} | ||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,171 @@ | ||
/* | ||
* Copyright (c) 2020, Erik Henriksson | ||
* Copyright (c) 2021, Niklas Hauser | ||
* | ||
* This file is part of the modm project. | ||
* | ||
* This Source Code Form is subject to the terms of the Mozilla Public | ||
* License, v. 2.0. If a copy of the MPL was not distributed with this | ||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. | ||
*/ | ||
// ---------------------------------------------------------------------------- | ||
|
||
#include "context.h" | ||
|
||
/* Stack layout (growing downwards): | ||
* Registers r4-r11 must be preserved across subroutine calls. | ||
* | ||
* LR | ||
%% if not cm0 | ||
* r11 | ||
* r10 | ||
* r9 | ||
* r8 | ||
%% endif | ||
* r7 | ||
* r6 | ||
* r5 | ||
* r4 | ||
%% if cm0 | ||
* r11 | ||
* r10 | ||
* r9 | ||
* r8 | ||
%% endif | ||
%% if with_fpu | ||
* s31 | ||
* s30 | ||
* s29 | ||
* s28 | ||
* s27 | ||
* s26 | ||
* s25 | ||
* s24 | ||
* s23 | ||
* s22 | ||
* s21 | ||
* s20 | ||
* s19 | ||
* s18 | ||
* s17 | ||
* s16 | ||
* | ||
* From the PCSAA: | ||
* Registers s16-s31 (d8-d15, q4-q7) must be preserved across subroutine calls; | ||
* registers s0-s15 (d0-d7, q0- q3) do not need to be preserved (and can be used | ||
* for passing arguments or returning results in standard procedure-call | ||
* variants). Registers d16-d31 (q8-q15), if present, do not need to be | ||
* preserved. | ||
%% endif | ||
*/ | ||
|
||
static void modm_naked | ||
modm_context_entry() | ||
{ | ||
asm volatile | ||
( | ||
"pop {r0} \n\t" // Loads return address | ||
"mov lr, r0 \n\t" // Set LR | ||
"pop {r0, pc} \n\t" // Load argument and jump | ||
); | ||
} | ||
|
||
modm_context_t | ||
modm_context_init(uintptr_t stack, uintptr_t arg, uintptr_t fn, uintptr_t end) | ||
{ | ||
uintptr_t* sp = (uintptr_t*)arg; | ||
*--sp = fn; // actual fiber function | ||
*--sp = arg; // r0 argument | ||
*--sp = end; // called after fn returns | ||
|
||
*--sp = (uintptr_t) modm_context_entry; | ||
sp -= 8{% if with_fpu %}+16{% endif %}; // r4-r11{% if with_fpu %}, s16-s31{% endif %} | ||
return {(uintptr_t) sp, arg - stack}; | ||
} | ||
|
||
#define MODM_PUSH_CONTEXT() \ | ||
%% if cm0 | ||
"push {r4-r7, lr} \n\t" \ | ||
"mov r4, r8 \n\t" \ | ||
"mov r5, r9 \n\t" \ | ||
"mov r6, r10 \n\t" \ | ||
"mov r7, r11 \n\t" \ | ||
"push {r4-r7} \n\t" | ||
%% else | ||
"push {r4-r11, lr} \n\t"{% if with_fpu %} \ | ||
"vpush {d8-d15} \n\t"{% endif %} | ||
%% endif | ||
%# | ||
#define MODM_POP_CONTEXT() \ | ||
%% if cm0 | ||
"pop {r4-r7} \n\t" \ | ||
"mov r8, r4 \n\t" \ | ||
"mov r9, r5 \n\t" \ | ||
"mov r10, r6 \n\t" \ | ||
"mov r11, r7 \n\t" \ | ||
"pop {r4-r7, pc} \n\t" | ||
%% else | ||
%% if with_fpu | ||
"vpop {d8-d15} \n\t" \ | ||
%% endif | ||
"pop {r4-r11, pc} \n\t" | ||
%% endif | ||
%# | ||
void modm_naked | ||
modm_context_start(uintptr_t) | ||
{ | ||
asm volatile | ||
( | ||
MODM_PUSH_CONTEXT() | ||
|
||
"mrs r2, control \n\t" | ||
%% if cm0 | ||
"mov r1, #2 \n\t" | ||
"orr r2, r2, r1 \n\t" // Set SPSEL | ||
%% else | ||
"orr r2, r2, #2 \n\t" // Set SPSEL | ||
%% endif | ||
"msr control, r2 \n\t" | ||
|
||
"mov sp, r0 \n\t" // Set PSP to fiber stack (to.sp) | ||
|
||
MODM_POP_CONTEXT() | ||
); | ||
} | ||
|
||
void modm_naked | ||
modm_context_jump(uintptr_t*, uintptr_t) | ||
{ | ||
asm volatile | ||
( | ||
MODM_PUSH_CONTEXT() | ||
%# | ||
%% if cm0 | ||
"mov r2, sp \n\t" | ||
"str r2, [r0] \n\t" // Store the SP in "from" | ||
%% else | ||
"str sp, [r0] \n\t" // Store the SP in "from" | ||
%% endif | ||
"mov sp, r1 \n\t" // Restore SP from "to" | ||
|
||
MODM_POP_CONTEXT() | ||
); | ||
} | ||
|
||
void modm_naked | ||
modm_context_end() | ||
{ | ||
asm volatile | ||
( | ||
"mrs r0, control \n\t" | ||
%% if cm0 | ||
"mov r1, #2 \n\t" | ||
"bic r0, r0, r1 \n\t" // Unset SPSEL | ||
%% else | ||
"bic r0, r0, #2 \n\t" // Unset SPSEL | ||
%% endif | ||
"msr control, r0 \n\t" | ||
|
||
MODM_POP_CONTEXT() | ||
); | ||
} |
Oops, something went wrong.