summaryrefslogtreecommitdiff
path: root/py
diff options
context:
space:
mode:
authorDavid Lechner <david@pybricks.com>2021-05-10 21:53:22 -0500
committerDamien George <damien@micropython.org>2021-06-19 09:43:44 +1000
commitca920f72184c50f61002aa9d5cd01555b1e28b7b (patch)
treea46b6cb9c91a275015b351443d1cb1181d8c5d14 /py
parent7c51cb2307eaca1a1ccc071e0bb5eb4a5f734610 (diff)
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>
Diffstat (limited to 'py')
-rw-r--r--py/modthread.c3
-rw-r--r--py/mpstate.h6
-rw-r--r--py/profile.c2
-rw-r--r--py/runtime.c2
-rw-r--r--py/scheduler.c14
-rw-r--r--py/vm.c10
6 files changed, 19 insertions, 18 deletions
diff --git a/py/modthread.c b/py/modthread.c
index 64fbb3f19..29b765493 100644
--- a/py/modthread.c
+++ b/py/modthread.c
@@ -174,6 +174,8 @@ STATIC void *thread_entry(void *args_in) {
// The GC starts off unlocked on this thread.
ts.gc_lock_depth = 0;
+ ts.mp_pending_exception = MP_OBJ_NULL;
+
// set locals and globals from the calling context
mp_locals_set(args->dict_locals);
mp_globals_set(args->dict_globals);
@@ -184,7 +186,6 @@ STATIC void *thread_entry(void *args_in) {
mp_thread_start();
// TODO set more thread-specific state here:
- // mp_pending_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));
diff --git a/py/mpstate.h b/py/mpstate.h
index a0e3d4f14..f5fb5b707 100644
--- a/py/mpstate.h
+++ b/py/mpstate.h
@@ -137,9 +137,6 @@ typedef struct _mp_state_vm_t {
// dictionary with loaded modules (may be exposed as sys.modules)
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
mp_sched_item_t sched_queue[MICROPY_SCHEDULER_DEPTH];
#endif
@@ -266,6 +263,9 @@ typedef struct _mp_state_thread_t {
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
mp_obj_t prof_trace_callback;
bool prof_callback_is_executing;
diff --git a/py/profile.c b/py/profile.c
index e5fb35f0e..054a0f9e6 100644
--- a/py/profile.c
+++ b/py/profile.c
@@ -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;
- if (MP_STATE_VM(mp_pending_exception) != MP_OBJ_NULL) {
+ if (MP_STATE_THREAD(mp_pending_exception) != MP_OBJ_NULL) {
mp_handle_pending(true);
}
return top;
diff --git a/py/runtime.c b/py/runtime.c
index 1ca0702e1..cda26a9cf 100644
--- a/py/runtime.c
+++ b/py/runtime.c
@@ -62,7 +62,7 @@ void mp_init(void) {
qstr_init();
// 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
MP_STATE_VM(sched_state) = MP_SCHED_IDLE;
MP_STATE_VM(sched_idx) = 0;
diff --git a/py/scheduler.c b/py/scheduler.c
index 0671a34a8..0114a7a58 100644
--- a/py/scheduler.c
+++ b/py/scheduler.c
@@ -29,7 +29,7 @@
#include "py/runtime.h"
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 (MP_STATE_VM(sched_state) == MP_SCHED_IDLE) {
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();
// Re-check state is still pending now that we're in the atomic section.
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) {
- MP_STATE_VM(mp_pending_exception) = MP_OBJ_NULL;
+ MP_STATE_THREAD(mp_pending_exception) = MP_OBJ_NULL;
if (!mp_sched_num_pending()) {
MP_STATE_VM(sched_state) = MP_SCHED_IDLE;
}
@@ -115,7 +115,7 @@ void mp_sched_unlock(void) {
assert(MP_STATE_VM(sched_state) < 0);
if (++MP_STATE_VM(sched_state) == 0) {
// 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;
} else {
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
void mp_handle_pending(bool raise_exc) {
- if (MP_STATE_VM(mp_pending_exception) != MP_OBJ_NULL) {
- mp_obj_t obj = MP_STATE_VM(mp_pending_exception);
- 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_THREAD(mp_pending_exception);
+ MP_STATE_THREAD(mp_pending_exception) = MP_OBJ_NULL;
if (raise_exc) {
nlr_raise(obj);
}
diff --git a/py/vm.c b/py/vm.c
index c97070b78..f9a589c9d 100644
--- a/py/vm.c
+++ b/py/vm.c
@@ -1375,9 +1375,9 @@ pending_exception_check:
// Re-check state is still pending now that we're in the atomic section.
if (MP_STATE_VM(sched_state) == MP_SCHED_PENDING) {
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) {
- MP_STATE_VM(mp_pending_exception) = MP_OBJ_NULL;
+ MP_STATE_THREAD(mp_pending_exception) = MP_OBJ_NULL;
if (!mp_sched_num_pending()) {
MP_STATE_VM(sched_state) = MP_SCHED_IDLE;
}
@@ -1391,10 +1391,10 @@ pending_exception_check:
}
#else
// 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();
- mp_obj_t obj = MP_STATE_VM(mp_pending_exception);
- MP_STATE_VM(mp_pending_exception) = MP_OBJ_NULL;
+ mp_obj_t obj = MP_STATE_THREAD(mp_pending_exception);
+ MP_STATE_THREAD(mp_pending_exception) = MP_OBJ_NULL;
RAISE(obj);
}
#endif