Skip to content

Commit 04cd393

Browse files
committed
WIP add stack overflow check in yield
1 parent 1463562 commit 04cd393

File tree

10 files changed

+179
-123
lines changed

10 files changed

+179
-123
lines changed
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/*
2+
* Copyright (c) 2024, Niklas Hauser
3+
*
4+
* This file is part of the modm project.
5+
*
6+
* This Source Code Form is subject to the terms of the Mozilla Public
7+
* License, v. 2.0. If a copy of the MPL was not distributed with this
8+
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
9+
*/
10+
// ----------------------------------------------------------------------------
11+
12+
#include <modm/board.hpp>
13+
#include <modm/processing.hpp>
14+
15+
using namespace Board;
16+
using namespace std::chrono_literals;
17+
18+
// modm::Fiber<> blinky([]
19+
// {
20+
// while(1)
21+
// {
22+
// Board::Leds::toggle();
23+
// modm::this_fiber::sleep_for(0.5s);
24+
// }
25+
// });
26+
27+
modm::Fiber<> bad_fiber([]
28+
{
29+
30+
MODM_LOG_INFO << "\nReboot!\nPush the button to overflow the stack!" << modm::endl;
31+
32+
while(1)
33+
{
34+
// cause stack overflow on button push
35+
if (Button::read()) asm volatile ("push {r0-r7}");
36+
modm::this_fiber::yield();
37+
}
38+
});
39+
40+
int
41+
main()
42+
{
43+
Board::initialize();
44+
Board::Leds::setOutput();
45+
46+
modm::fiber::Scheduler::run();
47+
48+
return 0;
49+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<library>
2+
<!-- <extends>modm:nucleo-u575zi-q</extends> -->
3+
<extends>modm:nucleo-g071rb</extends>
4+
<options>
5+
<option name="modm:build:build.path">../../../build/generic/fiber_overflow</option>
6+
</options>
7+
<modules>
8+
<module>modm:build:scons</module>
9+
<module>modm:processing:fiber</module>
10+
</modules>
11+
</library>

examples/nucleo_u575zi-q/fiber_overflow/project.xml

Lines changed: 0 additions & 10 deletions
This file was deleted.

src/modm/processing/fiber/context.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ modm_context_reset(modm_context_t *ctx);
6464
* Switches control from the main context to the fiber context. This initializes
6565
* the hardware and then jumps from the caller context into the `to` fiber.
6666
*/
67-
void
67+
uintptr_t
6868
modm_context_start(modm_context_t *to);
6969

7070
/**
@@ -80,7 +80,7 @@ modm_context_jump(modm_context_t *from, modm_context_t *to) asm("modm_context_ju
8080
* `modm_context_start()` function.
8181
*/
8282
void modm_noreturn
83-
modm_context_end();
83+
modm_context_end(uintptr_t retval);
8484

8585
/**
8686
* Zeros the register file and watermarks the rest of the stack.

src/modm/processing/fiber/context_arm_m.cpp.in

Lines changed: 33 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ modm_context_stack_usage(const modm_context_t *ctx)
142142
bool
143143
modm_context_stack_overflow(const modm_context_t *ctx)
144144
{
145-
return *ctx->bottom != StackWatermark;
145+
return ctx->sp < ctx->bottom or *ctx->bottom != StackWatermark;
146146
}
147147

148148
#define MODM_PUSH_CONTEXT() \
@@ -173,7 +173,7 @@ modm_context_stack_overflow(const modm_context_t *ctx)
173173
"pop {r4-r11, pc} \n\t"
174174
%% endif
175175
%#
176-
void modm_naked
176+
uintptr_t modm_naked
177177
modm_context_start(modm_context_t*)
178178
{
179179
asm volatile
@@ -211,41 +211,57 @@ modm_context_jump(modm_context_t*, modm_context_t*)
211211
(
212212
MODM_PUSH_CONTEXT()
213213
%#
214+
%% if not with_psplim
215+
"ldr r3, [r0, #4] \n\t" // Load from->bottom
216+
%% endif
214217
%% if is_cm0
215-
"mov r2, sp \n\t"
216-
"str r2, [r0] \n\t" // Store the SP in from->sp
218+
"mov r2, sp \n\t"
219+
"str r2, [r0] \n\t" // Store the SP in from->sp
220+
%#
221+
"cmp r2, r3 \n\t" // Compare SP to from->bottom
217222
%% else
218-
"str sp, [r0] \n\t" // Store the SP in from->sp
223+
"str sp, [r0] \n\t" // Store the SP in from->sp
224+
%% if not with_psplim
225+
%#
226+
"cmp sp, r3 \n\t" // Compare SP to from->bottom
227+
%% endif
228+
%% endif
229+
%% if not with_psplim
230+
"bls modm_context_end \n\t" // If SP <= bottom, stack overflow
231+
"ldr r3, [r3] \n\t" // Load stack bottom
232+
"ldr r2, =0xf00dcafe \n\t" // Load StackWatermark value
233+
"cmp r2, r3 \n\t" // Check if stack watermark is still at the bottom
234+
"bne modm_context_end \n\t" // If not, stack overflow
219235
%% endif
220236
%#
221237
%% if is_cm0
222-
"ldr r2, [r1] \n\t"
223-
"mov sp, r2 \n\t" // Restore SP from to->sp
238+
"ldr r2, [r1] \n\t"
239+
"mov sp, r2 \n\t" // Restore SP from to->sp
224240
%% elif with_psplim
225-
"ldm r1, {r1-r2} \n\t"
226-
"msr psplim, r2 \n\t" // Set PSPLIM to ctx->bottom
227-
"mov sp, r1 \n\t" // Set PSP to ctx->sp
241+
"ldm r1, {r1-r2} \n\t"
242+
"msr psplim, r2 \n\t" // Set PSPLIM to ctx->bottom
243+
"mov sp, r1 \n\t" // Set PSP to ctx->sp
228244
%% else
229-
"ldr sp, [r1] \n\t" // Restore SP from to->sp
245+
"ldr sp, [r1] \n\t" // Restore SP from to->sp
230246
%% endif
231247
%#
232248
MODM_POP_CONTEXT()
233249
);
234250
}
235251

236252
void modm_naked
237-
modm_context_end()
253+
modm_context_end(uintptr_t)
238254
{
239255
asm volatile
240256
(
241-
"mrs r0, control \n\t"
257+
"mrs r1, control \n\t"
242258
%% if is_cm0
243-
"mov r1, #2 \n\t"
244-
"bic r0, r0, r1 \n\t" // Unset SPSEL
259+
"mov r2, #2 \n\t"
260+
"bic r1, r1, r2 \n\t" // Unset SPSEL
245261
%% else
246-
"bic r0, r0, #2 \n\t" // Unset SPSEL
262+
"bic r1, r1, #2 \n\t" // Unset SPSEL
247263
%% endif
248-
"msr control, r0 \n\t"
264+
"msr control, r1 \n\t"
249265

250266
MODM_POP_CONTEXT()
251267
);

src/modm/processing/fiber/context_avr.cpp

Lines changed: 48 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -149,67 +149,90 @@ modm_context_stack_usage(const modm_context_t *ctx)
149149
bool
150150
modm_context_stack_overflow(const modm_context_t *ctx)
151151
{
152-
return *p2u(ctx->bottom) != StackWatermark;
152+
return ctx->sp < ctx->bottom or *p2u(ctx->bottom) != StackWatermark;
153153
}
154154

155155
// Stores only the stack pointer of the main stack
156156
static uintptr_t main_context_sp;
157157
static_assert(offsetof(modm_context_t, sp) == 0);
158158

159-
void
159+
uintptr_t
160160
modm_context_start(modm_context_t *to)
161161
{
162162
modm_context_jump((modm_context_t*)&main_context_sp, to);
163+
__builtin_unreachable();
163164
}
164165

166+
extern "C" void
167+
modm_context_jump_return(uintptr_t, modm_context_t*);
168+
165169
void modm_naked
166170
modm_context_jump(modm_context_t*, modm_context_t*)
167171
{
168172
asm volatile
169173
(
170174
// Push callee-saved registers on stack
171175
".irp regs, 2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,28,29 \n\t"
172-
"push r\\regs \n\t"
173-
".endr \n\t"
176+
"push r\\regs \n\t"
177+
".endr \n\t"
174178

175179
// Store the SP of current fiber
176-
"mov ZL, r24 \n\t"
177-
"mov ZH, r25 \n\t"
178-
"in r24, __SP_L__ \n\t"
179-
"in r25, __SP_H__ \n\t"
180-
"st Z+, r24 \n\t"
181-
"st Z, r25 \n\t"
180+
"mov ZL, r24 \n\t"
181+
"mov ZH, r25 \n\t"
182+
"in r20, __SP_L__ \n\t"
183+
"in r21, __SP_H__ \n\t"
184+
"std Z+1, r20 \n\t"
185+
"st Z, r21 \n\t"
186+
187+
// Check for stack overflow via bottom
188+
"ldd XL, Z+3 \n\t"
189+
"ldd XH, Z+2 \n\t"
190+
"cp r20, XL \n\t"
191+
"cpc r21, XH \n\t"
192+
"brcs modm_context_end \n\t"
193+
194+
// Check for stack overflow via watermark
195+
"ld r20, X \n\t"
196+
"cpi r20, 0xaa \n\t"
197+
"brne modm_context_end \n\t"
198+
199+
"modm_context_jump_return: \n\t"
182200

183201
// Load the SP of next fiber
184-
"mov ZL, r22 \n\t"
185-
"mov ZH, r23 \n\t"
186-
"ld r22, Z+ \n\t"
187-
"ld r23, Z \n\t"
202+
"mov ZL, r22 \n\t"
203+
"mov ZH, r23 \n\t"
204+
"ld r22, Z+ \n\t"
205+
"ld r23, Z \n\t"
188206

189207
// Save SREG and disable interrupts
190-
"in r24, __SREG__ \n\t"
191-
"cli \n\t"
208+
"in r20, __SREG__ \n\t"
209+
"cli \n\t"
192210

193211
// Write the SP
194-
"out __SP_L__, r22 \n\t"
195-
"out __SP_H__, r23 \n\t"
212+
"out __SP_L__, r22 \n\t"
213+
"out __SP_H__, r23 \n\t"
196214

197215
// Re-enable interrupts by restoring SREG
198-
"out __SREG__, r24 \n\t"
216+
"out __SREG__, r20 \n\t"
199217

200218
// Pop callee-saved registers from stack
201219
".irp regs, 29,28,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2 \n\t"
202-
"pop r\\regs \n\t"
203-
".endr \n\t"
220+
"pop r\\regs \n\t"
221+
".endr \n\t"
204222

205-
"ret \n\t"
223+
"ret \n\t"
206224
);
207225
}
208226

209227
void
210-
modm_context_end()
228+
modm_context_end(uintptr_t retval)
211229
{
212-
uintptr_t dummy;
213-
modm_context_jump((modm_context_t*)&dummy, (modm_context_t*)&main_context_sp);
230+
modm_context_jump_return(retval, (modm_context_t*)&main_context_sp);
214231
__builtin_unreachable();
215232
}
233+
234+
235+
236+
237+
238+

src/modm/processing/fiber/module.lb

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ def is_enabled(env):
2121
not env.has_module(":processing:protothread")
2222

2323
def prepare(module, options):
24-
module.depends(":architecture:clock", ":architecture:atomic")
24+
module.depends(":architecture:clock", ":architecture:atomic", ":architecture:assert")
2525

2626
module.add_query(
2727
EnvironmentQuery(name="__enabled", factory=is_enabled))
@@ -56,7 +56,7 @@ def build(env):
5656

5757
if core.startswith("cortex-m"):
5858
env.substitutions["stack_minimum"] = (2 + 9 + (16 if with_fpu else 0)) * 4
59-
env.substitutions["default_stack_size"] = 512
59+
env.substitutions["default_stack_size"] = 1024
6060
env.template("context_arm_m.cpp.in")
6161

6262
elif core.startswith("avr"):
@@ -77,7 +77,7 @@ def build(env):
7777
env.copy("context.h")
7878
env.template("stack.hpp.in")
7979
env.template("scheduler.hpp.in")
80-
env.copy("scheduler.cpp")
80+
env.template("scheduler.cpp.in")
8181
env.copy("task.hpp")
8282
env.copy("task_impl.hpp")
8383
env.copy("functions.hpp")

src/modm/processing/fiber/scheduler.cpp

Lines changed: 0 additions & 31 deletions
This file was deleted.

0 commit comments

Comments
 (0)