tests/malloc: Allow malloc to fail when out of RAM, add heap test

cases.

Fixes #76.
This commit is contained in:
Angus Gratton 2016-02-16 22:00:29 +11:00
parent 80b191af08
commit 8fffd14e50
4 changed files with 41 additions and 14 deletions

View file

@ -81,13 +81,16 @@
unsigned cpu_sr; unsigned cpu_sr;
char level1_int_disabled; char level1_int_disabled;
/* Supervisor stack pointer entry. This is the "high water mark" of how far the /* Supervisor stack pointer entry. On reset, sdk_user_start sets a
supervisor stack grew down before task started. * tentative 512 byte supervisor stack size.
When the scheduler starts, this changes to the "high water mark" of
how far the supervisor stack grew down before task started.
After tasks start, task stacks are all allocated from the heap and After tasks start, task stacks are all allocated from the heap and
FreeRTOS checks for stack overflow. FreeRTOS checks for stack overflow.
*/ */
static uint32_t xPortSupervisorStackPointer; void *xPortSupervisorStackPointer;
/* /*
* Stack initialization * Stack initialization
@ -218,7 +221,7 @@ size_t xPortGetFreeHeapSize( void )
struct mallinfo mi = mallinfo(); struct mallinfo mi = mallinfo();
uint32_t brk_val = (uint32_t) sbrk(0); uint32_t brk_val = (uint32_t) sbrk(0);
uint32_t sp = xPortSupervisorStackPointer; intptr_t sp = (intptr_t)xPortSupervisorStackPointer;
if(sp == 0) /* scheduler not started */ if(sp == 0) /* scheduler not started */
__asm__ __volatile__ ("mov %0, a1\n" : "=a"(sp)); __asm__ __volatile__ ("mov %0, a1\n" : "=a"(sp));
return sp - brk_val + mi.fordblks; return sp - brk_val + mi.fordblks;

View file

@ -12,6 +12,8 @@
#include <esp/uart.h> #include <esp/uart.h>
#include <stdlib.h> #include <stdlib.h>
extern void *xPortSupervisorStackPointer;
IRAM caddr_t _sbrk_r (struct _reent *r, int incr) IRAM caddr_t _sbrk_r (struct _reent *r, int incr)
{ {
extern char _heap_start; /* linker script defined */ extern char _heap_start; /* linker script defined */
@ -21,13 +23,16 @@ IRAM caddr_t _sbrk_r (struct _reent *r, int incr)
if (heap_end == NULL) if (heap_end == NULL)
heap_end = &_heap_start; heap_end = &_heap_start;
prev_heap_end = heap_end; prev_heap_end = heap_end;
/* TODO: Check stack collision
if (heap_end + incr > stack_ptr) intptr_t sp = (intptr_t)xPortSupervisorStackPointer;
if(sp == 0) /* scheduler not started */
__asm__ __volatile__ ("mov %0, a1\n" : "=a"(sp));
if ((intptr_t)heap_end + incr >= sp)
{ {
_write (1, "_sbrk: Heap collided with stack\n", 32); r->_errno = ENOMEM;
while(1) {} return (caddr_t)-1;
} }
*/
heap_end += incr; heap_end += incr;
return (caddr_t) prev_heap_end; return (caddr_t) prev_heap_end;

View file

@ -232,7 +232,7 @@ SECTIONS
_heap_start = ABSOLUTE(.); _heap_start = ABSOLUTE(.);
/* _stack_sentry = ALIGN(0x8); */ /* _stack_sentry = ALIGN(0x8); */
} >dram0_0_seg :dram0_0_bss_phdr } >dram0_0_seg :dram0_0_bss_phdr
/* __stack = 0x3ffc8000; */ /* __stack = 0x3ffc8000; <-- this value seems a bit odd, stack on sdk_user_start is ~0x3ffffce9 */
.lit4 : ALIGN(4) .lit4 : ALIGN(4)
{ {

View file

@ -4,6 +4,7 @@
#include <FreeRTOS.h> #include <FreeRTOS.h>
DEFINE_SOLO_TESTCASE(02_heap_simple) DEFINE_SOLO_TESTCASE(02_heap_simple)
DEFINE_SOLO_TESTCASE(02_heap_full)
/* Simple heap accounting tests */ /* Simple heap accounting tests */
static void a_02_heap_simple() static void a_02_heap_simple()
@ -35,3 +36,21 @@ static void a_02_heap_simple()
TEST_ASSERT_UINT32_WITHIN_MESSAGE(100, freeheap, after, "Free heap size after freeing buffer should be close to initial"); TEST_ASSERT_UINT32_WITHIN_MESSAGE(100, freeheap, after, "Free heap size after freeing buffer should be close to initial");
TEST_PASS; TEST_PASS;
} }
/* Ensure malloc behaves when out of memory */
static void a_02_heap_full()
{
void *x = malloc(65536);
TEST_ASSERT_NULL_MESSAGE(x, "Allocating 64kB should fail and return null");
void *y = malloc(32768);
TEST_ASSERT_NOT_NULL_MESSAGE(y, "Allocating 32kB should succeed");
void *z = malloc(32768);
TEST_ASSERT_NULL_MESSAGE(z, "Allocating second 32kB should fail");
free(y);
z = malloc(32768);
TEST_ASSERT_NOT_NULL_MESSAGE(z, "Allocating 32kB should succeed after first block freed");
TEST_PASS;
}