summaryrefslogtreecommitdiffstatshomepage
path: root/py/mpstate.h
diff options
context:
space:
mode:
authorAngus Gratton <angus@redyak.com.au>2024-12-04 10:58:06 +1100
committerDamien George <damien@micropython.org>2025-02-03 15:02:02 +1100
commit40e1c111e17864044190596dff6d32955d11280c (patch)
tree55eb42d4b6a88feedecbc0009ae4a8dbd57faa31 /py/mpstate.h
parent8a2ff2ca7366f605dd55c93f6b393552b365cd10 (diff)
downloadmicropython-40e1c111e17864044190596dff6d32955d11280c.tar.gz
micropython-40e1c111e17864044190596dff6d32955d11280c.zip
py/gc: Allow gc_free from inside a gc_sweep finalizer.
Do this by tracking being inside gc collection with a separate flag, GC_COLLECT_FLAG. In gc_free(), ignore this flag when determining if the heap is locked. * For finalisers calling gc_free() when heap is otherwise unlocked, this allows memory to be immediately freed (potentially avoiding a MemoryError). * Hard IRQs still can't call gc_free(), as heap will be locked via gc_lock(). * If finalisers are disabled then all of this code can be compiled out to save some code size. Signed-off-by: Angus Gratton <angus@redyak.com.au>
Diffstat (limited to 'py/mpstate.h')
-rw-r--r--py/mpstate.h13
1 files changed, 13 insertions, 0 deletions
diff --git a/py/mpstate.h b/py/mpstate.h
index 54eca596da..51f290b55b 100644
--- a/py/mpstate.h
+++ b/py/mpstate.h
@@ -77,6 +77,18 @@ typedef struct _mp_sched_item_t {
mp_obj_t arg;
} mp_sched_item_t;
+// gc_lock_depth field is a combination of the GC_COLLECT_FLAG
+// bit and a lock depth shifted GC_LOCK_DEPTH_SHIFT bits left.
+#if MICROPY_ENABLE_FINALISER
+#define GC_COLLECT_FLAG 1
+#define GC_LOCK_DEPTH_SHIFT 1
+#else
+// If finalisers are disabled then this check doesn't matter, as gc_lock()
+// is called anywhere else that heap can't be changed. So save some code size.
+#define GC_COLLECT_FLAG 0
+#define GC_LOCK_DEPTH_SHIFT 0
+#endif
+
// This structure holds information about a single contiguous area of
// memory reserved for the memory manager.
typedef struct _mp_state_mem_area_t {
@@ -268,6 +280,7 @@ typedef struct _mp_state_thread_t {
#endif
// Locking of the GC is done per thread.
+ // See GC_LOCK_DEPTH_SHIFT for an explanation of this field.
uint16_t gc_lock_depth;
////////////////////////////////////////////////////////////