Skip to content

Commit

Permalink
[fiber] Add cooperative, stackful fibers
Browse files Browse the repository at this point in the history
  • Loading branch information
salkinium committed Oct 29, 2021
1 parent def26a4 commit b22c89a
Show file tree
Hide file tree
Showing 16 changed files with 1,128 additions and 1 deletion.
4 changes: 4 additions & 0 deletions repo.lb
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,10 @@ def init(repo):
description=descr_target,
enumeration=devices))

# Invisible option guarding the Fiber API until it is ready
repo.add_option(BooleanOption(name="__fibers", default=False,
description="Enable unstable fiber API."))

def prepare(repo, options):
repo.add_modules_recursive("ext", modulefile="*.lb")
repo.add_modules_recursive("src", modulefile="*.lb")
Expand Down
4 changes: 4 additions & 0 deletions src/modm/architecture/utils.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,9 @@
/// Marks a declaration as deprecated and displays a message.
#define modm_deprecated(msg)

/// Tells the compiler to not generate prologue/epilogue code for this function.
#define modm_naked

/// Places a function in the fastest executable memory:
/// instruction cache, core coupled memory or SRAM as fallback.
#define modm_fastcode
Expand Down Expand Up @@ -134,6 +137,7 @@
#define modm_fallthrough __attribute__((fallthrough))
#define modm_noreturn __attribute__((noreturn))
#define modm_warn_unused_result __attribute__((warn_unused_result))
#define modm_naked __attribute__((naked))

#ifdef MODM_COMPILER_MINGW
// FIXME: Windows Object Format PE does not support weak symbols
Expand Down
13 changes: 13 additions & 0 deletions src/modm/processing/fiber.hpp
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"
48 changes: 48 additions & 0 deletions src/modm/processing/fiber/context.h
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
171 changes: 171 additions & 0 deletions src/modm/processing/fiber/context_arm_m.cpp.in
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()
);
}
Loading

0 comments on commit b22c89a

Please sign in to comment.