Skip to content

Commit 250da09

Browse files
andryblacksalkinium
authored andcommitted
[fiber] Adapt for multicore processing
1 parent 8297cf3 commit 250da09

File tree

4 files changed

+201
-127
lines changed

4 files changed

+201
-127
lines changed

src/modm/processing/fiber/fiber.hpp renamed to src/modm/processing/fiber/fiber.hpp.in

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,22 @@
99
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
1010
*/
1111
// ----------------------------------------------------------------------------
12+
%% if multicore
13+
%% set CoreDecl = ", size_t core=0"
14+
%% set CoreArg = ", size_t core"
15+
%% set CoreForward = ", core"
16+
%% else
17+
%% set CoreDecl = ""
18+
%% set CoreArg = ""
19+
%% set CoreForward = ""
20+
%% endif
1221

1322
#pragma once
1423
#include "context.h"
1524
#include "stack.hpp"
1625
#include <memory>
17-
1826
namespace modm
1927
{
20-
2128
namespace fiber
2229
{
2330

@@ -50,11 +57,11 @@ class Fiber
5057

5158
public:
5259
template<size_t Size>
53-
Fiber(fiber::Stack<Size>& stack, void(*fn)());
60+
Fiber(fiber::Stack<Size>& stack, void(*fn)(){{CoreDecl}});
5461

5562
template<size_t Size, class T>
5663
requires requires { &std::decay_t<T>::operator(); }
57-
Fiber(fiber::Stack<Size>& stack, T&& closure);
64+
Fiber(fiber::Stack<Size>& stack, T&& closure{{CoreDecl}});
5865

5966
protected:
6067
inline void
@@ -75,21 +82,20 @@ class Fiber
7582

7683
namespace modm
7784
{
78-
7985
template<size_t Size>
80-
Fiber::Fiber(fiber::Stack<Size>& stack, void(*fn)())
86+
Fiber::Fiber(fiber::Stack<Size>& stack, void(*fn)(){{CoreArg}})
8187
{
8288
ctx = modm_context_init((uintptr_t) stack.memory,
8389
(uintptr_t) stack.memory + stack.size,
8490
(uintptr_t) fn,
8591
(uintptr_t) fiber::Scheduler::deregisterFiber);
8692
// register this fiber to be scheduled
87-
fiber::Scheduler::registerFiber(this);
93+
fiber::Scheduler::registerFiber(this{{CoreForward}});
8894
}
8995

9096
template<size_t Size, class T>
9197
requires requires { &std::decay_t<T>::operator(); }
92-
Fiber::Fiber(fiber::Stack<Size>& stack, T&& closure)
98+
Fiber::Fiber(fiber::Stack<Size>& stack, T&& closure{{CoreArg}})
9399
{
94100
// Find a suitable aligned area at the top of stack to allocate the closure
95101
uintptr_t ptr = uintptr_t(stack.memory) + stack.size;
@@ -106,14 +112,13 @@ Fiber::Fiber(fiber::Stack<Size>& stack, T&& closure)
106112
ctx = modm_context_init((uintptr_t) stack.memory, ptr, function,
107113
(uintptr_t) fiber::Scheduler::deregisterFiber);
108114
// register this fiber to be scheduled
109-
fiber::Scheduler::registerFiber(this);
115+
fiber::Scheduler::registerFiber(this{{CoreForward}});
110116
}
111117

112118
void
113119
Fiber::jump(Fiber& other)
114120
{
115-
fiber::Scheduler::current = &other;
116-
modm_context_jump(&(ctx.sp), other.ctx.sp);
121+
fiber::Scheduler::jump(*this,other);
117122
}
118123

119124
} // namespace modm

src/modm/processing/fiber/module.lb

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,6 @@ def build(env):
2929
env.outbasepath = "modm/src/modm/processing/fiber"
3030
env.copy("../fiber.hpp")
3131

32-
env.copy("fiber.hpp")
33-
env.copy("scheduler.hpp")
34-
3532
env.copy("context.h")
3633

3734
core = env[":target"].get_driver("core")["type"]
@@ -41,7 +38,13 @@ def build(env):
4138
"with_fpu": env.get(":platform:cortex-m:float-abi", "soft") != "soft",
4239
"with_windows": env[":target"].identifier.family == "windows",
4340
"target": env[":target"].identifier,
41+
"multicore": env.has_module(":platform:multicore"),
4442
}
43+
if env.has_module(":platform:multicore"):
44+
cores = int(env[":target"].identifier.cores)
45+
env.substitutions["num_cores"] = cores
46+
env.template("fiber.hpp.in")
47+
env.template("scheduler.hpp.in")
4548

4649
env.template("stack.hpp.in")
4750

src/modm/processing/fiber/scheduler.hpp

Lines changed: 0 additions & 113 deletions
This file was deleted.
Lines changed: 179 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
1+
/*
2+
* Copyright (c) 2020, Erik Henriksson
3+
* Copyright (c) 2022, Andrey Kunitsyn
4+
*
5+
* This file is part of the modm project.
6+
*
7+
* This Source Code Form is subject to the terms of the Mozilla Public
8+
* License, v. 2.0. If a copy of the MPL was not distributed with this
9+
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
10+
*/
11+
// ----------------------------------------------------------------------------
12+
13+
#pragma once
14+
15+
#include "fiber.hpp"
16+
%% if multicore
17+
#include <modm/platform/core/multicore.hpp>
18+
%% endif
19+
20+
namespace modm::fiber
21+
{
22+
23+
void yield();
24+
25+
class Scheduler
26+
{
27+
friend class ::modm::Fiber;
28+
friend class Waitable;
29+
friend void yield();
30+
Scheduler(const Scheduler&) = delete;
31+
Scheduler() = delete;
32+
33+
protected:
34+
struct Data
35+
{
36+
/// Last fiber in the ready queue.
37+
Fiber* last = nullptr;
38+
/// Current running fiber
39+
Fiber* current = nullptr;
40+
41+
inline void registerFiber(Fiber* fiber)
42+
{
43+
if (last == nullptr)
44+
{
45+
fiber->next = fiber;
46+
last = fiber;
47+
return;
48+
}
49+
runLast(fiber);
50+
}
51+
inline void runLast(Fiber* fiber)
52+
{
53+
fiber->next = last->next;
54+
last->next = fiber;
55+
last = fiber;
56+
}
57+
inline Fiber* removeCurrent()
58+
{
59+
if (current == last) last = nullptr;
60+
else last->next = current->next;
61+
current->next = nullptr;
62+
return current;
63+
}
64+
inline bool empty() const
65+
{
66+
return last == nullptr;
67+
}
68+
inline void jump(Fiber& other)
69+
{
70+
auto from = current;
71+
current = &other;
72+
modm_context_jump(&(from->ctx.sp), other.ctx.sp);
73+
}
74+
};
75+
%% if multicore
76+
%% for i in range(num_cores)
77+
modm_core{{i}}_bss static inline Data data{{i}} = {nullptr, nullptr};
78+
%% endfor
79+
static constexpr Data* lookup[] = {
80+
%% for i in range(num_cores)
81+
&data{{i}},
82+
%% endfor
83+
};
84+
static inline Data& getData()
85+
{ return *lookup[::modm::platform::multicore::Core::cpuId()]; }
86+
%% else
87+
static inline Data data = {nullptr,nullptr};
88+
static inline Data& getData() { return data; }
89+
%% endif
90+
static inline void jump(Fiber& from, Fiber& to)
91+
{
92+
auto& d = getData();
93+
d.current = &to;
94+
modm_context_jump(&(from.ctx.sp), to.ctx.sp);
95+
}
96+
public:
97+
// Should be called by the main() function.
98+
static inline bool
99+
run()
100+
{
101+
auto& d = getData();
102+
if (d.last == nullptr) return false;
103+
d.current = d.last->next;
104+
modm_context_start(d.current->ctx.sp);
105+
return true;
106+
}
107+
108+
static inline bool
109+
empty()
110+
{
111+
return getData().empty();
112+
}
113+
114+
static inline Fiber*
115+
removeCurrent()
116+
{
117+
return getData().removeCurrent();
118+
}
119+
120+
static inline void
121+
runNext(Fiber* fiber)
122+
{
123+
auto& d = getData();
124+
fiber->next = d.current->next;
125+
d.current->next = fiber;
126+
}
127+
128+
static inline void
129+
runLast(Fiber* fiber)
130+
{
131+
getData().runLast(fiber);
132+
}
133+
134+
protected:
135+
%% if multicore
136+
static inline void
137+
registerFiber(Fiber* fiber, size_t core)
138+
{
139+
::modm::platform::multicore::SystemSpinLockGuard g;
140+
if (core != ::modm::platform::multicore::Core::cpuId())
141+
{
142+
lookup[core]->registerFiber(fiber);
143+
return;
144+
}
145+
%% else
146+
static inline void
147+
registerFiber(Fiber* fiber)
148+
{
149+
%% endif
150+
getData().registerFiber(fiber);
151+
}
152+
153+
static inline void
154+
deregisterFiber()
155+
{
156+
auto& d = getData();
157+
Fiber* next = d.current->next;
158+
d.removeCurrent();
159+
if (d.empty())
160+
{
161+
d.current = nullptr;
162+
modm_context_end();
163+
}
164+
d.jump(*next);
165+
}
166+
};
167+
168+
inline void
169+
yield()
170+
{
171+
auto& d = Scheduler::getData();
172+
if (d.current == nullptr) return;
173+
Fiber* next = d.current->next;
174+
if (next == d.current) return;
175+
d.last = d.current;
176+
d.jump(*next);
177+
}
178+
179+
} // namespace modm::fiber

0 commit comments

Comments
 (0)