1 /**
2 * @file lv_mem.c
3 */
4
5 /*********************
6 * INCLUDES
7 *********************/
8 #include "lv_mem_private.h"
9 #include "lv_string.h"
10 #include "../misc/lv_assert.h"
11 #include "../misc/lv_log.h"
12 #include "../core/lv_global.h"
13
14 #if LV_USE_OS == LV_OS_PTHREAD
15 #include <pthread.h>
16 #endif
17
18 /*********************
19 * DEFINES
20 *********************/
21 /*memset the allocated memories to 0xaa and freed memories to 0xbb (just for testing purposes)*/
22 #ifndef LV_MEM_ADD_JUNK
23 #define LV_MEM_ADD_JUNK 0
24 #endif
25
26 #define zero_mem LV_GLOBAL_DEFAULT()->memory_zero
27
28 /**********************
29 * TYPEDEFS
30 **********************/
31
32 /**********************
33 * STATIC PROTOTYPES
34 **********************/
35
36 /**********************
37 * GLOBAL PROTOTYPES
38 **********************/
39 void * lv_malloc_core(size_t size);
40 void * lv_realloc_core(void * p, size_t new_size);
41 void lv_free_core(void * p);
42 void lv_mem_monitor_core(lv_mem_monitor_t * mon_p);
43 lv_result_t lv_mem_test_core(void);
44
45 /**********************
46 * STATIC VARIABLES
47 **********************/
48
49 /**********************
50 * MACROS
51 **********************/
52 #if LV_USE_LOG && LV_LOG_TRACE_MEM
53 #define LV_TRACE_MEM(...) LV_LOG_TRACE(__VA_ARGS__)
54 #else
55 #define LV_TRACE_MEM(...)
56 #endif
57
58 /**********************
59 * GLOBAL FUNCTIONS
60 **********************/
61
lv_malloc(size_t size)62 void * lv_malloc(size_t size)
63 {
64 LV_TRACE_MEM("allocating %lu bytes", (unsigned long)size);
65 if(size == 0) {
66 LV_TRACE_MEM("using zero_mem");
67 return &zero_mem;
68 }
69
70 void * alloc = lv_malloc_core(size);
71
72 if(alloc == NULL) {
73 LV_LOG_INFO("couldn't allocate memory (%lu bytes)", (unsigned long)size);
74 #if LV_LOG_LEVEL <= LV_LOG_LEVEL_INFO
75 lv_mem_monitor_t mon;
76 lv_mem_monitor(&mon);
77 LV_LOG_INFO("used: %zu (%3d %%), frag: %3d %%, biggest free: %zu",
78 mon.total_size - mon.free_size, mon.used_pct, mon.frag_pct,
79 mon.free_biggest_size);
80 #endif
81 return NULL;
82 }
83
84 #if LV_MEM_ADD_JUNK
85 lv_memset(alloc, 0xaa, size);
86 #endif
87
88 LV_TRACE_MEM("allocated at %p", alloc);
89 return alloc;
90 }
91
lv_malloc_zeroed(size_t size)92 void * lv_malloc_zeroed(size_t size)
93 {
94 LV_TRACE_MEM("allocating %lu bytes", (unsigned long)size);
95 if(size == 0) {
96 LV_TRACE_MEM("using zero_mem");
97 return &zero_mem;
98 }
99
100 void * alloc = lv_malloc_core(size);
101 if(alloc == NULL) {
102 LV_LOG_INFO("couldn't allocate memory (%lu bytes)", (unsigned long)size);
103 #if LV_LOG_LEVEL <= LV_LOG_LEVEL_INFO
104 lv_mem_monitor_t mon;
105 lv_mem_monitor(&mon);
106 LV_LOG_INFO("used: %zu (%3d %%), frag: %3d %%, biggest free: %zu",
107 mon.total_size - mon.free_size, mon.used_pct, mon.frag_pct,
108 mon.free_biggest_size);
109 #endif
110 return NULL;
111 }
112
113 lv_memzero(alloc, size);
114
115 LV_TRACE_MEM("allocated at %p", alloc);
116 return alloc;
117 }
118
lv_calloc(size_t num,size_t size)119 void * lv_calloc(size_t num, size_t size)
120 {
121 LV_TRACE_MEM("allocating number of %zu each %zu bytes", num, size);
122 return lv_malloc_zeroed(num * size);
123 }
124
lv_zalloc(size_t size)125 void * lv_zalloc(size_t size)
126 {
127 return lv_malloc_zeroed(size);
128 }
129
lv_free(void * data)130 void lv_free(void * data)
131 {
132 LV_TRACE_MEM("freeing %p", data);
133 if(data == &zero_mem) return;
134 if(data == NULL) return;
135
136 lv_free_core(data);
137 }
138
lv_realloc(void * data_p,size_t new_size)139 void * lv_realloc(void * data_p, size_t new_size)
140 {
141 LV_TRACE_MEM("reallocating %p with %lu size", data_p, (unsigned long)new_size);
142 if(new_size == 0) {
143 LV_TRACE_MEM("using zero_mem");
144 lv_free(data_p);
145 return &zero_mem;
146 }
147
148 if(data_p == &zero_mem) return lv_malloc(new_size);
149
150 void * new_p = lv_realloc_core(data_p, new_size);
151
152 if(new_p == NULL) {
153 LV_LOG_ERROR("couldn't reallocate memory");
154 return NULL;
155 }
156
157 LV_TRACE_MEM("reallocated at %p", new_p);
158 return new_p;
159 }
160
lv_mem_test(void)161 lv_result_t lv_mem_test(void)
162 {
163 if(zero_mem != ZERO_MEM_SENTINEL) {
164 LV_LOG_WARN("zero_mem is written");
165 return LV_RESULT_INVALID;
166 }
167
168 return lv_mem_test_core();
169 }
170
lv_mem_monitor(lv_mem_monitor_t * mon_p)171 void lv_mem_monitor(lv_mem_monitor_t * mon_p)
172 {
173 lv_memzero(mon_p, sizeof(lv_mem_monitor_t));
174 lv_mem_monitor_core(mon_p);
175 }
176
177 /**********************
178 * STATIC FUNCTIONS
179 **********************/
180