Skip to content

Commit a975ef4

Browse files
authored
Merge pull request #3695 from cwalther/movable
Add movable supervisor allocations
2 parents 299b6ef + d6f8a43 commit a975ef4

File tree

20 files changed

+363
-231
lines changed

20 files changed

+363
-231
lines changed

main.c

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -123,15 +123,15 @@ void start_mp(supervisor_allocation* heap) {
123123
// to recover from limit hit. (Limit is measured in bytes.)
124124
mp_stack_ctrl_init();
125125

126-
if (stack_alloc != NULL) {
127-
mp_stack_set_limit(stack_alloc->length - 1024);
126+
if (stack_get_bottom() != NULL) {
127+
mp_stack_set_limit(stack_get_length() - 1024);
128128
}
129129

130130

131131
#if MICROPY_MAX_STACK_USAGE
132132
// _ezero (same as _ebss) is an int, so start 4 bytes above it.
133-
if (stack_alloc != NULL) {
134-
mp_stack_set_bottom(stack_alloc->ptr);
133+
if (stack_get_bottom() != NULL) {
134+
mp_stack_set_bottom(stack_get_bottom());
135135
mp_stack_fill_with_sentinel();
136136
}
137137
#endif
@@ -148,7 +148,7 @@ void start_mp(supervisor_allocation* heap) {
148148
#endif
149149

150150
#if MICROPY_ENABLE_GC
151-
gc_init(heap->ptr, heap->ptr + heap->length / 4);
151+
gc_init(heap->ptr, heap->ptr + get_allocation_length(heap) / 4);
152152
#endif
153153
mp_init();
154154
mp_obj_list_init(mp_sys_path, 0);
@@ -451,9 +451,6 @@ int __attribute__((used)) main(void) {
451451
// initialise the cpu and peripherals
452452
safe_mode_t safe_mode = port_init();
453453

454-
// Init memory after the port in case the port needs to set aside memory.
455-
memory_init();
456-
457454
// Turn on LEDs
458455
init_status_leds();
459456
rgb_led_status_init();

ports/atmel-samd/supervisor/port.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -390,8 +390,8 @@ void reset_cpu(void) {
390390
reset();
391391
}
392392

393-
supervisor_allocation* port_fixed_stack(void) {
394-
return NULL;
393+
bool port_has_fixed_stack(void) {
394+
return false;
395395
}
396396

397397
uint32_t *port_stack_get_limit(void) {

ports/cxd56/supervisor/port.c

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -98,12 +98,8 @@ void reset_to_bootloader(void) {
9898
}
9999
}
100100

101-
supervisor_allocation _fixed_stack;
102-
103-
supervisor_allocation* port_fixed_stack(void) {
104-
_fixed_stack.ptr = port_stack_get_limit();
105-
_fixed_stack.length = (port_stack_get_top() - port_stack_get_limit()) * sizeof(uint32_t);
106-
return &_fixed_stack;
101+
bool port_has_fixed_stack(void) {
102+
return true;
107103
}
108104

109105
uint32_t *port_stack_get_limit(void) {

ports/esp32s2/supervisor/port.c

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -193,12 +193,8 @@ uint32_t *port_stack_get_top(void) {
193193
return port_stack_get_limit() + ESP_TASK_MAIN_STACK / (sizeof(uint32_t) / sizeof(StackType_t));
194194
}
195195

196-
supervisor_allocation _fixed_stack;
197-
198-
supervisor_allocation* port_fixed_stack(void) {
199-
_fixed_stack.ptr = port_stack_get_limit();
200-
_fixed_stack.length = (port_stack_get_top() - port_stack_get_limit()) * sizeof(uint32_t);
201-
return &_fixed_stack;
196+
bool port_has_fixed_stack(void) {
197+
return true;
202198
}
203199

204200
// Place the word to save just after our BSS section that gets blanked.

ports/litex/supervisor/port.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -98,8 +98,8 @@ void reset_cpu(void) {
9898
for(;;) {}
9999
}
100100

101-
supervisor_allocation* port_fixed_stack(void) {
102-
return NULL;
101+
bool port_has_fixed_stack(void) {
102+
return false;
103103
}
104104

105105
uint32_t *port_heap_get_bottom(void) {

ports/mimxrt10xx/supervisor/port.c

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -334,11 +334,8 @@ uint32_t *port_stack_get_top(void) {
334334
return &_ld_stack_top;
335335
}
336336

337-
supervisor_allocation _fixed_stack;
338-
supervisor_allocation* port_fixed_stack(void) {
339-
_fixed_stack.ptr = port_stack_get_limit();
340-
_fixed_stack.length = (port_stack_get_top() - port_stack_get_limit()) * sizeof(uint32_t);
341-
return &_fixed_stack;
337+
bool port_has_fixed_stack(void) {
338+
return true;
342339
}
343340

344341
uint32_t *port_heap_get_bottom(void) {

ports/nrf/supervisor/port.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -251,8 +251,8 @@ uint32_t *port_heap_get_top(void) {
251251
return port_stack_get_top();
252252
}
253253

254-
supervisor_allocation* port_fixed_stack(void) {
255-
return NULL;
254+
bool port_has_fixed_stack(void) {
255+
return false;
256256
}
257257

258258
uint32_t *port_stack_get_limit(void) {

ports/stm/supervisor/port.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -267,8 +267,8 @@ uint32_t *port_heap_get_top(void) {
267267
return &_ld_heap_end;
268268
}
269269

270-
supervisor_allocation* port_fixed_stack(void) {
271-
return NULL;
270+
bool port_has_fixed_stack(void) {
271+
return false;
272272
}
273273

274274
uint32_t *port_stack_get_limit(void) {

py/circuitpy_mpconfig.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -860,17 +860,20 @@ extern const struct _mp_obj_module_t wifi_module;
860860

861861
#include "supervisor/flash_root_pointers.h"
862862

863+
// From supervisor/memory.c
864+
struct _supervisor_allocation_node;
865+
863866
#define CIRCUITPY_COMMON_ROOT_POINTERS \
864867
const char *readline_hist[8]; \
865868
vstr_t *repl_line; \
866869
mp_obj_t rtc_time_source; \
867870
GAMEPAD_ROOT_POINTERS \
868871
mp_obj_t pew_singleton; \
869-
mp_obj_t terminal_tilegrid_tiles; \
870872
BOARD_UART_ROOT_POINTER \
871873
FLASH_ROOT_POINTERS \
872874
MEMORYMONITOR_ROOT_POINTERS \
873875
NETWORK_ROOT_POINTERS \
876+
struct _supervisor_allocation_node* first_embedded_allocation; \
874877

875878
void supervisor_run_background_tasks_if_tick(void);
876879
#define RUN_BACKGROUND_TASKS (supervisor_run_background_tasks_if_tick())

shared-module/rgbmatrix/RGBMatrix.c

Lines changed: 7 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -78,10 +78,10 @@ void common_hal_rgbmatrix_rgbmatrix_reconstruct(rgbmatrix_rgbmatrix_obj_t* self,
7878
// verify that the matrix is big enough
7979
mp_get_index(mp_obj_get_type(self->framebuffer), self->bufinfo.len, MP_OBJ_NEW_SMALL_INT(self->bufsize-1), false);
8080
} else {
81-
_PM_free(self->bufinfo.buf);
82-
_PM_free(self->protomatter.rgbPins);
83-
_PM_free(self->protomatter.addr);
84-
_PM_free(self->protomatter.screenData);
81+
common_hal_rgbmatrix_free_impl(self->bufinfo.buf);
82+
common_hal_rgbmatrix_free_impl(self->protomatter.rgbPins);
83+
common_hal_rgbmatrix_free_impl(self->protomatter.addr);
84+
common_hal_rgbmatrix_free_impl(self->protomatter.screenData);
8585

8686
self->framebuffer = NULL;
8787
self->bufinfo.buf = common_hal_rgbmatrix_allocator_impl(self->bufsize);
@@ -180,9 +180,6 @@ void common_hal_rgbmatrix_rgbmatrix_deinit(rgbmatrix_rgbmatrix_obj_t* self) {
180180

181181
void rgbmatrix_rgbmatrix_collect_ptrs(rgbmatrix_rgbmatrix_obj_t* self) {
182182
gc_collect_ptr(self->framebuffer);
183-
gc_collect_ptr(self->protomatter.rgbPins);
184-
gc_collect_ptr(self->protomatter.addr);
185-
gc_collect_ptr(self->protomatter.screenData);
186183
}
187184

188185
void common_hal_rgbmatrix_rgbmatrix_set_paused(rgbmatrix_rgbmatrix_obj_t* self, bool paused) {
@@ -217,18 +214,10 @@ int common_hal_rgbmatrix_rgbmatrix_get_height(rgbmatrix_rgbmatrix_obj_t* self) {
217214
}
218215

219216
void *common_hal_rgbmatrix_allocator_impl(size_t sz) {
220-
if (gc_alloc_possible()) {
221-
return m_malloc_maybe(sz + sizeof(void*), true);
222-
} else {
223-
supervisor_allocation *allocation = allocate_memory(align32_size(sz), false);
224-
return allocation ? allocation->ptr : NULL;
225-
}
217+
supervisor_allocation *allocation = allocate_memory(align32_size(sz), false, true);
218+
return allocation ? allocation->ptr : NULL;
226219
}
227220

228221
void common_hal_rgbmatrix_free_impl(void *ptr_in) {
229-
supervisor_allocation *allocation = allocation_from_ptr(ptr_in);
230-
231-
if (allocation) {
232-
free_memory(allocation);
233-
}
222+
free_memory(allocation_from_ptr(ptr_in));
234223
}

shared-module/sharpdisplay/SharpMemoryFramebuffer.c

Lines changed: 14 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -34,32 +34,10 @@
3434
#include "shared-module/sharpdisplay/SharpMemoryFramebuffer.h"
3535

3636
#include "supervisor/memory.h"
37-
#include "supervisor/shared/safe_mode.h"
3837

3938
#define SHARPMEM_BIT_WRITECMD_LSB (0x80)
4039
#define SHARPMEM_BIT_VCOM_LSB (0x40)
4140

42-
static void *hybrid_alloc(size_t sz) {
43-
supervisor_allocation *allocation = allocate_memory(align32_size(sz), false);
44-
if (allocation) {
45-
memset(allocation->ptr, 0, sz);
46-
return allocation->ptr;
47-
}
48-
if (gc_alloc_possible()) {
49-
return m_malloc(sz, true);
50-
}
51-
reset_into_safe_mode(MEM_MANAGE);
52-
return NULL; // unreached
53-
}
54-
55-
static inline void hybrid_free(void *ptr_in) {
56-
supervisor_allocation *allocation = allocation_from_ptr(ptr_in);
57-
58-
if (allocation) {
59-
free_memory(allocation);
60-
}
61-
}
62-
6341
STATIC uint8_t bitrev(uint8_t n) {
6442
uint8_t r = 0;
6543
for(int i=0;i<8;i++) r |= ((n>>i) & 1)<<(7-i);
@@ -102,17 +80,22 @@ void common_hal_sharpdisplay_framebuffer_reset(sharpdisplay_framebuffer_obj_t *s
10280
}
10381

10482
void common_hal_sharpdisplay_framebuffer_reconstruct(sharpdisplay_framebuffer_obj_t *self) {
105-
if (!allocation_from_ptr(self->bufinfo.buf)) {
106-
self->bufinfo.buf = NULL;
107-
}
83+
// Look up the allocation by the old pointer and get the new pointer from it.
84+
supervisor_allocation* alloc = allocation_from_ptr(self->bufinfo.buf);
85+
self->bufinfo.buf = alloc ? alloc->ptr : NULL;
10886
}
10987

11088
void common_hal_sharpdisplay_framebuffer_get_bufinfo(sharpdisplay_framebuffer_obj_t *self, mp_buffer_info_t *bufinfo) {
11189
if (!self->bufinfo.buf) {
11290
int row_stride = common_hal_sharpdisplay_framebuffer_get_row_stride(self);
11391
int height = common_hal_sharpdisplay_framebuffer_get_height(self);
11492
self->bufinfo.len = row_stride * height + 2;
115-
self->bufinfo.buf = hybrid_alloc(self->bufinfo.len);
93+
supervisor_allocation* alloc = allocate_memory(align32_size(self->bufinfo.len), false, true);
94+
if (alloc == NULL) {
95+
m_malloc_fail(self->bufinfo.len);
96+
}
97+
self->bufinfo.buf = alloc->ptr;
98+
memset(alloc->ptr, 0, self->bufinfo.len);
11699

117100
uint8_t *data = self->bufinfo.buf;
118101
*data++ = SHARPMEM_BIT_WRITECMD_LSB;
@@ -123,7 +106,9 @@ void common_hal_sharpdisplay_framebuffer_get_bufinfo(sharpdisplay_framebuffer_ob
123106
}
124107
self->full_refresh = true;
125108
}
126-
*bufinfo = self->bufinfo;
109+
if (bufinfo) {
110+
*bufinfo = self->bufinfo;
111+
}
127112
}
128113

129114
void common_hal_sharpdisplay_framebuffer_deinit(sharpdisplay_framebuffer_obj_t *self) {
@@ -137,7 +122,7 @@ void common_hal_sharpdisplay_framebuffer_deinit(sharpdisplay_framebuffer_obj_t *
137122

138123
common_hal_reset_pin(self->chip_select.pin);
139124

140-
hybrid_free(self->bufinfo.buf);
125+
free_memory(allocation_from_ptr(self->bufinfo.buf));
141126

142127
memset(self, 0, sizeof(*self));
143128
}
@@ -154,19 +139,7 @@ void common_hal_sharpdisplay_framebuffer_construct(sharpdisplay_framebuffer_obj_
154139
self->height = height;
155140
self->baudrate = baudrate;
156141

157-
int row_stride = common_hal_sharpdisplay_framebuffer_get_row_stride(self);
158-
self->bufinfo.len = row_stride * height + 2;
159-
// re-use a supervisor allocation if possible
160-
self->bufinfo.buf = hybrid_alloc(self->bufinfo.len);
161-
162-
uint8_t *data = self->bufinfo.buf;
163-
*data++ = SHARPMEM_BIT_WRITECMD_LSB;
164-
165-
for(int y=0; y<self->height; y++) {
166-
*data = bitrev(y+1);
167-
data += row_stride;
168-
}
169-
self->full_refresh = true;
142+
common_hal_sharpdisplay_framebuffer_get_bufinfo(self, NULL);
170143
}
171144

172145
void common_hal_sharpdisplay_framebuffer_swapbuffers(sharpdisplay_framebuffer_obj_t *self, uint8_t *dirty_row_bitmask) {
@@ -271,7 +244,5 @@ const framebuffer_p_t sharpdisplay_framebuffer_proto = {
271244
};
272245

273246
void common_hal_sharpdisplay_framebuffer_collect_ptrs(sharpdisplay_framebuffer_obj_t *self) {
274-
gc_collect_ptr(self->framebuffer);
275247
gc_collect_ptr(self->bus);
276-
gc_collect_ptr(self->bufinfo.buf);
277248
}

shared-module/sharpdisplay/SharpMemoryFramebuffer.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@
3333

3434
typedef struct {
3535
mp_obj_base_t base;
36-
mp_obj_t framebuffer;
3736
busio_spi_obj_t* bus;
3837
busio_spi_obj_t inline_bus;
3938
digitalio_digitalinout_obj_t chip_select;

shared-module/usb_midi/__init__.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,12 +40,12 @@ supervisor_allocation* usb_midi_allocation;
4040

4141
void usb_midi_init(void) {
4242
// TODO(tannewt): Make this dynamic.
43-
uint16_t tuple_size = align32_size(sizeof(mp_obj_tuple_t) + sizeof(mp_obj_t*) * 2);
44-
uint16_t portin_size = align32_size(sizeof(usb_midi_portin_obj_t));
45-
uint16_t portout_size = align32_size(sizeof(usb_midi_portout_obj_t));
43+
size_t tuple_size = align32_size(sizeof(mp_obj_tuple_t) + sizeof(mp_obj_t*) * 2);
44+
size_t portin_size = align32_size(sizeof(usb_midi_portin_obj_t));
45+
size_t portout_size = align32_size(sizeof(usb_midi_portout_obj_t));
4646

4747
// For each embedded MIDI Jack in the descriptor we create a Port
48-
usb_midi_allocation = allocate_memory(tuple_size + portin_size + portout_size, false);
48+
usb_midi_allocation = allocate_memory(tuple_size + portin_size + portout_size, false, false);
4949

5050
mp_obj_tuple_t *ports = (mp_obj_tuple_t *) usb_midi_allocation->ptr;
5151
ports->base.type = &mp_type_tuple;

supervisor/memory.h

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -33,32 +33,45 @@
3333

3434
#include <stdbool.h>
3535
#include <stdint.h>
36+
#include <stddef.h>
3637

3738
typedef struct {
3839
uint32_t* ptr;
39-
uint32_t length; // in bytes
4040
} supervisor_allocation;
4141

4242

4343

44-
void memory_init(void);
4544
void free_memory(supervisor_allocation* allocation);
45+
46+
// Find the allocation with the given ptr, NULL if not found. When called from the context of a
47+
// supervisor_move_memory() callback, finds the allocation that had that ptr *before* the move, but
48+
// the returned allocation already contains the ptr after the move.
49+
// When called with NULL, may return either NULL or an unused allocation whose ptr is NULL (this is
50+
// a feature used internally in allocate_memory to save code size). Passing the return value to
51+
// free_memory() is a permissible no-op in either case.
4652
supervisor_allocation* allocation_from_ptr(void *ptr);
53+
4754
supervisor_allocation* allocate_remaining_memory(void);
4855

4956
// Allocate a piece of a given length in bytes. If high_address is true then it should be allocated
5057
// at a lower address from the top of the stack. Otherwise, addresses will increase starting after
51-
// statically allocated memory.
52-
supervisor_allocation* allocate_memory(uint32_t length, bool high_address);
58+
// statically allocated memory. If movable is false, memory will be taken from outside the GC heap
59+
// and will stay stationary until freed. While the VM is running, this will fail unless a previous
60+
// allocation of exactly matching length has recently been freed. If movable is true, memory will be
61+
// taken from either outside or inside the GC heap, and when the VM exits, will be moved outside.
62+
// The ptr of the returned supervisor_allocation will change at that point. If you need to be
63+
// notified of that, add your own callback function at the designated place near the end of
64+
// supervisor_move_memory().
65+
supervisor_allocation* allocate_memory(uint32_t length, bool high_address, bool movable);
5366

54-
static inline uint16_t align32_size(uint16_t size) {
55-
if (size % 4 != 0) {
56-
return (size & 0xfffc) + 0x4;
57-
}
58-
return size;
67+
static inline size_t align32_size(size_t size) {
68+
return (size + 3) & ~3;
5969
}
6070

61-
// Called after the heap is freed in case the supervisor wants to save some values.
71+
size_t get_allocation_length(supervisor_allocation* allocation);
72+
73+
// Called after the GC heap is freed, transfers movable allocations from the GC heap to the
74+
// supervisor heap and compacts the supervisor heap.
6275
void supervisor_move_memory(void);
6376

6477
#endif // MICROPY_INCLUDED_SUPERVISOR_MEMORY_H

0 commit comments

Comments
 (0)