summaryrefslogtreecommitdiffstatshomepage
path: root/py/gc.c
diff options
context:
space:
mode:
Diffstat (limited to 'py/gc.c')
-rw-r--r--py/gc.c45
1 files changed, 22 insertions, 23 deletions
diff --git a/py/gc.c b/py/gc.c
index 53a0d9da4a..88adf2045e 100644
--- a/py/gc.c
+++ b/py/gc.c
@@ -150,7 +150,7 @@ void gc_init(void *start, void *end) {
MP_STATE_MEM(gc_last_free_atb_index) = 0;
// unlock the GC
- MP_STATE_MEM(gc_lock_depth) = 0;
+ MP_STATE_THREAD(gc_lock_depth) = 0;
// allow auto collection
MP_STATE_MEM(gc_auto_collect_enabled) = 1;
@@ -174,19 +174,20 @@ void gc_init(void *start, void *end) {
}
void gc_lock(void) {
- GC_ENTER();
- MP_STATE_MEM(gc_lock_depth)++;
- GC_EXIT();
+ // This does not need to be atomic or have the GC mutex because:
+ // - each thread has its own gc_lock_depth so there are no races between threads;
+ // - a hard interrupt will only change gc_lock_depth during its execution, and
+ // upon return will restore the value of gc_lock_depth.
+ MP_STATE_THREAD(gc_lock_depth)++;
}
void gc_unlock(void) {
- GC_ENTER();
- MP_STATE_MEM(gc_lock_depth)--;
- GC_EXIT();
+ // This does not need to be atomic, See comment above in gc_lock.
+ MP_STATE_THREAD(gc_lock_depth)--;
}
bool gc_is_locked(void) {
- return MP_STATE_MEM(gc_lock_depth) != 0;
+ return MP_STATE_THREAD(gc_lock_depth) != 0;
}
// ptr should be of type void*
@@ -320,7 +321,7 @@ STATIC void gc_sweep(void) {
void gc_collect_start(void) {
GC_ENTER();
- MP_STATE_MEM(gc_lock_depth)++;
+ MP_STATE_THREAD(gc_lock_depth)++;
#if MICROPY_GC_ALLOC_THRESHOLD
MP_STATE_MEM(gc_alloc_amount) = 0;
#endif
@@ -360,13 +361,13 @@ void gc_collect_end(void) {
gc_deal_with_stack_overflow();
gc_sweep();
MP_STATE_MEM(gc_last_free_atb_index) = 0;
- MP_STATE_MEM(gc_lock_depth)--;
+ MP_STATE_THREAD(gc_lock_depth)--;
GC_EXIT();
}
void gc_sweep_all(void) {
GC_ENTER();
- MP_STATE_MEM(gc_lock_depth)++;
+ MP_STATE_THREAD(gc_lock_depth)++;
MP_STATE_MEM(gc_stack_overflow) = 0;
gc_collect_end();
}
@@ -445,14 +446,13 @@ void *gc_alloc(size_t n_bytes, unsigned int alloc_flags) {
return NULL;
}
- GC_ENTER();
-
// check if GC is locked
- if (MP_STATE_MEM(gc_lock_depth) > 0) {
- GC_EXIT();
+ if (MP_STATE_THREAD(gc_lock_depth) > 0) {
return NULL;
}
+ GC_ENTER();
+
size_t i;
size_t end_block;
size_t start_block;
@@ -573,13 +573,13 @@ void *gc_alloc_with_finaliser(mp_uint_t n_bytes) {
// force the freeing of a piece of memory
// TODO: freeing here does not call finaliser
void gc_free(void *ptr) {
- GC_ENTER();
- if (MP_STATE_MEM(gc_lock_depth) > 0) {
+ if (MP_STATE_THREAD(gc_lock_depth) > 0) {
// TODO how to deal with this error?
- GC_EXIT();
return;
}
+ GC_ENTER();
+
DEBUG_printf("gc_free(%p)\n", ptr);
if (ptr == NULL) {
@@ -674,15 +674,14 @@ void *gc_realloc(void *ptr_in, size_t n_bytes, bool allow_move) {
return NULL;
}
+ if (MP_STATE_THREAD(gc_lock_depth) > 0) {
+ return NULL;
+ }
+
void *ptr = ptr_in;
GC_ENTER();
- if (MP_STATE_MEM(gc_lock_depth) > 0) {
- GC_EXIT();
- return NULL;
- }
-
// get the GC block number corresponding to this pointer
assert(VERIFY_PTR(ptr));
size_t block = BLOCK_FROM_PTR(ptr);