From fd8b6bcf5572b342b1e61f4f3737a2a650659166 Mon Sep 17 00:00:00 2001 From: Damien <damien.p.george@gmail.com> Date: Tue, 22 Oct 2013 20:26:36 +0100 Subject: [PATCH] Add gc_free function to force a block to be freed. --- py/gc.c | 35 ++++++++++++++++++++++++----------- py/gc.h | 3 ++- 2 files changed, 26 insertions(+), 12 deletions(-) diff --git a/py/gc.c b/py/gc.c index 48e792266..0c9c56086 100644 --- a/py/gc.c +++ b/py/gc.c @@ -52,7 +52,6 @@ void gc_init(void *start, void *end) { printf(" alloc table at %p, length %u bytes\n", gc_alloc_table_start, gc_alloc_table_byte_len); printf(" pool at %p, length %u blocks = %u words = %u bytes\n", gc_pool_start, gc_pool_block_len, gc_pool_word_len, gc_pool_word_len * BYTES_PER_WORD); */ - printf("GC: %u bytes\n", gc_pool_word_len * BYTES_PER_WORD); } // ATB = allocation table byte @@ -89,13 +88,15 @@ void gc_init(void *start, void *end) { #define PTR_FROM_BLOCK(block) (((block) * BYTES_PER_BLOCK + (machine_uint_t)gc_pool_start)) #define ATB_FROM_BLOCK(bl) ((bl) / BLOCKS_PER_ATB) +#define VERIFY_PTR(ptr) ( \ + (ptr & (BYTES_PER_BLOCK - 1)) == 0 /* must be aligned on a block */ \ + && ptr >= (machine_uint_t)gc_pool_start /* must be above start of pool */ \ + && ptr < (machine_uint_t)gc_pool_end /* must be below end of pool */ \ + ) + #define VERIFY_MARK_AND_PUSH(ptr) \ do { \ - if ( \ - (ptr & (BYTES_PER_BLOCK - 1)) == 0 /* must be aligned on a block */ \ - && ptr >= (machine_uint_t)gc_pool_start /* must be above start of pool */ \ - && ptr < (machine_uint_t)gc_pool_end /* must be below end of pool */ \ - ) { \ + if (VERIFY_PTR(ptr)) { \ machine_uint_t _block = BLOCK_FROM_PTR(ptr); \ if (ATB_GET_KIND(_block) == AT_HEAD) { \ /* an unmarked head, mark it, and push it on gc stack */ \ @@ -283,14 +284,26 @@ found: return (void*)(gc_pool_start + start_block * WORDS_PER_BLOCK); } +// force the freeing of a piece of memory +void gc_free(void *ptr_in) { + machine_uint_t ptr = (machine_uint_t)ptr_in; + + if (VERIFY_PTR(ptr)) { + machine_uint_t block = BLOCK_FROM_PTR(ptr); + if (ATB_GET_KIND(block) == AT_HEAD) { + // free head and all of its tail blocks + do { + ATB_ANY_TO_FREE(block); + block += 1; + } while (ATB_GET_KIND(block) == AT_TAIL); + } + } +} + machine_uint_t gc_nbytes(void *ptr_in) { machine_uint_t ptr = (machine_uint_t)ptr_in; - if ( - (ptr & (BYTES_PER_BLOCK - 1)) == 0 // must be aligned on a block - && ptr >= (machine_uint_t)gc_pool_start // must be above start of pool - && ptr < (machine_uint_t)gc_pool_end // must be below end of pool - ) { + if (VERIFY_PTR(ptr)) { machine_uint_t block = BLOCK_FROM_PTR(ptr); if (ATB_GET_KIND(block) == AT_HEAD) { // work out number of consecutive blocks in the chain starting with this on diff --git a/py/gc.h b/py/gc.h index 4fe87b830..d5b5fcc91 100644 --- a/py/gc.h +++ b/py/gc.h @@ -4,7 +4,8 @@ void gc_collect_root(void **ptrs, machine_uint_t len); void gc_collect_end(); void gc_collect(); void *gc_alloc(machine_uint_t n_bytes); -machine_uint_t gc_nbytes(void *ptr_in); +void gc_free(void *ptr); +machine_uint_t gc_nbytes(void *ptr); void *gc_realloc(void *ptr, machine_uint_t n_bytes); typedef struct _gc_info_t { -- GitLab