wm_mem.c 25 KB

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