|
24 | 24 | * THE SOFTWARE. |
25 | 25 | */ |
26 | 26 |
|
| 27 | +#include <stdio.h> |
27 | 28 | #include <stdint.h> |
28 | 29 | #include <stdlib.h> |
| 30 | +#include <string.h> |
29 | 31 | #include <sys/mman.h> |
30 | 32 |
|
31 | | -#include "mpconfigport.h" |
| 33 | +#include "py/mpstate.h" |
| 34 | +#include "py/gc.h" |
32 | 35 |
|
33 | 36 | #if defined(__OpenBSD__) || defined(__MACH__) |
34 | 37 | #define MAP_ANONYMOUS MAP_ANON |
35 | 38 | #endif |
36 | 39 |
|
| 40 | +// The memory allocated here is not on the GC heap (and it may contain pointers |
| 41 | +// that need to be GC'd) so we must somehow trace this memory. We do it by |
| 42 | +// keeping a linked list of all mmap'd regions, and tracing them explicitly. |
| 43 | + |
| 44 | +typedef struct _mmap_region_t { |
| 45 | + void *ptr; |
| 46 | + size_t len; |
| 47 | + struct _mmap_region_t *next; |
| 48 | +} mmap_region_t; |
| 49 | + |
37 | 50 | void mp_unix_alloc_exec(mp_uint_t min_size, void **ptr, mp_uint_t *size) { |
38 | 51 | // size needs to be a multiple of the page size |
39 | 52 | *size = (min_size + 0xfff) & (~0xfff); |
40 | 53 | *ptr = mmap(NULL, *size, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); |
41 | 54 | if (*ptr == MAP_FAILED) { |
42 | 55 | *ptr = NULL; |
43 | 56 | } |
| 57 | + |
| 58 | + // add new link to the list of mmap'd regions |
| 59 | + mmap_region_t *rg = m_new_obj(mmap_region_t); |
| 60 | + rg->ptr = *ptr; |
| 61 | + rg->len = min_size; |
| 62 | + rg->next = MP_STATE_VM(mmap_region_head); |
| 63 | + MP_STATE_VM(mmap_region_head) = rg; |
44 | 64 | } |
45 | 65 |
|
46 | 66 | void mp_unix_free_exec(void *ptr, mp_uint_t size) { |
47 | 67 | munmap(ptr, size); |
| 68 | + |
| 69 | + // unlink the mmap'd region from the list |
| 70 | + for (mmap_region_t **rg = (mmap_region_t**)&MP_STATE_VM(mmap_region_head); *rg != NULL; *rg = (*rg)->next) { |
| 71 | + if ((*rg)->ptr == ptr) { |
| 72 | + mmap_region_t *next = (*rg)->next; |
| 73 | + m_del_obj(mmap_region_t, *rg); |
| 74 | + *rg = next; |
| 75 | + return; |
| 76 | + } |
| 77 | + } |
| 78 | +} |
| 79 | + |
| 80 | +void mp_unix_mark_exec(void) { |
| 81 | + for (mmap_region_t *rg = MP_STATE_VM(mmap_region_head); rg != NULL; rg = rg->next) { |
| 82 | + gc_collect_root(rg->ptr, rg->len / sizeof(mp_uint_t)); |
| 83 | + } |
48 | 84 | } |
0 commit comments