summaryrefslogtreecommitdiff
path: root/os/src/sbrk.c
blob: d013f4fc665f53485b144a4df10bcfdea8e3d2a6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#include <reent.h>
#include <errno.h>
#include <stdlib.h>

#include "FreeRTOS.h"
#include "task.h"
#include "mpu_wrappers.h"

#include <osdebug.h>

// Mostly stolen from mbed-freertos

extern uintptr_t __heap_start, __heap_end;
extern uintptr_t __stack_start __attribute__((weak));

/* Low-level bulk RAM allocator -- used by Newlib's Malloc */
void *heap_end = NULL;
PRIVILEGED_FUNCTION void *_sbrk_r(struct _reent *ptr, ptrdiff_t incr)
{
    void *prev_heap_end, *next_heap_end, *ret;
    void *stack_min = (void *)(__stack_start ? __stack_start : __heap_end);
    
    DBGOUT("_sbrk_r(%p, %u)\r\n", ptr, incr);

    taskENTER_CRITICAL();
    {
        /* Initialize on first call */
        if (heap_end == NULL)
        {
            heap_end = (void *)&__heap_start;
        }

        prev_heap_end = heap_end;

        /* Align to always be on 8-byte boundaries */
        next_heap_end = (void *)((((uintptr_t)heap_end + incr) + 7) & ~7);

        /* Check if this allocation would exceed the end of the ram - would probably get into the stack first however */
        if (next_heap_end > stack_min)
        {
            ptr->_errno = ENOMEM;
            ret = NULL;
        }
        else
        {
            heap_end = next_heap_end;
            ret = (void *)prev_heap_end;
        }
    }
    taskEXIT_CRITICAL();
    return ret;
}