1 /* 2 * Copyright (C) 2015-2017 Alibaba Group Holding Limited 3 */ 4 5 #ifndef K_MM_H 6 #define K_MM_H 7 8 9 #ifdef __cplusplus 10 extern "C" { 11 #endif 12 13 /** @addtogroup aos_rhino mm 14 * Heap memory management. 15 * 16 * @{ 17 */ 18 19 #if (RHINO_CONFIG_MM_TLF > 0) 20 #define KMM_ERROR_LOCKED 1 21 #define KMM_ERROR_UNLOCKED 0 22 23 #if (RHINO_CONFIG_MM_DEBUG && (RHINO_CONFIG_MM_TRACE_LVL > 0)) 24 #define KMM_BT_SET_BY_KV 1 25 #endif 26 27 /** 28 * Heap useage size statistic 29 */ 30 #define K_MM_STATISTIC 1 31 32 /** 33 * Memory buffer align to MM_ALIGN_SIZE 34 */ 35 #define MM_ALIGN_BIT 3 36 #define MM_ALIGN_SIZE (1 << MM_ALIGN_BIT) 37 #define MM_ALIGN_MASK (MM_ALIGN_SIZE - 1) 38 #define MM_ALIGN_UP(a) (((a) + MM_ALIGN_MASK) & ~MM_ALIGN_MASK) 39 #define MM_ALIGN_DOWN(a) ((a) & ~MM_ALIGN_MASK) 40 41 /** 42 * Max size of memory buffer 43 */ 44 #define MM_MAX_BIT RHINO_CONFIG_MM_MAXMSIZEBIT 45 #define MM_MAX_SIZE (1 << MM_MAX_BIT) 46 47 /** 48 * Min size of memory buffer 49 */ 50 #define MM_MIN_BIT RHINO_CONFIG_MM_MINISIZEBIT 51 #define MM_MIN_SIZE (1 << (MM_MIN_BIT - 1)) 52 53 /** 54 * Size level of memory buffer 55 */ 56 #define MM_BIT_LEVEL (MM_MAX_BIT - MM_MIN_BIT + 2) 57 58 /** 59 * Min size of memory heap 60 */ 61 #define MM_MIN_HEAP_SIZE 1024 62 63 /* magic word for check overwrite or corrupt */ 64 #define MM_DYE_USED 0xFEFE 65 #define MM_DYE_FREE 0xABAB 66 67 #define MM_OWNER_ID_SELF 0xFF 68 69 #define MM_CURSTAT_MASK 0x1 70 #define MM_PRESTAT_MASK 0x2 71 72 /* bit 0 */ 73 #define MM_BUFF_FREE 1 74 #define MM_BUFF_USED 0 75 76 /* bit 1 */ 77 #define MM_BUFF_PREV_FREE 2 78 #define MM_BUFF_PREV_USED 0 79 80 81 /** 82 * Buffer head size 83 */ 84 #define MMLIST_HEAD_SIZE (MM_ALIGN_UP(sizeof(k_mm_list_t) - sizeof(free_ptr_t))) 85 /** 86 * Buffer payload size 87 */ 88 #define MM_GET_BUF_SIZE(blk) ((blk)->buf_size & (~MM_ALIGN_MASK)) 89 /** 90 * Buffer head + payload size 91 */ 92 #define MM_GET_BLK_SIZE(blk) (MM_GET_BUF_SIZE(blk) + MMLIST_HEAD_SIZE) 93 94 /** 95 * Get next buffer head addr 96 */ 97 #define MM_GET_NEXT_BLK(blk) ((k_mm_list_t *)((blk)->mbinfo.buffer + MM_GET_BUF_SIZE(blk))) 98 /** 99 * Get this buffer head addr 100 */ 101 #define MM_GET_THIS_BLK(buf) ((k_mm_list_t *)((char *)(buf)-MMLIST_HEAD_SIZE)) 102 103 #define MM_LAST_BLK_MAGIC 0x11224433 104 105 #if (RHINO_CONFIG_MM_REGION_MUTEX == 0) 106 /** 107 * MM critical section strategy: 108 * Interrupt mask for single core, and busy-waiting spinlock for multi-core 109 */ 110 #define MM_CRITICAL_ENTER(pmmhead,flags_cpsr) krhino_spin_lock_irq_save(&(pmmhead->mm_lock),flags_cpsr); 111 #define MM_CRITICAL_EXIT(pmmhead,flags_cpsr) krhino_spin_unlock_irq_restore(&(pmmhead->mm_lock),flags_cpsr); 112 #else /* (RHINO_CONFIG_MM_REGION_MUTEX != 0) */ 113 /** 114 * MM critical section strategy: 115 * Task blocked 116 */ 117 #define MM_CRITICAL_ENTER(pmmhead,flags_cpsr) \ 118 do { \ 119 (void)flags_cpsr; \ 120 CPSR_ALLOC(); \ 121 RHINO_CRITICAL_ENTER(); \ 122 if (g_intrpt_nested_level[cpu_cur_get()] > 0u) { \ 123 k_err_proc(RHINO_NOT_CALLED_BY_INTRPT); \ 124 } \ 125 RHINO_CRITICAL_EXIT(); \ 126 krhino_mutex_lock(&(pmmhead->mm_mutex), RHINO_WAIT_FOREVER); \ 127 } while (0); 128 #define MM_CRITICAL_EXIT(pmmhead,flags_cpsr) \ 129 do { \ 130 (void)flags_cpsr; \ 131 krhino_mutex_unlock(&(pmmhead->mm_mutex)); \ 132 } while (0); 133 #endif 134 135 /** 136 * free buffer list 137 */ 138 typedef struct free_ptr_struct { 139 struct k_mm_list_struct *prev; 140 struct k_mm_list_struct *next; 141 } free_ptr_t; 142 143 /** 144 * memory buffer head 145 */ 146 #define ALIGN_UP_2(a) ((a % 2 == 0) ? a : (a + 1)) 147 148 typedef struct k_mm_list_struct { 149 #if (RHINO_CONFIG_MM_DEBUG > 0) 150 uint16_t dye; 151 uint8_t owner_id; 152 uint8_t trace_id; 153 size_t owner; 154 #if (RHINO_CONFIG_MM_TRACE_LVL > 0) 155 void *trace[ALIGN_UP_2(RHINO_CONFIG_MM_TRACE_LVL)]; 156 #endif 157 #endif 158 struct k_mm_list_struct *prev; 159 /**< 160 * buffer payload size, and: 161 * bit 0 indicates whether the block is used and 162 * bit 1 allows to know whether the previous block is free 163 */ 164 size_t buf_size; 165 union { 166 free_ptr_t free_ptr; /**< when buffer is free, add to free list */ 167 uint8_t buffer[1]; /**< when buffer is alloced, payload start */ 168 } mbinfo; 169 } k_mm_list_t; 170 171 /** 172 * memory region info 173 * Heap can contain multiple regoins 174 */ 175 typedef struct k_mm_region_info_struct { 176 k_mm_list_t *end; 177 struct k_mm_region_info_struct *next; 178 } k_mm_region_info_t; 179 180 /** 181 * memory heap info 182 * heap contains: 183 * --------------------------------------------------------------------------- 184 * | k_mm_head | k_mm_list_t | k_mm_region_info_t | free space | k_mm_list_t | 185 * --------------------------------------------------------------------------- 186 */ 187 typedef struct { 188 #if (RHINO_CONFIG_MM_REGION_MUTEX > 0) 189 kmutex_t mm_mutex; 190 #else 191 kspinlock_t mm_lock; 192 #endif 193 194 k_mm_region_info_t *regioninfo; /**< Heap can contain multiple regoins */ 195 196 #if (RHINO_CONFIG_MM_BLK > 0) 197 void *fix_pool; /**< heap can contain one fix pool, deal with little buffer */ 198 #endif 199 200 #if (K_MM_STATISTIC > 0) 201 size_t used_size; 202 size_t maxused_size; 203 size_t free_size; 204 size_t alloc_times[MM_BIT_LEVEL]; /* number of times for each TLF level */ 205 #endif 206 /**< msb (MM_BIT_LEVEL-1) <-> lsb 0, one bit match one freelist */ 207 uint32_t free_bitmap; 208 /**< 209 * freelist[N]: contain free blks at level N, 210 * 2^(N + MM_MIN_BIT) <= level N buffer size < 2^(1 + N + MM_MIN_BIT) 211 */ 212 k_mm_list_t *freelist[MM_BIT_LEVEL]; 213 } k_mm_head; 214 215 /** 216 * internal funcs 217 */ 218 kstat_t krhino_init_mm_head(k_mm_head **ppmmhead, void *addr, size_t len); 219 kstat_t krhino_deinit_mm_head(k_mm_head *mmhead); 220 kstat_t krhino_add_mm_region(k_mm_head *mmhead, void *addr, size_t len); 221 222 void *k_mm_alloc(k_mm_head *mmhead, size_t size); 223 void k_mm_free(k_mm_head *mmhead, void *ptr); 224 void *k_mm_realloc(k_mm_head *mmhead, void *oldmem, size_t new_size); 225 226 /** 227 * Memory buffer allocation. 228 * 229 * @param[in] size size of the mem to malloc 230 * 231 * @return buffer address or NULL 232 */ 233 void *krhino_mm_alloc(size_t size); 234 235 /** 236 * Memory buffer free. 237 * 238 * @param[in] ptr buffer address 239 * 240 * @return none 241 */ 242 void krhino_mm_free(void *ptr); 243 244 /** 245 * Memory buffer realloc. 246 * 247 * @param[in] oldmem oldmem buffer address 248 * @param[in] newsize size of the mem to malloc 249 * 250 * @return buffer address or NULL 251 */ 252 void *krhino_mm_realloc(void *oldmem, size_t newsize); 253 254 /** 255 * Get the max free buffer size. 256 * 257 * @param[in] NULL 258 * 259 * @return the max free buffer size 260 */ 261 size_t krhino_mm_max_free_size_get(void); 262 263 #else 264 265 #include <stdlib.h> 266 267 /** 268 * do not use os heap management 269 */ 270 271 #define krhino_mm_alloc malloc 272 #define krhino_mm_free free 273 #define krhino_mm_realloc realloc 274 275 #endif /* RHINO_CONFIG_MM_TLF > 0 */ 276 277 /** @} */ 278 279 #ifdef __cplusplus 280 } 281 #endif 282 283 #endif /* K_MM_H */ 284 285