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