diff --git a/ports/unix/coverage.c b/ports/unix/coverage.c index 2b65b47fc5..644e6927a8 100644 --- a/ports/unix/coverage.c +++ b/ports/unix/coverage.c @@ -292,6 +292,13 @@ static mp_obj_t extra_coverage(void) { gc_collect(); } + // resize one of the blocks + void *before = ptrs[1]; + ptrs[1] = FLIP_POINTER(m_tracked_realloc(FLIP_POINTER(ptrs[1]), 2 * NUM_BYTES)); + void *after = ptrs[1]; + bool location_changed = before != after; + mp_printf(&mp_plat_print, "%d\n", location_changed); + // check the memory blocks have the correct content for (size_t i = 0; i < NUM_PTRS; ++i) { bool correct_contents = true; diff --git a/py/malloc.c b/py/malloc.c index f557ade44f..eb564cc516 100644 --- a/py/malloc.c +++ b/py/malloc.c @@ -263,6 +263,49 @@ void *m_tracked_calloc(size_t nmemb, size_t size) { return &node->data[0]; } +void *m_tracked_realloc(void *ptr_in, size_t n_bytes) { + // check for pure allocation + if (ptr_in == NULL) { + return m_tracked_calloc(1, n_bytes); + } + // check for pure free + if (n_bytes == 0) { + m_tracked_free(ptr_in); + return NULL; + } + m_tracked_node_t *node = (m_tracked_node_t *)((uint8_t *)ptr_in - sizeof(m_tracked_node_t)); + #if MICROPY_MALLOC_USES_ALLOCATED_SIZE || MICROPY_DEBUG_VERBOSE + size_t prev_bytes; + #if MICROPY_TRACKED_ALLOC_STORE_SIZE + prev_bytes = node->size; + #else + prev_bytes = gc_nbytes(node); + #endif + #if MICROPY_DEBUG_VERBOSE + size_t nb; + size_t n = m_tracked_count_links(&nb); + DEBUG_printf("m_tracked_realloc(%p, [%p, %p], pbytes=%u, nbytes=%u, links=%u;%u)\n", node, node->prev, node->next, (int)prev_bytes, (int)n_bytes, (int)n, (int)nb); + #endif + #endif + node = m_realloc(node, + #if MICROPY_MALLOC_USES_ALLOCATED_SIZE + sizeof(m_tracked_node_t) + prev_bytes, + #endif + sizeof(m_tracked_node_t) + n_bytes + ); + if (node == NULL) { + node->prev->next = node->next; + node->next->prev = node->prev; + return NULL; + } + #if MICROPY_TRACKED_ALLOC_STORE_SIZE + node->size = n_bytes; + #endif + node->prev->next = node; + node->next->prev = node; + return &node->data[0]; +} + void m_tracked_free(void *ptr_in) { if (ptr_in == NULL) { return; diff --git a/py/misc.h b/py/misc.h index 96b13c151a..3b52945be7 100644 --- a/py/misc.h +++ b/py/misc.h @@ -111,6 +111,7 @@ NORETURN void m_malloc_fail(size_t num_bytes); // These alloc/free functions track the pointers in a linked list so the GC does not reclaim // them. They can be used by code that requires traditional C malloc/free semantics. void *m_tracked_calloc(size_t nmemb, size_t size); +void *m_tracked_realloc(void *ptr_in, size_t n_bytes); void m_tracked_free(void *ptr_in); #endif diff --git a/tests/ports/unix/extra_coverage.py.exp b/tests/ports/unix/extra_coverage.py.exp index 176db8e9f8..91aa33080b 100644 --- a/tests/ports/unix/extra_coverage.py.exp +++ b/tests/ports/unix/extra_coverage.py.exp @@ -29,6 +29,7 @@ m_tracked_head = 0 5 1 6 1 7 1 +1 0 1 1 1 2 1 diff --git a/tests/run-tests.py b/tests/run-tests.py index f9f8413077..c0ab1dc932 100755 --- a/tests/run-tests.py +++ b/tests/run-tests.py @@ -937,6 +937,10 @@ the last matching regex is used: run-tests.py -i async - exclude all, then include tests containing "async" anywhere run-tests.py -e '/big.+int' - include all, then exclude by regex run-tests.py -e async -i async_foo - include all, exclude async, yet still include async_foo + +For tests that use cpython, unix micropython and mpy-cross, the default executables +vcan be overridden with the environment variables MICROPY_CPYTHON3, MICROPY_MICROPYTHON and +MICROPY_MPYCROSS respectively. """, ) cmd_parser.add_argument("--target", default="unix", help="the target platform")