1 /*
2  * Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #include <stdlib.h>
8 #include "pico.h"
9 #include "pico/malloc.h"
10 
11 #if PICO_USE_MALLOC_MUTEX
12 #include "pico/mutex.h"
13 auto_init_mutex(malloc_mutex);
14 #endif
15 
16 extern void *REAL_FUNC(malloc)(size_t size);
17 extern void *REAL_FUNC(calloc)(size_t count, size_t size);
18 extern void *REAL_FUNC(realloc)(void *mem, size_t size);
19 extern void REAL_FUNC(free)(void *mem);
20 
21 extern char __StackLimit; /* Set by linker.  */
22 
check_alloc(__unused void * mem,__unused uint size)23 static inline void check_alloc(__unused void *mem, __unused uint size) {
24 #if PICO_MALLOC_PANIC
25     if (!mem || (((char *)mem) + size) > &__StackLimit) {
26         panic("Out of memory");
27     }
28 #endif
29 }
30 
WRAPPER_FUNC(malloc)31 void *WRAPPER_FUNC(malloc)(size_t size) {
32 #if PICO_USE_MALLOC_MUTEX
33     mutex_enter_blocking(&malloc_mutex);
34 #endif
35     void *rc = REAL_FUNC(malloc)(size);
36 #if PICO_USE_MALLOC_MUTEX
37     mutex_exit(&malloc_mutex);
38 #endif
39 #if PICO_DEBUG_MALLOC
40     if (!rc || ((uint8_t *)rc) + size > (uint8_t*)PICO_DEBUG_MALLOC_LOW_WATER) {
41         printf("malloc %d %p->%p\n", (uint) size, rc, ((uint8_t *) rc) + size);
42     }
43 #endif
44     check_alloc(rc, size);
45     return rc;
46 }
47 
WRAPPER_FUNC(calloc)48 void *WRAPPER_FUNC(calloc)(size_t count, size_t size) {
49 #if PICO_USE_MALLOC_MUTEX
50     mutex_enter_blocking(&malloc_mutex);
51 #endif
52     void *rc = REAL_FUNC(calloc)(count, size);
53 #if PICO_USE_MALLOC_MUTEX
54     mutex_exit(&malloc_mutex);
55 #endif
56 #if PICO_DEBUG_MALLOC
57     if (!rc || ((uint8_t *)rc) + size > (uint8_t*)PICO_DEBUG_MALLOC_LOW_WATER) {
58         printf("calloc %d %p->%p\n", (uint) (count * size), rc, ((uint8_t *) rc) + size);
59     }
60 #endif
61     check_alloc(rc, size);
62     return rc;
63 }
64 
WRAPPER_FUNC(realloc)65 void *WRAPPER_FUNC(realloc)(void *mem, size_t size) {
66 #if PICO_USE_MALLOC_MUTEX
67     mutex_enter_blocking(&malloc_mutex);
68 #endif
69     void *rc = REAL_FUNC(realloc)(mem, size);
70 #if PICO_USE_MALLOC_MUTEX
71     mutex_exit(&malloc_mutex);
72 #endif
73 #if PICO_DEBUG_MALLOC
74     if (!rc || ((uint8_t *)rc) + size > (uint8_t*)PICO_DEBUG_MALLOC_LOW_WATER) {
75         printf("realloc %p %d->%p\n", mem, (uint) size, rc);
76     }
77 #endif
78     check_alloc(rc, size);
79     return rc;
80 }
81 
WRAPPER_FUNC(free)82 void WRAPPER_FUNC(free)(void *mem) {
83 #if PICO_USE_MALLOC_MUTEX
84     mutex_enter_blocking(&malloc_mutex);
85 #endif
86     REAL_FUNC(free)(mem);
87 #if PICO_USE_MALLOC_MUTEX
88     mutex_exit(&malloc_mutex);
89 #endif
90 }
91