wm_mem.c 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856
  1. /*****************************************************************************
  2. *
  3. * File Name : wm_mem.c
  4. *
  5. * Description: memory manager Module
  6. *
  7. * Copyright (c) 2014 Winner Micro Electronic Design Co., Ltd.
  8. * All rights reserved.
  9. *
  10. * Author : dave
  11. *
  12. * Date : 2014-6-12
  13. *****************************************************************************/
  14. #include "wm_osal.h"
  15. #include "wm_mem.h"
  16. #include "list.h"
  17. #include <string.h>
  18. extern u8 tls_get_isr_count(void);
  19. /**
  20. * This variable is set if the memory mananger has been initialized.
  21. * This is available only for debug version of the driver
  22. */
  23. bool memory_manager_initialized = false;
  24. /**
  25. * This mutex is used to synchronize the list of allocated
  26. * memory blocks. This is a debug version only feature
  27. */
  28. tls_os_sem_t *mem_sem;
  29. #if WM_MEM_DEBUG
  30. struct dl_list memory_used_list;
  31. struct dl_list memory_free_list;
  32. #define MEM_BLOCK_SIZE 800
  33. MEMORY_BLOCK mem_blocks[MEM_BLOCK_SIZE];
  34. u32 alloc_heap_mem_bytes = 0;
  35. u32 alloc_heap_mem_blk_cnt = 0;
  36. u32 alloc_heap_mem_max_size = 0;
  37. #define PRE_OVERSIZE 0
  38. #define OVERSIZE 0
  39. /**
  40. * This is a debug only function that performs memory management operations for us.
  41. * Memory allocated using this function is tracked, flagged when leaked, and caught for
  42. * overflows and underflows.
  43. *
  44. * \param size The size in bytes of memory to
  45. * allocate
  46. *
  47. * \param file The full path of file where this
  48. * function is invoked from
  49. * \param line The line number in the file where this
  50. * method was called from
  51. * \return Pointer to the allocated memory or NULL in case of a failure
  52. */
  53. void * mem_alloc_debug(u32 size, char* file, int line)
  54. {
  55. void *buf = NULL;
  56. u32 pad_len;
  57. int i = 0;
  58. u32 cpu_sr;
  59. //
  60. // If the memory manager has not been initialized, do so now
  61. //
  62. cpu_sr = tls_os_set_critical();
  63. if (!memory_manager_initialized) {
  64. tls_os_status_t os_status;
  65. memory_manager_initialized = true;
  66. //
  67. // NOTE: If two thread allocate the very first allocation simultaneously
  68. // it could cause double initialization of the memory manager. This is a
  69. // highly unlikely scenario and will occur in debug versions only.
  70. //
  71. os_status = tls_os_sem_create(&mem_sem, 1);
  72. if(os_status != TLS_OS_SUCCESS)
  73. printf("mem_alloc_debug: tls_os_sem_create mem_sem error\r\n");
  74. dl_list_init(&memory_used_list);
  75. dl_list_init(&memory_free_list);
  76. for(i = 0; i < MEM_BLOCK_SIZE; i++)
  77. {
  78. dl_list_add_tail(&memory_free_list, &mem_blocks[i].list);
  79. }
  80. }
  81. tls_os_release_critical(cpu_sr);
  82. tls_os_sem_acquire(mem_sem, 0);
  83. cpu_sr = tls_os_set_critical();
  84. //
  85. // Allocate the required memory chunk plus header and trailer bytes
  86. //
  87. pad_len = sizeof(u32) - (size & 0x3);
  88. buf = malloc(sizeof(MEMORY_PATTERN) + PRE_OVERSIZE + size + pad_len + OVERSIZE + sizeof(MEMORY_PATTERN));
  89. if (buf) {
  90. //
  91. // Memory allocation succeeded. Add information about the allocated
  92. // block in the list that tracks all allocations.
  93. //
  94. PMEMORY_PATTERN mem_ptn_hd;
  95. PMEMORY_PATTERN mem_ptn_tl;
  96. PMEMORY_BLOCK mem_blk_hd1;
  97. if(dl_list_empty(&memory_free_list))
  98. {
  99. printf("Memory blocks empty!\r\n");
  100. free(buf);
  101. tls_os_release_critical(cpu_sr);
  102. tls_os_sem_release(mem_sem);
  103. tls_mem_alloc_info();
  104. return NULL;
  105. }
  106. mem_blk_hd1 = dl_list_first(&memory_free_list, MEMORY_BLOCK, list);
  107. dl_list_del(&mem_blk_hd1->list);
  108. dl_list_add_tail(&memory_used_list, &mem_blk_hd1->list);
  109. alloc_heap_mem_bytes += size+sizeof(MEMORY_PATTERN)+sizeof(MEMORY_PATTERN)+pad_len + PRE_OVERSIZE + OVERSIZE;
  110. alloc_heap_mem_blk_cnt++;
  111. if (alloc_heap_mem_bytes > alloc_heap_mem_max_size)
  112. {
  113. alloc_heap_mem_max_size = alloc_heap_mem_bytes;
  114. //printf("alloc_heap_mem_max_size=%d\n", alloc_heap_mem_max_size);
  115. }
  116. mem_blk_hd1->pad = pad_len;
  117. mem_blk_hd1->file = file;
  118. mem_blk_hd1->line = line;
  119. mem_blk_hd1->length = size;
  120. mem_blk_hd1->header_pattern = (u32)buf;
  121. // Fill in the memory header and trailer
  122. mem_ptn_hd = (PMEMORY_PATTERN)buf;
  123. mem_ptn_hd->pattern0= MEM_HEADER_PATTERN;
  124. /*mem_ptn_hd->pattern1= MEM_HEADER_PATTERN;
  125. mem_ptn_hd->pattern2= MEM_HEADER_PATTERN;
  126. mem_ptn_hd->pattern3= MEM_HEADER_PATTERN;*/
  127. mem_ptn_tl = (PMEMORY_PATTERN)(((u8 *)(buf))+size + sizeof(MEMORY_PATTERN)+pad_len + PRE_OVERSIZE + OVERSIZE);
  128. mem_ptn_tl->pattern0= MEM_TAILER_PATTERN;
  129. /*mem_ptn_tl->pattern1= MEM_TAILER_PATTERN;
  130. mem_ptn_tl->pattern2= MEM_TAILER_PATTERN;
  131. mem_ptn_tl->pattern3= MEM_TAILER_PATTERN;*/
  132. // Jump ahead by memory header so pointer returned to caller points at the right place
  133. buf = ((u8 *)buf) + sizeof (MEMORY_PATTERN) + PRE_OVERSIZE;
  134. #if 0
  135. printf("==>Memory was allocated from %s at line %d with length %d\n",
  136. mem_blk_hd1->file,
  137. mem_blk_hd1->line,
  138. mem_blk_hd1->length);
  139. printf("==>mem alloc ptr = 0x%x\n", buf);
  140. #endif
  141. }
  142. else
  143. {
  144. printf("==>Memory was allocated from %s at line %d with length %d, allocated size %d, count %d\r\n",
  145. file,
  146. line,
  147. size, alloc_heap_mem_bytes, alloc_heap_mem_blk_cnt);
  148. tls_os_release_critical(cpu_sr);
  149. tls_os_sem_release(mem_sem);
  150. tls_mem_alloc_info();
  151. return buf;
  152. }
  153. tls_os_release_critical(cpu_sr);
  154. tls_os_sem_release(mem_sem);
  155. return buf;
  156. }
  157. void * mem_calloc_debug(u32 n, u32 size, char* file, int line)
  158. {
  159. void *buf = NULL;
  160. u32 pad_len;
  161. int i = 0;
  162. u32 cpu_sr;
  163. //
  164. // If the memory manager has not been initialized, do so now
  165. //
  166. cpu_sr = tls_os_set_critical();
  167. if (!memory_manager_initialized) {
  168. tls_os_status_t os_status;
  169. memory_manager_initialized = true;
  170. //
  171. // NOTE: If two thread allocate the very first allocation simultaneously
  172. // it could cause double initialization of the memory manager. This is a
  173. // highly unlikely scenario and will occur in debug versions only.
  174. //
  175. os_status = tls_os_sem_create(&mem_sem, 1);
  176. if(os_status != TLS_OS_SUCCESS)
  177. printf("mem_alloc_debug: tls_os_sem_create mem_sem error\r\n");
  178. dl_list_init(&memory_used_list);
  179. dl_list_init(&memory_free_list);
  180. for(i = 0; i < MEM_BLOCK_SIZE; i++)
  181. {
  182. dl_list_add_tail(&memory_free_list, &mem_blocks[i].list);
  183. }
  184. }
  185. tls_os_release_critical(cpu_sr);
  186. tls_os_sem_acquire(mem_sem, 0);
  187. cpu_sr = tls_os_set_critical();
  188. //
  189. // Allocate the required memory chunk plus header and trailer bytes
  190. //
  191. pad_len = sizeof(u32) - ((n*size) & 0x3);
  192. buf = malloc(sizeof(MEMORY_PATTERN) + PRE_OVERSIZE + n*size + pad_len + OVERSIZE + sizeof(MEMORY_PATTERN));
  193. if (buf) {
  194. //
  195. // Memory allocation succeeded. Add information about the allocated
  196. // block in the list that tracks all allocations.
  197. //
  198. PMEMORY_PATTERN mem_ptn_hd;
  199. PMEMORY_PATTERN mem_ptn_tl;
  200. PMEMORY_BLOCK mem_blk_hd1;
  201. if(dl_list_empty(&memory_free_list))
  202. {
  203. printf("Memory blocks empty!\r\n");
  204. free(buf);
  205. tls_os_release_critical(cpu_sr);
  206. tls_os_sem_release(mem_sem);
  207. tls_mem_alloc_info();
  208. return NULL;
  209. }
  210. mem_blk_hd1 = dl_list_first(&memory_free_list, MEMORY_BLOCK, list);
  211. dl_list_del(&mem_blk_hd1->list);
  212. dl_list_add_tail(&memory_used_list, &mem_blk_hd1->list);
  213. alloc_heap_mem_bytes += n*size+sizeof(MEMORY_PATTERN)+sizeof(MEMORY_PATTERN)+pad_len + PRE_OVERSIZE + OVERSIZE;
  214. alloc_heap_mem_blk_cnt++;
  215. if (alloc_heap_mem_bytes > alloc_heap_mem_max_size)
  216. {
  217. alloc_heap_mem_max_size = alloc_heap_mem_bytes;
  218. //printf("alloc_heap_mem_max_size=%d\n", alloc_heap_mem_max_size);
  219. }
  220. mem_blk_hd1->pad = pad_len;
  221. mem_blk_hd1->file = file;
  222. mem_blk_hd1->line = line;
  223. mem_blk_hd1->length = n*size;
  224. mem_blk_hd1->header_pattern = (u32)buf;
  225. // Fill in the memory header and trailer
  226. mem_ptn_hd = (PMEMORY_PATTERN)buf;
  227. mem_ptn_hd->pattern0= MEM_HEADER_PATTERN;
  228. /*mem_ptn_hd->pattern1= MEM_HEADER_PATTERN;
  229. mem_ptn_hd->pattern2= MEM_HEADER_PATTERN;
  230. mem_ptn_hd->pattern3= MEM_HEADER_PATTERN;*/
  231. mem_ptn_tl = (PMEMORY_PATTERN)(((u8 *)(buf))+n*size + sizeof(MEMORY_PATTERN)+pad_len + PRE_OVERSIZE + OVERSIZE);
  232. mem_ptn_tl->pattern0= MEM_TAILER_PATTERN;
  233. /*mem_ptn_tl->pattern1= MEM_TAILER_PATTERN;
  234. mem_ptn_tl->pattern2= MEM_TAILER_PATTERN;
  235. mem_ptn_tl->pattern3= MEM_TAILER_PATTERN;*/
  236. // Jump ahead by memory header so pointer returned to caller points at the right place
  237. buf = ((u8 *)buf) + sizeof (MEMORY_PATTERN) + PRE_OVERSIZE;
  238. #if 0
  239. printf("==>Memory was allocated from %s at line %d with length %d\r\n",
  240. mem_blk_hd1->file,
  241. mem_blk_hd1->line,
  242. mem_blk_hd1->length);
  243. printf("==>mem alloc ptr = 0x%x\n", buf);
  244. #endif
  245. }
  246. else
  247. {
  248. printf("==>Memory was allocated from %s at line %d with length %d, allocated size %d, count %d\r\n",
  249. file,
  250. line,
  251. n*size, alloc_heap_mem_bytes, alloc_heap_mem_blk_cnt);
  252. tls_os_release_critical(cpu_sr);
  253. tls_os_sem_release(mem_sem);
  254. tls_mem_alloc_info();
  255. return buf;
  256. }
  257. tls_os_release_critical(cpu_sr);
  258. tls_os_sem_release(mem_sem);
  259. return buf;
  260. }
  261. /**
  262. * This routine is called to free memory which was previously allocated using MpAllocateMemory function.
  263. * Before freeing the memory, this function checks and makes sure that no overflow or underflows have
  264. * happened and will also try to detect multiple frees of the same memory chunk.
  265. *
  266. * \param p Pointer to allocated memory
  267. */
  268. void mem_free_debug(void *p, char* file, int line)
  269. {
  270. PMEMORY_PATTERN mem_ptn_hd;
  271. PMEMORY_PATTERN mem_ptn_tl;
  272. PMEMORY_BLOCK mem_blk_hd1;
  273. u8 needfree = 0;
  274. u8 haserr = 0;
  275. u32 cpu_sr;
  276. // Jump back by memory header size so we can get to the header
  277. mem_ptn_hd = (PMEMORY_PATTERN) (((u8 *)p) - sizeof(MEMORY_PATTERN) - PRE_OVERSIZE);
  278. tls_os_sem_acquire(mem_sem, 0);
  279. cpu_sr = tls_os_set_critical();
  280. dl_list_for_each(mem_blk_hd1, &memory_used_list, MEMORY_BLOCK, list){
  281. if(mem_blk_hd1->header_pattern == (u32)mem_ptn_hd)
  282. {
  283. needfree = 1;
  284. break;
  285. }
  286. }
  287. if(needfree)
  288. {
  289. dl_list_del(&mem_blk_hd1->list);
  290. dl_list_add_tail(&memory_free_list, &mem_blk_hd1->list);
  291. alloc_heap_mem_bytes -= mem_blk_hd1->length + sizeof(MEMORY_PATTERN) + sizeof(MEMORY_PATTERN) + PRE_OVERSIZE + OVERSIZE +
  292. mem_blk_hd1->pad;
  293. alloc_heap_mem_blk_cnt--;
  294. }
  295. if(needfree == 0)
  296. {
  297. printf("Memory Block %p was deallocated from %s at line %d \r\n", mem_ptn_hd, file, line);
  298. printf("Memory %p has been deallocated!\r\n", p);
  299. dl_list_for_each_reverse(mem_blk_hd1, &memory_free_list, MEMORY_BLOCK, list){
  300. if(mem_blk_hd1->header_pattern == (u32)mem_ptn_hd)
  301. {
  302. printf("Memory Block %p has been put free list!\r\n", mem_ptn_hd);
  303. break;
  304. }
  305. }
  306. tls_os_release_critical(cpu_sr);
  307. tls_os_sem_release(mem_sem);
  308. tls_mem_alloc_info();
  309. return;
  310. }
  311. #if 0
  312. if(mem_blk_hd1->line == 976 || mem_blk_hd1->line == 983)
  313. {
  314. printf("Memory Block %p can not deallocated from %s at line %d \r\n", mem_ptn_hd, file, line);
  315. printf("Memory %p has been deallocated!\r\n", p);
  316. tls_mem_alloc_info();
  317. }
  318. #endif
  319. mem_ptn_tl = (PMEMORY_PATTERN) ((u8 *)p + mem_blk_hd1->length + mem_blk_hd1->pad + OVERSIZE);
  320. //
  321. // Check that header was not corrupted
  322. //
  323. if (mem_ptn_hd->pattern0 != MEM_HEADER_PATTERN /*|| mem_ptn_hd->pattern1 != MEM_HEADER_PATTERN
  324. || mem_ptn_hd->pattern2 != MEM_HEADER_PATTERN || mem_ptn_hd->pattern3 != MEM_HEADER_PATTERN*/)
  325. {
  326. printf("Memory %p was deallocated from %s at line %d \r\n", p, file, line);
  327. printf("Memory header corruption due to underflow detected at memory block %p\r\n",
  328. mem_ptn_hd);
  329. printf("Header pattern 0(0x%x)\r\n",//, 1(0x%x), 2(0x%x), 3(0x%x)
  330. mem_ptn_hd->pattern0/*,
  331. mem_ptn_hd->pattern1,
  332. mem_ptn_hd->pattern2,
  333. mem_ptn_hd->pattern3*/);
  334. //printf("Dumping information about memory block. "
  335. // "This information may itself have been "
  336. // "corrupted and could cause machine to bugcheck.\r\n");
  337. printf("Memory was allocated from %s at line %d with length %d\r\n",
  338. mem_blk_hd1->file,
  339. mem_blk_hd1->line,
  340. mem_blk_hd1->length);
  341. haserr = 1;
  342. }
  343. #if 0
  344. printf("<==free memory allocated from %s at line %d with length %d\n",
  345. mem_blk_hd->file,
  346. mem_blk_hd->line,
  347. mem_blk_hd->length);
  348. printf("<==free memory 0x%x\n", (u8 *)mem_blk_hd+sizeof(*mem_blk_hd));
  349. #endif
  350. //
  351. // Check that trailer was not corrupted
  352. //
  353. if(mem_ptn_tl->pattern0 != MEM_TAILER_PATTERN /*|| mem_ptn_tl->pattern1 != MEM_TAILER_PATTERN
  354. || mem_ptn_tl->pattern2 != MEM_TAILER_PATTERN || mem_ptn_tl->pattern3 != MEM_TAILER_PATTERN*/) {
  355. printf("Memory %p was deallocated from %s at line %d \r\n", p, file, line);
  356. printf("Memory tailer corruption due to overflow detected at %p\r\n", mem_ptn_hd);
  357. printf("Tailer pattern 0(0x%x)\r\n",//, 1(0x%x), 2(0x%x), 3(0x%x)
  358. mem_ptn_tl->pattern0/*,
  359. mem_ptn_tl->pattern1,
  360. mem_ptn_tl->pattern2,
  361. mem_ptn_tl->pattern3*/);
  362. //printf("Dumping information about memory block. "
  363. // "This information may itself have been "
  364. // "corrupted and could cause machine to bugcheck.\r\n");
  365. printf("Memory was allocated from %s at line %d with length %d\r\n",
  366. mem_blk_hd1->file, mem_blk_hd1->line, mem_blk_hd1->length);
  367. haserr = 1;
  368. }
  369. if(needfree){
  370. free(mem_ptn_hd);
  371. }
  372. tls_os_release_critical(cpu_sr);
  373. tls_os_sem_release(mem_sem);
  374. if(haserr)
  375. tls_mem_alloc_info();
  376. }
  377. void * mem_realloc_debug(void *mem_address, u32 size, char* file, int line)
  378. {
  379. void * mem_re_addr;
  380. u32 cpu_sr;
  381. if ((mem_re_addr = mem_alloc_debug(size, file, line)) == NULL){
  382. printf("mem_realloc_debug failed(size=%d).\r\n", size);
  383. return NULL;
  384. }
  385. if(mem_address != NULL)
  386. {
  387. cpu_sr = tls_os_set_critical();
  388. memcpy(mem_re_addr, mem_address, size);
  389. tls_os_release_critical(cpu_sr);
  390. mem_free_debug(mem_address, file, line);
  391. }
  392. //printf("mem_realloc_debug mem_address=%p, mem_re_addr=%p, size=%d, file=%s, line=%d\n", mem_address, mem_re_addr, size, file, line);
  393. return mem_re_addr;
  394. }
  395. void tls_mem_alloc_info(void)
  396. {
  397. int i;
  398. MEMORY_BLOCK * pos;
  399. u32 cpu_sr;
  400. tls_os_sem_acquire(mem_sem, 0);
  401. cpu_sr = tls_os_set_critical();
  402. printf("==>Memory was allocated size %d, count %d\r\n",
  403. alloc_heap_mem_bytes, alloc_heap_mem_blk_cnt);
  404. i = 1;
  405. dl_list_for_each(pos, &memory_used_list, MEMORY_BLOCK, list){
  406. printf("Block(%2d): addr<%p>, file<%s>, line<%d>, length<%d>\r\n",
  407. i, (void *)pos->header_pattern, pos->file, pos->line, pos->length);
  408. i++;
  409. }
  410. tls_os_release_critical(cpu_sr);
  411. tls_os_sem_release(mem_sem);
  412. }
  413. int is_safe_addr_debug(void* p, u32 len, char* file, int line)
  414. {
  415. int i;
  416. MEMORY_BLOCK * pos;
  417. u32 cpu_sr;
  418. if(((u32)p) >= (u32)0x64ae8 || ((u32)p) < (u32)0x54ae8)
  419. {
  420. return 1;
  421. }
  422. tls_os_sem_acquire(mem_sem, 0);
  423. cpu_sr = tls_os_set_critical();
  424. i = 1;
  425. dl_list_for_each(pos, &memory_used_list, MEMORY_BLOCK, list){
  426. if((pos->header_pattern + sizeof (MEMORY_PATTERN) + PRE_OVERSIZE) <= ((u32)p) && ((u32)p) <= ((u32)(pos->header_pattern + sizeof(MEMORY_PATTERN) + PRE_OVERSIZE + pos->length)))
  427. {
  428. if(((u32)p) + len > ((u32)(pos->header_pattern + sizeof(MEMORY_PATTERN) + PRE_OVERSIZE + pos->length)))
  429. {
  430. printf("==>Memory oversize. Block(%2d): addr<%p>, file<%s>, line<%d>, length<%d>\r\n",
  431. i, (void *)pos->header_pattern, pos->file, pos->line, pos->length);
  432. break;
  433. }
  434. else
  435. {
  436. tls_os_release_critical(cpu_sr);
  437. tls_os_sem_release(mem_sem);
  438. return 1;
  439. }
  440. }
  441. //else if(((u32)p) < pos->header_pattern)
  442. //{
  443. // //tls_os_release_critical(cpu_sr);
  444. // tls_os_sem_release(mem_sem);
  445. // return 1;
  446. // }
  447. i++;
  448. }
  449. tls_os_release_critical(cpu_sr);
  450. tls_os_sem_release(mem_sem);
  451. printf("==>Memory is not safe addr<%p>, file<%s>, line<%d>.\r\n",p, file, line);
  452. return 0;
  453. }
  454. #else /* WM_MEM_DEBUG */
  455. #if TLS_OS_FREERTOS
  456. u32 alloc_heap_mem_bytes = 0;
  457. u32 alloc_heap_mem_blk_cnt = 0;
  458. u32 alloc_heap_mem_max_size = 0;
  459. #define OS_MEM_FLAG (0x5AA5A55A)
  460. #define NON_OS_MEM_FLAG (0xA55A5A5A)
  461. #define MEM_HEAD_FLAG (0xBB55B55B)
  462. #endif
  463. #define USING_ADD_HEADER 1
  464. extern u32 total_mem_size;
  465. void * mem_alloc_debug(u32 size)
  466. {
  467. u32 cpu_sr = 0;
  468. u32 *buffer = NULL;
  469. u32 length = size;
  470. //printf("size:%d\n", size);
  471. if (!memory_manager_initialized) {
  472. tls_os_status_t os_status;
  473. cpu_sr = tls_os_set_critical();
  474. memory_manager_initialized = true;
  475. //
  476. // NOTE: If two thread allocate the very first allocation simultaneously
  477. // it could cause double initialization of the memory manager. This is a
  478. // highly unlikely scenario and will occur in debug versions only.
  479. //
  480. os_status = tls_os_sem_create(&mem_sem, 1);
  481. if(os_status != TLS_OS_SUCCESS)
  482. printf("mem_alloc_debug: tls_os_sem_create mem_sem error\r\n");
  483. tls_os_release_critical(cpu_sr);
  484. }
  485. #if USING_ADD_HEADER
  486. length += 8;
  487. if(tls_get_isr_count() > 0)
  488. {
  489. extern void *pvPortMalloc( size_t xWantedSize );
  490. buffer = pvPortMalloc(length);
  491. if(buffer)
  492. {
  493. *buffer = OS_MEM_FLAG;
  494. buffer++;
  495. *buffer = length;
  496. buffer++;
  497. }
  498. }
  499. else
  500. {
  501. tls_os_sem_acquire(mem_sem, 0);
  502. cpu_sr = tls_os_set_critical();
  503. buffer = (u32*)malloc(length);
  504. if(buffer)
  505. {
  506. *buffer = NON_OS_MEM_FLAG;
  507. buffer++;
  508. *buffer = length;
  509. buffer++;
  510. total_mem_size -= length;
  511. }
  512. tls_os_release_critical(cpu_sr);
  513. tls_os_sem_release(mem_sem);
  514. }
  515. #else
  516. tls_os_sem_acquire(mem_sem, 0);
  517. cpu_sr = tls_os_set_critical();
  518. buffer = (u32*)malloc(length);
  519. tls_os_release_critical(cpu_sr);
  520. tls_os_sem_release(mem_sem);
  521. #endif
  522. return buffer;
  523. }
  524. void mem_free_debug(void *p)
  525. {
  526. u32 cpu_sr = 0;
  527. // u32 len = 0;
  528. #if USING_ADD_HEADER
  529. u32* intMemPtr = NULL;
  530. u8 isrstatus = 0;
  531. isrstatus = tls_get_isr_count();
  532. if(isrstatus == 0)
  533. {
  534. tls_os_sem_acquire(mem_sem, 0);
  535. cpu_sr = tls_os_set_critical();
  536. }
  537. intMemPtr = (u32*)p;
  538. if(p)
  539. {
  540. intMemPtr -= 2;
  541. if (*intMemPtr == OS_MEM_FLAG)
  542. {
  543. extern void vPortFree( void *pv );
  544. vPortFree(intMemPtr);
  545. intMemPtr = NULL;
  546. }
  547. else if (*intMemPtr == NON_OS_MEM_FLAG)
  548. {
  549. total_mem_size += *(intMemPtr + 1);
  550. free(intMemPtr);
  551. intMemPtr = NULL;
  552. }
  553. else
  554. {
  555. printf("mem_free_debug ptr error!!!!!\r\n");
  556. }
  557. }
  558. if(isrstatus == 0)
  559. {
  560. tls_os_release_critical(cpu_sr);
  561. tls_os_sem_release(mem_sem);
  562. }
  563. #else //UCOSII
  564. tls_os_sem_acquire(mem_sem, 0);
  565. cpu_sr = tls_os_set_critical();
  566. free(p);
  567. tls_os_release_critical(cpu_sr);
  568. tls_os_sem_release(mem_sem);
  569. #endif
  570. }
  571. void * mem_realloc_debug(void *mem_address, u32 size)
  572. {
  573. u32 * mem_re_addr = NULL;
  574. u32 cpu_sr = 0;
  575. u32 length = size;
  576. #if USING_ADD_HEADER
  577. length = size + 2*4;
  578. if(tls_get_isr_count() > 0)
  579. {
  580. extern void *pvPortMalloc( size_t xWantedSize );
  581. mem_re_addr = pvPortMalloc(length);
  582. if (mem_re_addr)
  583. {
  584. return NULL;
  585. }
  586. if(mem_address != NULL)
  587. {
  588. if (*((u32 *)mem_address-1)> size)
  589. {
  590. memcpy((u8 *)(mem_re_addr + 2), (u8 *)mem_address, size);
  591. }
  592. else
  593. {
  594. memcpy((u8 *)(mem_re_addr + 2), (u8 *)mem_address, *((u32 *)mem_address-1));
  595. }
  596. mem_free_debug(mem_address);
  597. mem_address = NULL;
  598. }
  599. if(mem_re_addr)
  600. {
  601. *mem_re_addr = OS_MEM_FLAG;
  602. mem_re_addr ++;
  603. *mem_re_addr = length;
  604. mem_re_addr ++;
  605. }
  606. }
  607. else
  608. {
  609. tls_os_sem_acquire(mem_sem, 0);
  610. cpu_sr = tls_os_set_critical();
  611. mem_re_addr = (u32*)malloc(length);
  612. if(mem_re_addr && mem_address)
  613. {
  614. if (*((u32 *)mem_address-1)> size)
  615. {
  616. memcpy((u8 *)(mem_re_addr + 2), (u8 *)mem_address, size);
  617. }
  618. else
  619. {
  620. memcpy((u8 *)(mem_re_addr + 2), (u8 *)mem_address, *((u32 *)mem_address-1));
  621. }
  622. *mem_re_addr = NON_OS_MEM_FLAG;
  623. mem_re_addr ++;
  624. *mem_re_addr = length;
  625. mem_re_addr ++;
  626. total_mem_size -= length;
  627. }
  628. tls_os_release_critical(cpu_sr);
  629. tls_os_sem_release(mem_sem);
  630. mem_free_debug(mem_address);
  631. }
  632. #else
  633. tls_os_sem_acquire(mem_sem, 0);
  634. cpu_sr = tls_os_set_critical();
  635. mem_re_addr = realloc(mem_address, length);
  636. tls_os_release_critical(cpu_sr);
  637. tls_os_sem_release(mem_sem);
  638. #endif
  639. //if(mem_re_addr == NULL)
  640. //{
  641. // printf("realloc error \r\n");
  642. //}
  643. return mem_re_addr;
  644. }
  645. void *mem_calloc_debug(u32 n, u32 size)
  646. {
  647. u32 cpu_sr = 0;
  648. u32 *buffer = NULL;
  649. u32 length = 0;
  650. #if USING_ADD_HEADER
  651. length = n*size;
  652. length += 2*4;
  653. if(tls_get_isr_count() > 0)
  654. {
  655. extern void *pvPortMalloc( size_t xWantedSize );
  656. buffer = pvPortMalloc(length);
  657. if(buffer)
  658. {
  659. memset(buffer, 0, length);
  660. *buffer = OS_MEM_FLAG;
  661. buffer ++;
  662. *buffer = length;
  663. buffer ++;
  664. }
  665. }
  666. else
  667. {
  668. tls_os_sem_acquire(mem_sem, 0);
  669. cpu_sr = tls_os_set_critical();
  670. buffer = (u32*)malloc(length);
  671. if(buffer)
  672. {
  673. memset(buffer, 0, length);
  674. *buffer = NON_OS_MEM_FLAG;
  675. buffer ++;
  676. *buffer = length;
  677. buffer ++;
  678. total_mem_size -= length;
  679. }
  680. tls_os_release_critical(cpu_sr);
  681. tls_os_sem_release(mem_sem);
  682. }
  683. #else //UCOSII
  684. tls_os_sem_acquire(mem_sem, 0);
  685. cpu_sr = tls_os_set_critical();
  686. buffer = (u32*)calloc(n,size);
  687. tls_os_release_critical(cpu_sr);
  688. tls_os_sem_release(mem_sem);
  689. #endif
  690. //if(buffer == NULL)
  691. //{
  692. // printf("calloc error \r\n");
  693. //}
  694. return buffer;
  695. }
  696. #endif /* WM_MEM_DEBUG */
  697. extern u32 __heap_end;
  698. extern u32 __heap_start;
  699. u32 tls_mem_get_avail_heapsize(void)
  700. {
  701. #if USING_ADD_HEADER
  702. u32 availablemem = 0;
  703. u32 cpu_sr;
  704. tls_os_sem_acquire(mem_sem, 0);
  705. cpu_sr = tls_os_set_critical();
  706. availablemem = total_mem_size;
  707. tls_os_release_critical(cpu_sr);
  708. tls_os_sem_release(mem_sem);
  709. return availablemem;
  710. #else
  711. u8 *p = NULL;
  712. u32 startpos = 0;
  713. u32 stoppos = 0;
  714. u32 laststartpos = 0;
  715. static u32 last_avail_heapsize = 0;
  716. u32 cpu_sr = 0;
  717. if (!memory_manager_initialized) {
  718. tls_os_status_t os_status;
  719. memory_manager_initialized = true;
  720. //
  721. // NOTE: If two thread allocate the very first allocation simultaneously
  722. // it could cause double initialization of the memory manager. This is a
  723. // highly unlikely scenario and will occur in debug versions only.
  724. //
  725. os_status = tls_os_sem_create(&mem_sem, 1);
  726. if(os_status != TLS_OS_SUCCESS)
  727. printf("mem_alloc_debug: tls_os_sem_create mem_sem error\n");
  728. }
  729. tls_os_sem_acquire(mem_sem, 0);
  730. cpu_sr = tls_os_set_critical();
  731. if (last_avail_heapsize)
  732. {
  733. startpos = last_avail_heapsize;
  734. stoppos = last_avail_heapsize*2;
  735. if (startpos > ((u32)&__heap_end - (u32)&__heap_start))
  736. {
  737. startpos = (u32)&__heap_end - (u32)&__heap_start;
  738. }
  739. }
  740. else
  741. {
  742. startpos = (u32)&__heap_end - (u32)&__heap_start;
  743. stoppos = (u32)&__heap_end - (u32)&__heap_start;
  744. }
  745. for (;startpos <= stoppos;)
  746. {
  747. p = malloc(startpos);
  748. if (p)
  749. {
  750. free(p);
  751. if (startpos < 1024 || (stoppos - startpos) < 1024
  752. || (startpos == ((u32)&__heap_end - (u32)&__heap_start)))
  753. {
  754. last_avail_heapsize = startpos;
  755. goto END;
  756. }
  757. laststartpos = startpos;
  758. startpos = (stoppos + startpos)>>1;
  759. }
  760. else
  761. {
  762. stoppos = startpos;
  763. if (laststartpos)
  764. {
  765. startpos = (laststartpos + stoppos)/2;
  766. }
  767. else
  768. {
  769. startpos = startpos>>1;
  770. }
  771. if (startpos < 1024 || (stoppos - startpos) < 1024)
  772. {
  773. last_avail_heapsize = startpos;
  774. goto END;
  775. }
  776. }
  777. }
  778. END:
  779. tls_os_release_critical(cpu_sr);
  780. tls_os_sem_release(mem_sem);
  781. return startpos;
  782. #endif
  783. }