Skip to content
Snippets Groups Projects
Commit 05fe66f6 authored by Damien George's avatar Damien George
Browse files

py: Move locals/globals dicts to the thread-specific state.

Each threads needs to have its own private references to its current
locals/globals dicts, otherwise functions running within different
contexts (eg imported from different files) can behave very strangely.
parent fe866d99
No related branches found
No related tags found
No related merge requests found
...@@ -143,6 +143,8 @@ STATIC mp_obj_t mod_thread_stack_size(size_t n_args, const mp_obj_t *args) { ...@@ -143,6 +143,8 @@ STATIC mp_obj_t mod_thread_stack_size(size_t n_args, const mp_obj_t *args) {
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_thread_stack_size_obj, 0, 1, mod_thread_stack_size); STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_thread_stack_size_obj, 0, 1, mod_thread_stack_size);
typedef struct _thread_entry_args_t { typedef struct _thread_entry_args_t {
mp_obj_dict_t *dict_locals;
mp_obj_dict_t *dict_globals;
size_t stack_size; size_t stack_size;
mp_obj_t fun; mp_obj_t fun;
size_t n_args; size_t n_args;
...@@ -161,6 +163,10 @@ STATIC void *thread_entry(void *args_in) { ...@@ -161,6 +163,10 @@ STATIC void *thread_entry(void *args_in) {
mp_stack_set_top(&ts + 1); // need to include ts in root-pointer scan mp_stack_set_top(&ts + 1); // need to include ts in root-pointer scan
mp_stack_set_limit(args->stack_size); mp_stack_set_limit(args->stack_size);
// set locals and globals from the calling context
mp_locals_set(args->dict_locals);
mp_globals_set(args->dict_globals);
MP_THREAD_GIL_ENTER(); MP_THREAD_GIL_ENTER();
// signal that we are set up and running // signal that we are set up and running
...@@ -169,7 +175,6 @@ STATIC void *thread_entry(void *args_in) { ...@@ -169,7 +175,6 @@ STATIC void *thread_entry(void *args_in) {
// TODO set more thread-specific state here: // TODO set more thread-specific state here:
// mp_pending_exception? (root pointer) // mp_pending_exception? (root pointer)
// cur_exception (root pointer) // cur_exception (root pointer)
// dict_locals? (root pointer) uPy doesn't make a new locals dict for functions, just for classes, so it's different to CPy
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));
...@@ -240,6 +245,10 @@ STATIC mp_obj_t mod_thread_start_new_thread(size_t n_args, const mp_obj_t *args) ...@@ -240,6 +245,10 @@ STATIC mp_obj_t mod_thread_start_new_thread(size_t n_args, const mp_obj_t *args)
th_args->n_args = pos_args_len; th_args->n_args = pos_args_len;
memcpy(th_args->args, pos_args_items, pos_args_len * sizeof(mp_obj_t)); memcpy(th_args->args, pos_args_items, pos_args_len * sizeof(mp_obj_t));
// pass our locals and globals into the new thread
th_args->dict_locals = mp_locals_get();
th_args->dict_globals = mp_globals_get();
// set the stack size to use // set the stack size to use
th_args->stack_size = thread_stack_size; th_args->stack_size = thread_stack_size;
......
...@@ -196,11 +196,13 @@ typedef struct _mp_state_vm_t { ...@@ -196,11 +196,13 @@ typedef struct _mp_state_vm_t {
// This structure holds state that is specific to a given thread. // This structure holds state that is specific to a given thread.
// Everything in this structure is scanned for root pointers. // Everything in this structure is scanned for root pointers.
typedef struct _mp_state_thread_t { typedef struct _mp_state_thread_t {
mp_obj_dict_t *dict_locals;
mp_obj_dict_t *dict_globals;
// Note: nlr asm code has the offset of this hard-coded // Note: nlr asm code has the offset of this hard-coded
nlr_buf_t *nlr_top; // ROOT POINTER nlr_buf_t *nlr_top; // ROOT POINTER
// Stack top at the start of program // Stack top at the start of program
// Note: this entry is used to locate the end of the root pointer section.
char *stack_top; char *stack_top;
#if MICROPY_STACK_CHECK #if MICROPY_STACK_CHECK
...@@ -208,15 +210,11 @@ typedef struct _mp_state_thread_t { ...@@ -208,15 +210,11 @@ typedef struct _mp_state_thread_t {
#endif #endif
} mp_state_thread_t; } mp_state_thread_t;
// This structure combines the above 3 structures, and adds the local // This structure combines the above 3 structures.
// and global dicts. // The order of the entries are important for root pointer scanning in the GC to work.
// Note: if this structure changes then revisit all nlr asm code since they // Note: if this structure changes then revisit all nlr asm code since they
// have the offset of nlr_top hard-coded. // have the offset of nlr_top hard-coded.
typedef struct _mp_state_ctx_t { typedef struct _mp_state_ctx_t {
// these must come first for root pointer scanning in GC to work
mp_obj_dict_t *dict_locals;
mp_obj_dict_t *dict_globals;
// these must come next in this order for root pointer scanning in GC to work
mp_state_thread_t thread; mp_state_thread_t thread;
mp_state_vm_t vm; mp_state_vm_t vm;
mp_state_mem_t mem; mp_state_mem_t mem;
...@@ -224,7 +222,7 @@ typedef struct _mp_state_ctx_t { ...@@ -224,7 +222,7 @@ typedef struct _mp_state_ctx_t {
extern mp_state_ctx_t mp_state_ctx; extern mp_state_ctx_t mp_state_ctx;
#define MP_STATE_CTX(x) (mp_state_ctx.x) #define MP_STATE_CTX(x) MP_STATE_THREAD(x)
#define MP_STATE_VM(x) (mp_state_ctx.vm.x) #define MP_STATE_VM(x) (mp_state_ctx.vm.x)
#define MP_STATE_MEM(x) (mp_state_ctx.mem.x) #define MP_STATE_MEM(x) (mp_state_ctx.mem.x)
......
...@@ -44,7 +44,7 @@ ...@@ -44,7 +44,7 @@
#endif #endif
// offset of nlr_top within mp_state_thread_t structure // offset of nlr_top within mp_state_thread_t structure
#define NLR_TOP_TH_OFF (0) #define NLR_TOP_TH_OFF (2 * 8)
#if defined(_WIN32) || defined(__CYGWIN__) #if defined(_WIN32) || defined(__CYGWIN__)
#define NLR_OS_WINDOWS #define NLR_OS_WINDOWS
......
...@@ -52,7 +52,7 @@ ...@@ -52,7 +52,7 @@
#endif #endif
// offset of nlr_top within mp_state_thread_t structure // offset of nlr_top within mp_state_thread_t structure
#define NLR_TOP_TH_OFF (0) #define NLR_TOP_TH_OFF (2 * 4)
.file "nlr.s" .file "nlr.s"
.text .text
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment