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