10000 py: Add portable framework to query/check C stack usage. · micropython/micropython@2366869 · GitHub
[go: up one dir, main page]

Skip to content

Commit 2366869

Browse files
author
Paul Sokolovsky
committed
py: Add portable framework to query/check C stack usage.
Such mechanism is important to get stable Python functioning, because Python function calling is handled with C stack. The idea is to sprinkle STACK_CHECK() calls in places where there can be C recursion. TODO: Add more STACK_CHECK()'s.
1 parent 91b576d commit 2366869

File tree

6 files changed

+119
-9
lines changed

6 files changed

+119
-9
lines changed

py/mpconfig.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,12 @@
157157
#define MICROPY_ENABLE_GC_FINALISER (0)
158158
#endif
159159

160+
// Whether to check C stack usage. C stack used for calling Python functions,
161+
// etc. Not checking means segfault on overflow.
162+
#ifndef MICROPY_STACK_CHECK
163+
#define MICROPY_STACK_CHECK (1)
164+
#endif
165+
160166
// Whether to include REPL helper function
161167
#ifndef MICROPY_HELPER_REPL
162168
#define MICROPY_HELPER_REPL (0)

py/objfun.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
#include "runtime0.h"
4040
#include "runtime.h"
4141
#include "bc.h"
42+
#include "stackctrl.h"
4243

4344
#if 0 // print debugging info
4445
#define DEBUG_PRINT (1)
@@ -204,6 +205,8 @@ STATIC NORETURN void fun_pos_args_mismatch(mp_obj_fun_bc_t *f, uint expected, ui
204205
// code_state should have ->ip filled in (pointing past code info block),
205206
// as well as ->n_state.
206207
void mp_setup_code_state(mp_code_state *code_state, mp_obj_t self_in, uint n_args, uint n_kw, const mp_obj_t *args) {
208+
// This function is pretty complicated. It's main aim is to be efficient in speed and RAM
209+
// usage for the common case of positional only args.
207210
mp_obj_fun_bc_t *self = self_in;
208211
machine_uint_t n_state = code_state->n_state;
209212
const byte *ip = code_state->ip;
@@ -353,8 +356,7 @@ continue2:;
353356

354357

355358
STATIC mp_obj_t fun_bc_call(mp_obj_t self_in, uint n_args, uint n_kw, const mp_obj_t *args) {
356-
// This function is pretty complicated. It's main aim is to be efficient in speed and RAM
357-
// usage for the common case of positional only args.
359+
STACK_CHECK();
358360

359361
DEBUG_printf("Input n_args: %d, n_kw: %d\n", n 10000 _args, n_kw);
360362
DEBUG_printf("Input pos args: ");

py/py.mk

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ PY_O_BASENAME = \
4343
parsenum.o \
4444
emitglue.o \
4545
runtime.o \
46+
stackctrl.o \
4647
argcheck.o \
4748
map.o \
4849
obj.o \

py/stackctrl.c

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
/*
2+
* This file is part of the Micro Python project, http://micropython.org/
3+
*
4+
* The MIT License (MIT)
5+
*
6+
* Copyright (c) 2014 Paul Sokolovsky
7+
*
8+
* Permission is hereby granted, free of charge, to any person obtaining a copy
9+
* of this software and associated documentation files (the "Software"), to deal
10+
* in the Software without restriction, including without limitation the rights
11+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12+
* copies of the Software, and to permit persons to whom the Software is
13+
* furnished to do so, subject to the following conditions:
14+
*
15+
* The above copyright notice and this permission notice shall be included in
16+
* all copies or substantial portions of the Software.
17+
*
18+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24+
* THE SOFTWARE.
25+
*/
26+
27+
#include "mpconfig.h"
28+
#include "misc.h"
29+
#include "nlr.h"
30+
#include "qstr.h"
31+
#include "obj.h"
32+
#include "runtime.h"
33+
#include "stackctrl.h"
34+
35+
// Stack top at the start of program
36+
char *stack_top;
37+
38+
void stack_ctrl_init() {
39+
volatile int stack_dummy;
40+
stack_top = (char*)&stack_dummy;
41+
}
42+
43+
uint stack_usage() {
44+
// Assumes descending stack
45+
volatile int stack_dummy;
46+
return stack_top - (char*)&stack_dummy;
47+
}
48+
49+
#if MICROPY_STACK_CHECK
50+
51+
uint stack_limit = 10240;
52+
53+
void stack_set_limit(uint limit) {
54+
stack_limit = limit;
55+
}
56+
57+
void stack_check() {
58+
if (stack_usage() >= stack_limit) {
59+
nlr_raise(mp_obj_new_exception_msg(&mp_type_RuntimeError, "maximum recursion depth exceeded"));
60+
}
61+
}
62+
63+
#endif // MICROPY_STACK_CHECK

py/stackctrl.h

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
/*
2+
* This file is part of the Micro Python project, http://micropython.org/
3+
*
4+
* The MIT License (MIT)
5+
*
6+
* Copyright (c) 2014 Paul Sokolovsky
7+
*
8+
* Permission is hereby granted, free of charge, to any person obtaining a copy
9+
* of this software and associated documentation files (the "Software"), to deal
10+
* in the Software without restriction, including without limitation the rights
11+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12+
* copies of the Software, and to permit persons to whom the Software is
13+
* furnished to do so, subject to the following conditions:
14+
*
15+
* The above copyright notice and this permission notice shall be included in
16+
* all copies or substantial portions of the Software.
17+
*
18+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24+
* THE SOFTWARE.
25+
*/
26+
27+
void stack_ctrl_init();
28+
uint stack_usage();
29+
30+
#if MICROPY_STACK_CHECK
31+
32+
void stack_set_limit(uint limit);
33+
void stack_check();
34+
#define STACK_CHECK() stack_check()
35+
36+
#else
37+
38+
#define stack_set_limit(limit)
39+
#define STACK_CHECK()
40+
41+
#endif

unix/main.c

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
#include "gc.h"
5252
#include "genhdr/py-version.h"
5353
#include "input.h"
54+
#include "stackctrl.h"
5455

5556
// Command line options, with their defaults
5657
bool compile_only = false;
@@ -63,9 +64,6 @@ uint mp_verbose_flag;
6364
long heap_size = 128*1024 * (sizeof(machine_uint_t) / 4);
6465
#endif
6566

66-
// Stack top at the start of program
67-
char *stack_top;
68-
6967
void microsocket_init();
7068
void time_init();
7169
void ffi_init();
@@ -214,10 +212,9 @@ int usage(char **argv) {
214212
}
215213

216214
mp_obj_t mem_info(void) {
217-
volatile int stack_dummy;
218215
printf("mem: total=%d, current=%d, peak=%d\n",
219216
m_get_total_bytes_allocated(), m_get_current_bytes_allocated(), m_get_peak_bytes_allocated());
220-
printf("stack: " INT_FMT "\n", stack_top - (char*)&stack_dummy);
217+
printf("stack: %u\n", stack_usage());
221218
#if MICROPY_ENABLE_GC
222219
gc_dump_info();
223220
#endif
@@ -268,8 +265,8 @@ void pre_process_options(int argc, char **argv) {
268265
#endif
269266

270267
int main(int argc, char **argv) {
271-
volatile int stack_dummy;
272-
stack_top = (char*)&stack_dummy;
268+
stack_ctrl_init();
269+
stack_set_limit(32768);
273270

274271
pre_process_options(argc, argv);
275272

0 commit comments

Comments
 (0)
0