kopia lustrzana https://github.com/micropython/micropython
py/mpstate: Make exceptions thread-local.
This moves mp_pending_exception from mp_state_vm_t to mp_state_thread_t. This allows exceptions to be scheduled on a specific thread. Signed-off-by: David Lechner <david@pybricks.com>pull/7425/head
rodzic
7c51cb2307
commit
ca920f7218
|
@ -237,7 +237,7 @@ STATIC mp_obj_t esp_scan(mp_obj_t self_in) {
|
||||||
while (esp_scan_list != NULL) {
|
while (esp_scan_list != NULL) {
|
||||||
// our esp_scan_cb is called via ets_loop_iter so it's safe to set the
|
// our esp_scan_cb is called via ets_loop_iter so it's safe to set the
|
||||||
// esp_scan_list variable to NULL without disabling interrupts
|
// esp_scan_list variable to NULL without disabling interrupts
|
||||||
if (MP_STATE_VM(mp_pending_exception) != NULL) {
|
if (MP_STATE_THREAD(mp_pending_exception) != NULL) {
|
||||||
esp_scan_list = NULL;
|
esp_scan_list = NULL;
|
||||||
mp_handle_pending(true);
|
mp_handle_pending(true);
|
||||||
}
|
}
|
||||||
|
|
|
@ -149,7 +149,7 @@ STATIC void async_stop(void) {
|
||||||
STATIC void wait_for_event(void) {
|
STATIC void wait_for_event(void) {
|
||||||
while (!wakeup_event) {
|
while (!wakeup_event) {
|
||||||
// allow CTRL-C to stop the animation
|
// allow CTRL-C to stop the animation
|
||||||
if (MP_STATE_VM(mp_pending_exception) != MP_OBJ_NULL) {
|
if (MP_STATE_THREAD(mp_pending_exception) != MP_OBJ_NULL) {
|
||||||
async_stop();
|
async_stop();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -140,7 +140,7 @@ STATIC void wait_async_music_idle(void) {
|
||||||
// wait for the async music state to become idle
|
// wait for the async music state to become idle
|
||||||
while (music_data->async_state != ASYNC_MUSIC_STATE_IDLE) {
|
while (music_data->async_state != ASYNC_MUSIC_STATE_IDLE) {
|
||||||
// allow CTRL-C to stop the music
|
// allow CTRL-C to stop the music
|
||||||
if (MP_STATE_VM(mp_pending_exception) != MP_OBJ_NULL) {
|
if (MP_STATE_THREAD(mp_pending_exception) != MP_OBJ_NULL) {
|
||||||
music_data->async_state = ASYNC_MUSIC_STATE_IDLE;
|
music_data->async_state = ASYNC_MUSIC_STATE_IDLE;
|
||||||
pwm_set_duty_cycle(music_data->async_pin->pin, 0); // TODO: remove pin setting.
|
pwm_set_duty_cycle(music_data->async_pin->pin, 0); // TODO: remove pin setting.
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -140,7 +140,7 @@ int switch_get(int sw) {
|
||||||
// TODO need an irq
|
// TODO need an irq
|
||||||
void uart_rx_irq(void) {
|
void uart_rx_irq(void) {
|
||||||
if (c == interrupt_char) {
|
if (c == interrupt_char) {
|
||||||
MP_STATE_VM(mp_pending_exception) = MP_STATE_PORT(keyboard_interrupt_obj);
|
MP_STATE_THREAD(mp_pending_exception) = MP_STATE_PORT(keyboard_interrupt_obj);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -60,10 +60,10 @@ void pendsv_init(void) {
|
||||||
// the given exception object using nlr_jump in the context of the top-level
|
// the given exception object using nlr_jump in the context of the top-level
|
||||||
// thread.
|
// thread.
|
||||||
void pendsv_kbd_intr(void) {
|
void pendsv_kbd_intr(void) {
|
||||||
if (MP_STATE_VM(mp_pending_exception) == MP_OBJ_NULL) {
|
if (MP_STATE_THREAD(mp_pending_exception) == MP_OBJ_NULL) {
|
||||||
mp_sched_keyboard_interrupt();
|
mp_sched_keyboard_interrupt();
|
||||||
} else {
|
} else {
|
||||||
MP_STATE_VM(mp_pending_exception) = MP_OBJ_NULL;
|
MP_STATE_THREAD(mp_pending_exception) = MP_OBJ_NULL;
|
||||||
pendsv_object = &MP_STATE_VM(mp_kbd_exception);
|
pendsv_object = &MP_STATE_VM(mp_kbd_exception);
|
||||||
SCB->ICSR = SCB_ICSR_PENDSVSET_Msk;
|
SCB->ICSR = SCB_ICSR_PENDSVSET_Msk;
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,7 +54,7 @@ STATIC void sighandler(int signum) {
|
||||||
sigprocmask(SIG_SETMASK, &mask, NULL);
|
sigprocmask(SIG_SETMASK, &mask, NULL);
|
||||||
nlr_raise(MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_kbd_exception)));
|
nlr_raise(MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_kbd_exception)));
|
||||||
#else
|
#else
|
||||||
if (MP_STATE_VM(mp_pending_exception) == MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_kbd_exception))) {
|
if (MP_STATE_THREAD(mp_pending_exception) == MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_kbd_exception))) {
|
||||||
// this is the second time we are called, so die straight away
|
// this is the second time we are called, so die straight away
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
|
@ -80,7 +80,7 @@ void mp_hal_stdio_mode_orig(void) {
|
||||||
// the thread created for handling it might not be running yet so we'd miss the notification.
|
// the thread created for handling it might not be running yet so we'd miss the notification.
|
||||||
BOOL WINAPI console_sighandler(DWORD evt) {
|
BOOL WINAPI console_sighandler(DWORD evt) {
|
||||||
if (evt == CTRL_C_EVENT) {
|
if (evt == CTRL_C_EVENT) {
|
||||||
if (MP_STATE_VM(mp_pending_exception) == MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_kbd_exception))) {
|
if (MP_STATE_THREAD(mp_pending_exception) == MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_kbd_exception))) {
|
||||||
// this is the second time we are called, so die straight away
|
// this is the second time we are called, so die straight away
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
|
@ -174,6 +174,8 @@ STATIC void *thread_entry(void *args_in) {
|
||||||
// The GC starts off unlocked on this thread.
|
// The GC starts off unlocked on this thread.
|
||||||
ts.gc_lock_depth = 0;
|
ts.gc_lock_depth = 0;
|
||||||
|
|
||||||
|
ts.mp_pending_exception = MP_OBJ_NULL;
|
||||||
|
|
||||||
// set locals and globals from the calling context
|
// set locals and globals from the calling context
|
||||||
mp_locals_set(args->dict_locals);
|
mp_locals_set(args->dict_locals);
|
||||||
mp_globals_set(args->dict_globals);
|
mp_globals_set(args->dict_globals);
|
||||||
|
@ -184,7 +186,6 @@ STATIC void *thread_entry(void *args_in) {
|
||||||
mp_thread_start();
|
mp_thread_start();
|
||||||
|
|
||||||
// TODO set more thread-specific state here:
|
// TODO set more thread-specific state here:
|
||||||
// mp_pending_exception? (root pointer)
|
|
||||||
// cur_exception (root pointer)
|
// cur_exception (root pointer)
|
||||||
|
|
||||||
DEBUG_printf("[thread] start ts=%p args=%p stack=%p\n", &ts, &args, MP_STATE_THREAD(stack_top));
|
DEBUG_printf("[thread] start ts=%p args=%p stack=%p\n", &ts, &args, MP_STATE_THREAD(stack_top));
|
||||||
|
|
|
@ -137,9 +137,6 @@ typedef struct _mp_state_vm_t {
|
||||||
// dictionary with loaded modules (may be exposed as sys.modules)
|
// dictionary with loaded modules (may be exposed as sys.modules)
|
||||||
mp_obj_dict_t mp_loaded_modules_dict;
|
mp_obj_dict_t mp_loaded_modules_dict;
|
||||||
|
|
||||||
// pending exception object (MP_OBJ_NULL if not pending)
|
|
||||||
volatile mp_obj_t mp_pending_exception;
|
|
||||||
|
|
||||||
#if MICROPY_ENABLE_SCHEDULER
|
#if MICROPY_ENABLE_SCHEDULER
|
||||||
mp_sched_item_t sched_queue[MICROPY_SCHEDULER_DEPTH];
|
mp_sched_item_t sched_queue[MICROPY_SCHEDULER_DEPTH];
|
||||||
#endif
|
#endif
|
||||||
|
@ -266,6 +263,9 @@ typedef struct _mp_state_thread_t {
|
||||||
|
|
||||||
nlr_buf_t *nlr_top;
|
nlr_buf_t *nlr_top;
|
||||||
|
|
||||||
|
// pending exception object (MP_OBJ_NULL if not pending)
|
||||||
|
volatile mp_obj_t mp_pending_exception;
|
||||||
|
|
||||||
#if MICROPY_PY_SYS_SETTRACE
|
#if MICROPY_PY_SYS_SETTRACE
|
||||||
mp_obj_t prof_trace_callback;
|
mp_obj_t prof_trace_callback;
|
||||||
bool prof_callback_is_executing;
|
bool prof_callback_is_executing;
|
||||||
|
|
|
@ -297,7 +297,7 @@ STATIC mp_obj_t mp_prof_callback_invoke(mp_obj_t callback, prof_callback_args_t
|
||||||
|
|
||||||
mp_prof_is_executing = false;
|
mp_prof_is_executing = false;
|
||||||
|
|
||||||
if (MP_STATE_VM(mp_pending_exception) != MP_OBJ_NULL) {
|
if (MP_STATE_THREAD(mp_pending_exception) != MP_OBJ_NULL) {
|
||||||
mp_handle_pending(true);
|
mp_handle_pending(true);
|
||||||
}
|
}
|
||||||
return top;
|
return top;
|
||||||
|
|
|
@ -62,7 +62,7 @@ void mp_init(void) {
|
||||||
qstr_init();
|
qstr_init();
|
||||||
|
|
||||||
// no pending exceptions to start with
|
// no pending exceptions to start with
|
||||||
MP_STATE_VM(mp_pending_exception) = MP_OBJ_NULL;
|
MP_STATE_THREAD(mp_pending_exception) = MP_OBJ_NULL;
|
||||||
#if MICROPY_ENABLE_SCHEDULER
|
#if MICROPY_ENABLE_SCHEDULER
|
||||||
MP_STATE_VM(sched_state) = MP_SCHED_IDLE;
|
MP_STATE_VM(sched_state) = MP_SCHED_IDLE;
|
||||||
MP_STATE_VM(sched_idx) = 0;
|
MP_STATE_VM(sched_idx) = 0;
|
||||||
|
|
|
@ -29,7 +29,7 @@
|
||||||
#include "py/runtime.h"
|
#include "py/runtime.h"
|
||||||
|
|
||||||
void MICROPY_WRAP_MP_SCHED_EXCEPTION(mp_sched_exception)(mp_obj_t exc) {
|
void MICROPY_WRAP_MP_SCHED_EXCEPTION(mp_sched_exception)(mp_obj_t exc) {
|
||||||
MP_STATE_VM(mp_pending_exception) = exc;
|
MP_STATE_THREAD(mp_pending_exception) = exc;
|
||||||
#if MICROPY_ENABLE_SCHEDULER
|
#if MICROPY_ENABLE_SCHEDULER
|
||||||
if (MP_STATE_VM(sched_state) == MP_SCHED_IDLE) {
|
if (MP_STATE_VM(sched_state) == MP_SCHED_IDLE) {
|
||||||
MP_STATE_VM(sched_state) = MP_SCHED_PENDING;
|
MP_STATE_VM(sched_state) = MP_SCHED_PENDING;
|
||||||
|
@ -66,9 +66,9 @@ void mp_handle_pending(bool raise_exc) {
|
||||||
mp_uint_t atomic_state = MICROPY_BEGIN_ATOMIC_SECTION();
|
mp_uint_t atomic_state = MICROPY_BEGIN_ATOMIC_SECTION();
|
||||||
// Re-check state is still pending now that we're in the atomic section.
|
// Re-check state is still pending now that we're in the atomic section.
|
||||||
if (MP_STATE_VM(sched_state) == MP_SCHED_PENDING) {
|
if (MP_STATE_VM(sched_state) == MP_SCHED_PENDING) {
|
||||||
mp_obj_t obj = MP_STATE_VM(mp_pending_exception);
|
mp_obj_t obj = MP_STATE_THREAD(mp_pending_exception);
|
||||||
if (obj != MP_OBJ_NULL) {
|
if (obj != MP_OBJ_NULL) {
|
||||||
MP_STATE_VM(mp_pending_exception) = MP_OBJ_NULL;
|
MP_STATE_THREAD(mp_pending_exception) = MP_OBJ_NULL;
|
||||||
if (!mp_sched_num_pending()) {
|
if (!mp_sched_num_pending()) {
|
||||||
MP_STATE_VM(sched_state) = MP_SCHED_IDLE;
|
MP_STATE_VM(sched_state) = MP_SCHED_IDLE;
|
||||||
}
|
}
|
||||||
|
@ -115,7 +115,7 @@ void mp_sched_unlock(void) {
|
||||||
assert(MP_STATE_VM(sched_state) < 0);
|
assert(MP_STATE_VM(sched_state) < 0);
|
||||||
if (++MP_STATE_VM(sched_state) == 0) {
|
if (++MP_STATE_VM(sched_state) == 0) {
|
||||||
// vm became unlocked
|
// vm became unlocked
|
||||||
if (MP_STATE_VM(mp_pending_exception) != MP_OBJ_NULL || mp_sched_num_pending()) {
|
if (MP_STATE_THREAD(mp_pending_exception) != MP_OBJ_NULL || mp_sched_num_pending()) {
|
||||||
MP_STATE_VM(sched_state) = MP_SCHED_PENDING;
|
MP_STATE_VM(sched_state) = MP_SCHED_PENDING;
|
||||||
} else {
|
} else {
|
||||||
MP_STATE_VM(sched_state) = MP_SCHED_IDLE;
|
MP_STATE_VM(sched_state) = MP_SCHED_IDLE;
|
||||||
|
@ -148,9 +148,9 @@ bool MICROPY_WRAP_MP_SCHED_SCHEDULE(mp_sched_schedule)(mp_obj_t function, mp_obj
|
||||||
|
|
||||||
// A variant of this is inlined in the VM at the pending exception check
|
// A variant of this is inlined in the VM at the pending exception check
|
||||||
void mp_handle_pending(bool raise_exc) {
|
void mp_handle_pending(bool raise_exc) {
|
||||||
if (MP_STATE_VM(mp_pending_exception) != MP_OBJ_NULL) {
|
if (MP_STATE_THREAD(mp_pending_exception) != MP_OBJ_NULL) {
|
||||||
mp_obj_t obj = MP_STATE_VM(mp_pending_exception);
|
mp_obj_t obj = MP_STATE_THREAD(mp_pending_exception);
|
||||||
MP_STATE_VM(mp_pending_exception) = MP_OBJ_NULL;
|
MP_STATE_THREAD(mp_pending_exception) = MP_OBJ_NULL;
|
||||||
if (raise_exc) {
|
if (raise_exc) {
|
||||||
nlr_raise(obj);
|
nlr_raise(obj);
|
||||||
}
|
}
|
||||||
|
|
10
py/vm.c
10
py/vm.c
|
@ -1375,9 +1375,9 @@ pending_exception_check:
|
||||||
// Re-check state is still pending now that we're in the atomic section.
|
// Re-check state is still pending now that we're in the atomic section.
|
||||||
if (MP_STATE_VM(sched_state) == MP_SCHED_PENDING) {
|
if (MP_STATE_VM(sched_state) == MP_SCHED_PENDING) {
|
||||||
MARK_EXC_IP_SELECTIVE();
|
MARK_EXC_IP_SELECTIVE();
|
||||||
mp_obj_t obj = MP_STATE_VM(mp_pending_exception);
|
mp_obj_t obj = MP_STATE_THREAD(mp_pending_exception);
|
||||||
if (obj != MP_OBJ_NULL) {
|
if (obj != MP_OBJ_NULL) {
|
||||||
MP_STATE_VM(mp_pending_exception) = MP_OBJ_NULL;
|
MP_STATE_THREAD(mp_pending_exception) = MP_OBJ_NULL;
|
||||||
if (!mp_sched_num_pending()) {
|
if (!mp_sched_num_pending()) {
|
||||||
MP_STATE_VM(sched_state) = MP_SCHED_IDLE;
|
MP_STATE_VM(sched_state) = MP_SCHED_IDLE;
|
||||||
}
|
}
|
||||||
|
@ -1391,10 +1391,10 @@ pending_exception_check:
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
// This is an inlined variant of mp_handle_pending
|
// This is an inlined variant of mp_handle_pending
|
||||||
if (MP_STATE_VM(mp_pending_exception) != MP_OBJ_NULL) {
|
if (MP_STATE_THREAD(mp_pending_exception) != MP_OBJ_NULL) {
|
||||||
MARK_EXC_IP_SELECTIVE();
|
MARK_EXC_IP_SELECTIVE();
|
||||||
mp_obj_t obj = MP_STATE_VM(mp_pending_exception);
|
mp_obj_t obj = MP_STATE_THREAD(mp_pending_exception);
|
||||||
MP_STATE_VM(mp_pending_exception) = MP_OBJ_NULL;
|
MP_STATE_THREAD(mp_pending_exception) = MP_OBJ_NULL;
|
||||||
RAISE(obj);
|
RAISE(obj);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
Ładowanie…
Reference in New Issue