Allow overriding of the heap allocator and getting heap sizes

Also port from codal-core in support of PXT GC.
Also, fix compiler optimization bug in calloc().
This commit is contained in:
Michal Moskal 2019-01-20 17:59:10 +00:00
parent 530072491a
commit 6275437300
2 changed files with 58 additions and 5 deletions

View File

@ -85,4 +85,38 @@ struct HeapDefinition
int microbit_create_heap(uint32_t start, uint32_t end);
void microbit_heap_print();
/**
* Returns the size of a given heap.
*
* @param heap_index index between 0 and MICROBIT_MAXIMUM_HEAPS-1
*
* @return the size of heap in bytes, or zero if no such heap exists.
*/
uint32_t microbit_heap_size(uint8_t heap_index);
/**
* Attempt to allocate a given amount of memory from any of our configured heap areas.
*
* @param size The amount of memory, in bytes, to allocate.
*
* @return A pointer to the allocated memory, or NULL if insufficient memory is available.
*/
extern "C" void* microbit_alloc(size_t size);
/**
* Release a given area of memory from the heap.
*
* @param mem The memory area to release.
*/
extern "C" void microbit_free(void *mem);
/**
* Copy existing contents of ptr to a new memory block of given size.
*
* @param ptr The existing memory block (can be NULL)
* @param size The size of new block (can be smaller or larger than the old one)
*/
extern "C" void* microbit_realloc(void* ptr, size_t size);
#endif

View File

@ -173,6 +173,14 @@ int microbit_create_heap(uint32_t start, uint32_t end)
return MICROBIT_OK;
}
uint32_t device_heap_size(uint8_t heap_index)
{
if (heap_index >= heap_count)
return 0;
HeapDefinition *h = &heap[heap_index];
return (uint8_t*)h->heap_end - (uint8_t*)h->heap_start;
}
/**
* Attempt to allocate a given amount of memory from a given heap area.
*
@ -271,11 +279,14 @@ void *microbit_malloc(size_t size, HeapDefinition &heap)
*
* @return A pointer to the allocated memory, or NULL if insufficient memory is available.
*/
void *malloc(size_t size)
void *microbit_alloc(size_t size)
{
static uint8_t initialised = 0;
void *p;
if (size == 0)
return NULL;
if (!initialised)
{
heap_count = 0;
@ -319,7 +330,7 @@ void *malloc(size_t size)
*
* @param mem The memory area to release.
*/
void free(void *mem)
void microbit_free(void *mem)
{
uint32_t *memory = (uint32_t *)mem;
uint32_t *cb = memory-1;
@ -355,13 +366,17 @@ void* calloc (size_t num, size_t size)
{
void *mem = malloc(num*size);
if (mem)
memclr(mem, num*size);
if (mem) {
// without this write, GCC will happily optimize malloc() above into calloc()
// and remove the memset
((uint32_t*)mem)[0] = 1;
memset(mem, 0, num*size);
}
return mem;
}
void* realloc (void* ptr, size_t size)
void* microbit_realloc (void* ptr, size_t size)
{
void *mem = malloc(size);
@ -380,6 +395,10 @@ void* realloc (void* ptr, size_t size)
return mem;
}
void *malloc(size_t sz) __attribute__ ((weak, alias ("microbit_alloc")));
void free(void *mem) __attribute__ ((weak, alias ("microbit_free")));
void* realloc (void* ptr, size_t size) __attribute__ ((weak, alias ("microbit_realloc")));
// make sure the libc allocator is not pulled in
void *_malloc_r(struct _reent *, size_t len)
{