wm_mem.c 25 KB

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