aboutsummaryrefslogtreecommitdiff
path: root/py/gc.c
diff options
context:
space:
mode:
authorLaurens Valk <laurens@pybricks.com>2021-10-26 10:47:04 +0200
committerDamien George <damien@micropython.org>2021-11-01 15:39:37 +1100
commitfe120484b67bdc114dbbc2b9bd913fab98c82778 (patch)
tree8e4ed6f1158b2b8c12b48b991c0298cb8065f75a /py/gc.c
parent693b927687c3ac18726a5eb7b64127fc347a3c41 (diff)
py/gc: Add hook to run code during time consuming GC operations.
This makes it possible for cooperative multitasking systems to keep running event loops during garbage collector operations. For example, this can be used to ensure that a motor control loop runs approximately each 5 ms. Without this hook, the loop time can jump to about 15 ms. Addresses #3475. Signed-off-by: Laurens Valk <laurens@pybricks.com>
Diffstat (limited to 'py/gc.c')
-rw-r--r--py/gc.c5
1 files changed, 5 insertions, 0 deletions
diff --git a/py/gc.c b/py/gc.c
index 8284c435b..a01d81abd 100644
--- a/py/gc.c
+++ b/py/gc.c
@@ -213,6 +213,7 @@ STATIC void gc_mark_subtree(size_t block) {
// Start with the block passed in the argument.
size_t sp = 0;
for (;;) {
+ MICROPY_GC_HOOK_LOOP
// work out number of consecutive blocks in the chain starting with this one
size_t n_blocks = 0;
do {
@@ -222,6 +223,7 @@ STATIC void gc_mark_subtree(size_t block) {
// check this block's children
void **ptrs = (void **)PTR_FROM_BLOCK(block);
for (size_t i = n_blocks * BYTES_PER_BLOCK / sizeof(void *); i > 0; i--, ptrs++) {
+ MICROPY_GC_HOOK_LOOP
void *ptr = *ptrs;
if (VERIFY_PTR(ptr)) {
// Mark and push this pointer
@@ -255,6 +257,7 @@ STATIC void gc_deal_with_stack_overflow(void) {
// scan entire memory looking for blocks which have been marked but not their children
for (size_t block = 0; block < MP_STATE_MEM(gc_alloc_table_byte_len) * BLOCKS_PER_ATB; block++) {
+ MICROPY_GC_HOOK_LOOP
// trace (again) if mark bit set
if (ATB_GET_KIND(block) == AT_MARK) {
gc_mark_subtree(block);
@@ -270,6 +273,7 @@ STATIC void gc_sweep(void) {
// free unmarked heads and their tails
int free_tail = 0;
for (size_t block = 0; block < MP_STATE_MEM(gc_alloc_table_byte_len) * BLOCKS_PER_ATB; block++) {
+ MICROPY_GC_HOOK_LOOP
switch (ATB_GET_KIND(block)) {
case AT_HEAD:
#if MICROPY_ENABLE_FINALISER
@@ -354,6 +358,7 @@ static void *gc_get_ptr(void **ptrs, int i) {
void gc_collect_root(void **ptrs, size_t len) {
for (size_t i = 0; i < len; i++) {
+ MICROPY_GC_HOOK_LOOP
void *ptr = gc_get_ptr(ptrs, i);
if (VERIFY_PTR(ptr)) {
size_t block = BLOCK_FROM_PTR(ptr);