summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--py/mpconfig.h6
-rw-r--r--py/vm.c20
2 files changed, 23 insertions, 3 deletions
diff --git a/py/mpconfig.h b/py/mpconfig.h
index 093625a461..1b47d822f1 100644
--- a/py/mpconfig.h
+++ b/py/mpconfig.h
@@ -949,6 +949,12 @@ typedef double mp_float_t;
#define MICROPY_PY_THREAD_GIL (MICROPY_PY_THREAD)
#endif
+// Number of VM jump-loops to do before releasing the GIL.
+// Set this to 0 to disable the divisor.
+#ifndef MICROPY_PY_THREAD_GIL_VM_DIVISOR
+#define MICROPY_PY_THREAD_GIL_VM_DIVISOR (32)
+#endif
+
// Extended modules
#ifndef MICROPY_PY_UCTYPES
diff --git a/py/vm.c b/py/vm.c
index f4cfa2cd6f..fb59bf9cff 100644
--- a/py/vm.c
+++ b/py/vm.c
@@ -169,6 +169,12 @@ run_code_state: ;
volatile bool currently_in_except_block = MP_TAGPTR_TAG0(code_state->exc_sp); // 0 or 1, to detect nested exceptions
mp_exc_stack_t *volatile exc_sp = MP_TAGPTR_PTR(code_state->exc_sp); // stack grows up, exc_sp points to top of stack
+ #if MICROPY_PY_THREAD_GIL && MICROPY_PY_THREAD_GIL_VM_DIVISOR
+ // This needs to be volatile and outside the VM loop so it persists across handling
+ // of any exceptions. Otherwise it's possible that the VM never gives up the GIL.
+ volatile int gil_divisor = MICROPY_PY_THREAD_GIL_VM_DIVISOR;
+ #endif
+
// outer exception handling loop
for (;;) {
nlr_buf_t nlr;
@@ -1243,9 +1249,17 @@ pending_exception_check:
RAISE(obj);
}
- // TODO make GIL release more efficient
- MP_THREAD_GIL_EXIT();
- MP_THREAD_GIL_ENTER();
+ #if MICROPY_PY_THREAD_GIL
+ #if MICROPY_PY_THREAD_GIL_VM_DIVISOR
+ if (--gil_divisor == 0) {
+ gil_divisor = MICROPY_PY_THREAD_GIL_VM_DIVISOR;
+ #else
+ {
+ #endif
+ MP_THREAD_GIL_EXIT();
+ MP_THREAD_GIL_ENTER();
+ }
+ #endif
} // for loop