using vm cleanup and no globals

This commit is contained in:
Bill Sideris 2023-02-15 22:27:37 +02:00
parent cf6afe250c
commit c3b9567641
No known key found for this signature in database
GPG Key ID: 1BEF1BCEBA58EA33
1 changed files with 21 additions and 27 deletions

48
main.c
View File

@ -122,13 +122,9 @@
uint8_t value_out = 0; uint8_t value_out = 0;
#endif #endif
#if MICROPY_ENABLE_PYSTACK #if MICROPY_ENABLE_PYSTACK && CIRCUITPY_OS_GETENV
supervisor_allocation *pystack;
mp_int_t pystack_size = 0; // 0 indicated 'not allocated'
#if CIRCUITPY_OS_GETENV
#include "shared-module/os/__init__.h" #include "shared-module/os/__init__.h"
#endif #endif
#endif
static void reset_devices(void) { static void reset_devices(void) {
#if CIRCUITPY_BLEIO_HCI #if CIRCUITPY_BLEIO_HCI
@ -137,30 +133,24 @@ static void reset_devices(void) {
} }
#if MICROPY_ENABLE_PYSTACK #if MICROPY_ENABLE_PYSTACK
STATIC void alloc_pystack(void) { STATIC mp_int_t fetch_pystack_size(void) {
mp_int_t old_pystack_size = pystack_size; mp_int_t pystack_size = CIRCUITPY_PYSTACK_SIZE;
pystack_size = CIRCUITPY_PYSTACK_SIZE; // Use build default for now.
// Fetch value if exists from settings.toml
#if CIRCUITPY_OS_GETENV #if CIRCUITPY_OS_GETENV
// Fetch value if exists from settings.toml
// Leaves size to build default on any failure // Leaves size to build default on any failure
(void)common_hal_os_getenv_int("CIRCUITPY_PYSTACK_SIZE", &pystack_size); (void)common_hal_os_getenv_int("CIRCUITPY_PYSTACK_SIZE", &pystack_size);
// Check if value is valid // Check if value is valid
if ((CIRCUITPY_PYSTACK_SIZE != pystack_size) && ((pystack_size < 1) || (pystack_size % sizeof(size_t) != 0))) { if ((CIRCUITPY_PYSTACK_SIZE != pystack_size) && ((pystack_size < 1) || (pystack_size % sizeof(size_t) != 0))) {
pystack_size = CIRCUITPY_PYSTACK_SIZE; // Reset to build default pystack_size = CIRCUITPY_PYSTACK_SIZE; // Reset
// TODO: Find a way to inform the user about it. // TODO: Find a way to inform the user about it.
// Perhaps safemode? Or is it too much? // Perhaps safemode? Or is it too much?
} }
#endif #endif
if (old_pystack_size != pystack_size) { return pystack_size;
if (old_pystack_size != 0) {
free_memory(pystack);
}
pystack = allocate_memory(pystack_size, false, false);
}
} }
#endif #endif
STATIC void start_mp(supervisor_allocation *heap) { STATIC void start_mp(supervisor_allocation *heap, supervisor_allocation *pystack, mp_int_t pystack_size) {
supervisor_workflow_reset(); supervisor_workflow_reset();
// Stack limit should be less than real stack size, so we have a chance // Stack limit should be less than real stack size, so we have a chance
@ -292,7 +282,7 @@ STATIC void count_strn(void *data, const char *str, size_t len) {
*(size_t *)data += len; *(size_t *)data += len;
} }
STATIC void cleanup_after_vm(supervisor_allocation *heap, mp_obj_t exception) { STATIC void cleanup_after_vm(supervisor_allocation *heap, supervisor_allocation *pystack, mp_obj_t exception) {
// Get the traceback of any exception from this run off the heap. // Get the traceback of any exception from this run off the heap.
// MP_OBJ_SENTINEL means "this run does not contribute to traceback storage, don't touch it" // MP_OBJ_SENTINEL means "this run does not contribute to traceback storage, don't touch it"
// MP_OBJ_NULL (=0) means "this run completed successfully, clear any stored traceback" // MP_OBJ_NULL (=0) means "this run completed successfully, clear any stored traceback"
@ -373,6 +363,7 @@ STATIC void cleanup_after_vm(supervisor_allocation *heap, mp_obj_t exception) {
filesystem_flush(); filesystem_flush();
stop_mp(); stop_mp();
free_memory(heap); free_memory(heap);
free_memory(pystack);
supervisor_move_memory(); supervisor_move_memory();
// Let the workflows know we've reset in case they want to restart. // Let the workflows know we've reset in case they want to restart.
@ -428,10 +419,11 @@ STATIC bool run_code_py(safe_mode_t safe_mode, bool *simulate_reset) {
#endif #endif
#if MICROPY_ENABLE_PYSTACK #if MICROPY_ENABLE_PYSTACK
alloc_pystack(); mp_int_t pystack_size = fetch_pystack_size();
supervisor_allocation *pystack = allocate_memory(pystack_size, false, false);
#endif #endif
supervisor_allocation *heap = allocate_remaining_memory(); supervisor_allocation *heap = allocate_remaining_memory();
start_mp(heap); start_mp(heap, pystack, pystack_size);
#if CIRCUITPY_USB #if CIRCUITPY_USB
usb_setup_with_vm(); usb_setup_with_vm();
@ -479,7 +471,7 @@ STATIC bool run_code_py(safe_mode_t safe_mode, bool *simulate_reset) {
// Finished executing python code. Cleanup includes filesystem flush and a board reset. // Finished executing python code. Cleanup includes filesystem flush and a board reset.
cleanup_after_vm(heap, _exec_result.exception); cleanup_after_vm(heap, pystack, _exec_result.exception);
_exec_result.exception = NULL; _exec_result.exception = NULL;
// If a new next code file was set, that is a reason to keep it (obviously). Stuff this into // If a new next code file was set, that is a reason to keep it (obviously). Stuff this into
@ -776,10 +768,11 @@ STATIC void __attribute__ ((noinline)) run_boot_py(safe_mode_t safe_mode) {
// Do USB setup even if boot.py is not run. // Do USB setup even if boot.py is not run.
#if MICROPY_ENABLE_PYSTACK #if MICROPY_ENABLE_PYSTACK
alloc_pystack(); mp_int_t pystack_size = fetch_pystack_size();
supervisor_allocation *pystack = allocate_memory(pystack_size, false, false);
#endif #endif
supervisor_allocation *heap = allocate_remaining_memory(); supervisor_allocation *heap = allocate_remaining_memory();
start_mp(heap); start_mp(heap, pystack, pystack_size);
#if CIRCUITPY_USB #if CIRCUITPY_USB
// Set up default USB values after boot.py VM starts but before running boot.py. // Set up default USB values after boot.py VM starts but before running boot.py.
@ -865,7 +858,7 @@ STATIC void __attribute__ ((noinline)) run_boot_py(safe_mode_t safe_mode) {
port_post_boot_py(true); port_post_boot_py(true);
cleanup_after_vm(heap, _exec_result.exception); cleanup_after_vm(heap, pystack, _exec_result.exception);
_exec_result.exception = NULL; _exec_result.exception = NULL;
port_post_boot_py(false); port_post_boot_py(false);
@ -881,10 +874,11 @@ STATIC int run_repl(void) {
stack_resize(); stack_resize();
filesystem_flush(); filesystem_flush();
#if MICROPY_ENABLE_PYSTACK #if MICROPY_ENABLE_PYSTACK
alloc_pystack(); mp_int_t pystack_size = fetch_pystack_size();
supervisor_allocation *pystack = allocate_memory(pystack_size, false, false);
#endif #endif
supervisor_allocation *heap = allocate_remaining_memory(); supervisor_allocation *heap = allocate_remaining_memory();
start_mp(heap); start_mp(heap, pystack, pystack_size);
#if CIRCUITPY_USB #if CIRCUITPY_USB
usb_setup_with_vm(); usb_setup_with_vm();
@ -927,7 +921,7 @@ STATIC int run_repl(void) {
exit_code = PYEXEC_DEEP_SLEEP; exit_code = PYEXEC_DEEP_SLEEP;
} }
#endif #endif
cleanup_after_vm(heap, MP_OBJ_SENTINEL); cleanup_after_vm(heap, pystack, MP_OBJ_SENTINEL);
// Also reset bleio. The above call omits it in case workflows should continue. In this case, // Also reset bleio. The above call omits it in case workflows should continue. In this case,
// we're switching straight to another VM so we want to reset. // we're switching straight to another VM so we want to reset.