Skip to content

Commit fe12048

Browse files
laurensvalkdpgeorge
authored andcommitted
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 micropython#3475. Signed-off-by: Laurens Valk <[email protected]>
1 parent 693b927 commit fe12048

File tree

2 files changed

+10
-0
lines changed

2 files changed

+10
-0
lines changed

py/gc.c

+5
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,7 @@ STATIC void gc_mark_subtree(size_t block) {
213213
// Start with the block passed in the argument.
214214
size_t sp = 0;
215215
for (;;) {
216+
MICROPY_GC_HOOK_LOOP
216217
// work out number of consecutive blocks in the chain starting with this one
217218
size_t n_blocks = 0;
218219
do {
@@ -222,6 +223,7 @@ STATIC void gc_mark_subtree(size_t block) {
222223
// check this block's children
223224
void **ptrs = (void **)PTR_FROM_BLOCK(block);
224225
for (size_t i = n_blocks * BYTES_PER_BLOCK / sizeof(void *); i > 0; i--, ptrs++) {
226+
MICROPY_GC_HOOK_LOOP
225227
void *ptr = *ptrs;
226228
if (VERIFY_PTR(ptr)) {
227229
// Mark and push this pointer
@@ -255,6 +257,7 @@ STATIC void gc_deal_with_stack_overflow(void) {
255257

256258
// scan entire memory looking for blocks which have been marked but not their children
257259
for (size_t block = 0; block < MP_STATE_MEM(gc_alloc_table_byte_len) * BLOCKS_PER_ATB; block++) {
260+
MICROPY_GC_HOOK_LOOP
258261
// trace (again) if mark bit set
259262
if (ATB_GET_KIND(block) == AT_MARK) {
260263
gc_mark_subtree(block);
@@ -270,6 +273,7 @@ STATIC void gc_sweep(void) {
270273
// free unmarked heads and their tails
271274
int free_tail = 0;
272275
for (size_t block = 0; block < MP_STATE_MEM(gc_alloc_table_byte_len) * BLOCKS_PER_ATB; block++) {
276+
MICROPY_GC_HOOK_LOOP
273277
switch (ATB_GET_KIND(block)) {
274278
case AT_HEAD:
275279
#if MICROPY_ENABLE_FINALISER
@@ -354,6 +358,7 @@ static void *gc_get_ptr(void **ptrs, int i) {
354358

355359
void gc_collect_root(void **ptrs, size_t len) {
356360
for (size_t i = 0; i < len; i++) {
361+
MICROPY_GC_HOOK_LOOP
357362
void *ptr = gc_get_ptr(ptrs, i);
358363
if (VERIFY_PTR(ptr)) {
359364
size_t block = BLOCK_FROM_PTR(ptr);

py/mpconfig.h

+5
Original file line numberDiff line numberDiff line change
@@ -602,6 +602,11 @@
602602
#define MICROPY_ENABLE_GC (0)
603603
#endif
604604

605+
// Hook to run code during time consuming garbage collector operations
606+
#ifndef MICROPY_GC_HOOK_LOOP
607+
#define MICROPY_GC_HOOK_LOOP
608+
#endif
609+
605610
// Whether to enable finalisers in the garbage collector (ie call __del__)
606611
#ifndef MICROPY_ENABLE_FINALISER
607612
#define MICROPY_ENABLE_FINALISER (MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_EXTRA_FEATURES)

0 commit comments

Comments
 (0)