|
1 | 1 | #include <stdio.h>
|
| 2 | +#include <stdlib.h> |
2 | 3 | #include <string.h>
|
3 | 4 |
|
4 | 5 | #include "py/obj.h"
|
@@ -224,6 +225,42 @@ STATIC mp_obj_t extra_coverage(void) {
|
224 | 225 | mp_printf(&mp_plat_print, "%p\n", gc_nbytes(NULL));
|
225 | 226 | }
|
226 | 227 |
|
| 228 | + // GC initialisation and allocation stress test, to check the logic behind ALLOC_TABLE_GAP_BYTE |
| 229 | + // (the following test should fail when ALLOC_TABLE_GAP_BYTE=0) |
| 230 | + { |
| 231 | + mp_printf(&mp_plat_print, "# GC part 2\n"); |
| 232 | + |
| 233 | + // check the GC is unlocked and save its state |
| 234 | + assert(MP_STATE_THREAD(gc_lock_depth) == 0); |
| 235 | + mp_state_mem_t mp_state_mem_orig = mp_state_ctx.mem; |
| 236 | + |
| 237 | + // perform the test |
| 238 | + unsigned heap_size = 64 * MICROPY_BYTES_PER_GC_BLOCK; |
| 239 | + for (unsigned j = 0; j < 256 * MP_BYTES_PER_OBJ_WORD; ++j) { |
| 240 | + char *heap = calloc(heap_size, 1); |
| 241 | + gc_init(heap, heap + heap_size); |
| 242 | + |
| 243 | + m_malloc(MICROPY_BYTES_PER_GC_BLOCK); |
| 244 | + void *o = gc_alloc(MICROPY_BYTES_PER_GC_BLOCK, GC_ALLOC_FLAG_HAS_FINALISER); |
| 245 | + ((mp_obj_base_t *)o)->type = NULL; // ensure type is cleared so GC doesn't look for finaliser |
| 246 | + for (unsigned i = 0; i < heap_size / MICROPY_BYTES_PER_GC_BLOCK; ++i) { |
| 247 | + void *p = m_malloc_maybe(MICROPY_BYTES_PER_GC_BLOCK); |
| 248 | + if (!p) { |
| 249 | + break; |
| 250 | + } |
| 251 | + *(void **)p = o; |
| 252 | + o = p; |
| 253 | + } |
| 254 | + gc_collect(); |
| 255 | + free(heap); |
| 256 | + heap_size += MICROPY_BYTES_PER_GC_BLOCK / 16; |
| 257 | + } |
| 258 | + mp_printf(&mp_plat_print, "pass\n"); |
| 259 | + |
| 260 | + // restore the GC state (the original heap) |
| 261 | + mp_state_ctx.mem = mp_state_mem_orig; |
| 262 | + } |
| 263 | + |
227 | 264 | // tracked allocation
|
228 | 265 | {
|
229 | 266 | #define NUM_PTRS (8)
|
|
0 commit comments