Skip to content

Commit 443e018

Browse files
committed
py: Improve GC locking/unlocking, and make it part of the API.
1 parent ff5639f commit 443e018

2 files changed

Lines changed: 32 additions & 15 deletions

File tree

py/gc.c

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ STATIC machine_uint_t *gc_pool_end;
3737
STATIC int gc_stack_overflow;
3838
STATIC machine_uint_t gc_stack[STACK_SIZE];
3939
STATIC machine_uint_t *gc_sp;
40-
STATIC bool gc_lock;
40+
STATIC machine_uint_t gc_lock_depth;
4141

4242
// ATB = allocation table byte
4343
// 0b00 = FREE -- free block
@@ -130,7 +130,7 @@ void gc_init(void *start, void *end) {
130130
}
131131

132132
// unlock the GC
133-
gc_lock = false;
133+
gc_lock_depth = 0;
134134

135135
DEBUG_printf("GC layout:\n");
136136
DEBUG_printf(" alloc table at %p, length " UINT_FMT " bytes, " UINT_FMT " blocks\n", gc_alloc_table_start, gc_alloc_table_byte_len, gc_alloc_table_byte_len * BLOCKS_PER_ATB);
@@ -140,6 +140,14 @@ void gc_init(void *start, void *end) {
140140
DEBUG_printf(" pool at %p, length " UINT_FMT " bytes, " UINT_FMT " blocks\n", gc_pool_start, gc_pool_block_len * BYTES_PER_BLOCK, gc_pool_block_len);
141141
}
142142

143+
void gc_lock(void) {
144+
gc_lock_depth++;
145+
}
146+
147+
void gc_unlock(void) {
148+
gc_lock_depth--;
149+
}
150+
143151
#define VERIFY_PTR(ptr) ( \
144152
(ptr & (BYTES_PER_BLOCK - 1)) == 0 /* must be aligned on a block */ \
145153
&& ptr >= (machine_uint_t)gc_pool_start /* must be above start of pool */ \
@@ -238,7 +246,7 @@ STATIC void gc_sweep(void) {
238246
}
239247

240248
void gc_collect_start(void) {
241-
gc_lock = true;
249+
gc_lock();
242250
gc_stack_overflow = 0;
243251
gc_sp = gc_stack;
244252
}
@@ -254,7 +262,7 @@ void gc_collect_root(void **ptrs, machine_uint_t len) {
254262
void gc_collect_end(void) {
255263
gc_deal_with_stack_overflow();
256264
gc_sweep();
257-
gc_lock = false;
265+
gc_unlock();
258266
}
259267

260268
void gc_info(gc_info_t *info) {
@@ -306,8 +314,9 @@ void *gc_alloc(machine_uint_t n_bytes, bool has_finaliser) {
306314
machine_uint_t n_blocks = ((n_bytes + BYTES_PER_BLOCK - 1) & (~(BYTES_PER_BLOCK - 1))) / BYTES_PER_BLOCK;
307315
DEBUG_printf("gc_alloc(" UINT_FMT " bytes -> " UINT_FMT " blocks)\n", n_bytes, n_blocks);
308316

309-
if (gc_lock) {
310-
// TODO
317+
// check if GC is locked
318+
if (gc_lock_depth > 0) {
319+
return NULL;
311320
}
312321

313322
// check for 0 allocation
@@ -382,8 +391,9 @@ void *gc_alloc_with_finaliser(machine_uint_t n_bytes) {
382391

383392
// force the freeing of a piece of memory
384393
void gc_free(void *ptr_in) {
385-
if (gc_lock) {
386-
// TODO
394+
if (gc_lock_depth > 0) {
395+
// TODO how to deal with this error?
396+
return;
387397
}
388398

389399
machine_uint_t ptr = (machine_uint_t)ptr_in;
@@ -420,7 +430,7 @@ machine_uint_t gc_nbytes(void *ptr_in) {
420430
}
421431

422432
#if 0
423-
// use this realloc for now, one below is broken
433+
// old, simple realloc that didn't expand memory in place
424434
void *gc_realloc(void *ptr, machine_uint_t n_bytes) {
425435
machine_uint_t n_existing = gc_nbytes(ptr);
426436
if (n_bytes <= n_existing) {
@@ -436,10 +446,11 @@ void *gc_realloc(void *ptr, machine_uint_t n_bytes) {
436446
return ptr2;
437447
}
438448
}
439-
#else
449+
#endif
450+
440451
void *gc_realloc(void *ptr_in, machine_uint_t n_bytes) {
441-
if (gc_lock) {
442-
// TODO
452+
if (gc_lock_depth > 0) {
453+
return NULL;
443454
}
444455

445456
void *ptr_out = NULL;
@@ -516,8 +527,6 @@ void *gc_realloc(void *ptr_in, machine_uint_t n_bytes) {
516527
return ptr_out;
517528
}
518529

519-
#endif
520-
521530
void gc_dump_info() {
522531
gc_info_t info;
523532
gc_info(&info);

py/gc.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,16 @@
11
void gc_init(void *start, void *end);
2+
3+
// These lock/unlock functions can be nested.
4+
// They can be used to prevent the GC from allocating/freeing.
5+
void gc_lock(void);
6+
void gc_unlock(void);
7+
8+
// A given port must implement gc_collect by using the other collect functions.
9+
void gc_collect(void);
210
void gc_collect_start(void);
311
void gc_collect_root(void **ptrs, machine_uint_t len);
412
void gc_collect_end(void);
5-
void gc_collect(void);
13+
614
void *gc_alloc(machine_uint_t n_bytes, bool has_finaliser);
715
void gc_free(void *ptr);
816
machine_uint_t gc_nbytes(void *ptr);

0 commit comments

Comments
 (0)