OSAL_Memory.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635
  1. /**************************************************************************************************
  2. Filename: OSAL_Memory.c
  3. Revised: $Date: 2010-09-20 14:59:43 -0700 (Mon, 20 Sep 2010) $
  4. Revision: $Revision: 23848 $
  5. Description: OSAL Heap Memory management functions. There is an Application Note that
  6. should be read before studying and/or modifying this module:
  7. SWRA204 "Heap Memory Management"
  8. Copyright 2004-2010 Texas Instruments Incorporated. All rights reserved.
  9. IMPORTANT: Your use of this Software is limited to those specific rights
  10. granted under the terms of a software license agreement between the user
  11. who downloaded the software, his/her employer (which must be your employer)
  12. and Texas Instruments Incorporated (the "License"). You may not use this
  13. Software unless you agree to abide by the terms of the License. The License
  14. limits your use, and you acknowledge, that the Software may not be modified,
  15. copied or distributed unless embedded on a Texas Instruments microcontroller
  16. or used solely and exclusively in conjunction with a Texas Instruments radio
  17. frequency transceiver, which is integrated into your product. Other than for
  18. the foregoing purpose, you may not use, reproduce, copy, prepare derivative
  19. works of, modify, distribute, perform, display or sell this Software and/or
  20. its documentation for any purpose.
  21. YOU FURTHER ACKNOWLEDGE AND AGREE THAT THE SOFTWARE AND DOCUMENTATION ARE
  22. PROVIDED “AS IS” WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED,
  23. INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY, TITLE,
  24. NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL
  25. TEXAS INSTRUMENTS OR ITS LICENSORS BE LIABLE OR OBLIGATED UNDER CONTRACT,
  26. NEGLIGENCE, STRICT LIABILITY, CONTRIBUTION, BREACH OF WARRANTY, OR OTHER
  27. LEGAL EQUITABLE THEORY ANY DIRECT OR INDIRECT DAMAGES OR EXPENSES
  28. INCLUDING BUT NOT LIMITED TO ANY INCIDENTAL, SPECIAL, INDIRECT, PUNITIVE
  29. OR CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF PROCUREMENT
  30. OF SUBSTITUTE GOODS, TECHNOLOGY, SERVICES, OR ANY CLAIMS BY THIRD PARTIES
  31. (INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF), OR OTHER SIMILAR COSTS.
  32. Should you have any questions regarding your right to use this Software,
  33. contact Texas Instruments Incorporated at www.TI.com.
  34. **************************************************************************************************/
  35. /* ------------------------------------------------------------------------------------------------
  36. * Includes
  37. * ------------------------------------------------------------------------------------------------
  38. */
  39. #include "comdef.h"
  40. #include "OSAL.h"
  41. #include "OSAL_Memory.h"
  42. #include "OnBoard.h"
  43. #include "hal_assert.h"
  44. /* ------------------------------------------------------------------------------------------------
  45. * Constants
  46. * ------------------------------------------------------------------------------------------------
  47. */
  48. #define OSALMEM_IN_USE 0x8000
  49. #if (MAXMEMHEAP & OSALMEM_IN_USE)
  50. #error MAXMEMHEAP is too big to manage!
  51. #endif
  52. #define OSALMEM_HDRSZ sizeof(osalMemHdr_t)
  53. // Round a value up to the ceiling of OSALMEM_HDRSZ for critical dependencies on even multiples.
  54. #define OSALMEM_ROUND(X) ((((X) + OSALMEM_HDRSZ - 1) / OSALMEM_HDRSZ) * OSALMEM_HDRSZ)
  55. /* Minimum wasted bytes to justify splitting a block before allocation.
  56. * Adjust accordingly to attempt to balance the tradeoff of wasted space and runtime throughput
  57. * spent splitting blocks into sizes that may not be practically usable when sandwiched between
  58. * two blocks in use (and thereby not able to be coalesced.)
  59. * Ensure that this size is an even multiple of OSALMEM_HDRSZ.
  60. */
  61. #if !defined OSALMEM_MIN_BLKSZ
  62. #define OSALMEM_MIN_BLKSZ (OSALMEM_ROUND((OSALMEM_HDRSZ * 2)))
  63. #endif
  64. #if !defined OSALMEM_LL_BLKSZ
  65. #if defined NONWK
  66. #define OSALMEM_LL_BLKSZ (OSALMEM_ROUND(6) + (1 * OSALMEM_HDRSZ))
  67. #else
  68. /*
  69. * Profiling the sample apps with default settings shows the following long-lived allocations
  70. * which should live at the bottom of the small-block bucket so that they are never iterated over
  71. * by osal_mem_alloc/free(), nor ever considered for coalescing, etc. This saves significant
  72. * run-time throughput (on 8051 SOC if not also MSP). This is dynamic "dead space" and is not
  73. * available to the small-block bucket heap.
  74. *
  75. * Adjust this size accordingly to accomodate application-specific changes including changing the
  76. * size of long-lived objects profiled by sample apps and long-lived objects added by application.
  77. */
  78. #if defined ZCL_KEY_ESTABLISH // Attempt to capture worst-case for SE sample apps.
  79. #define OSALMEM_LL_BLKSZ (OSALMEM_ROUND(526) + (32 * OSALMEM_HDRSZ))
  80. #elif defined TC_LINKKEY_JOIN
  81. #define OSALMEM_LL_BLKSZ (OSALMEM_ROUND(454) + (21 * OSALMEM_HDRSZ))
  82. #elif ((defined SECURE) && (SECURE != 0))
  83. #define OSALMEM_LL_BLKSZ (OSALMEM_ROUND(418) + (19 * OSALMEM_HDRSZ))
  84. #else
  85. #define OSALMEM_LL_BLKSZ (OSALMEM_ROUND(417) + (19 * OSALMEM_HDRSZ))
  86. #endif
  87. #endif
  88. #endif
  89. /* Adjust accordingly to attempt to accomodate the block sizes of the vast majority of
  90. * very high frequency allocations/frees by profiling the system runtime.
  91. * This default of 16 accomodates the OSAL timers block, osalTimerRec_t, and many others.
  92. * Ensure that this size is an even multiple of OSALMEM_MIN_BLKSZ for run-time efficiency.
  93. */
  94. #if !defined OSALMEM_SMALL_BLKSZ
  95. #define OSALMEM_SMALL_BLKSZ (OSALMEM_ROUND(16))
  96. #endif
  97. #if !defined OSALMEM_SMALL_BLKCNT
  98. #define OSALMEM_SMALL_BLKCNT 8
  99. #endif
  100. /*
  101. * These numbers setup the size of the small-block bucket which is reserved at the front of the
  102. * heap for allocations of OSALMEM_SMALL_BLKSZ or smaller.
  103. */
  104. // Size of the heap bucket reserved for small block-sized allocations.
  105. // Adjust accordingly to attempt to accomodate the vast majority of very high frequency operations.
  106. #define OSALMEM_SMALLBLK_BUCKET ((OSALMEM_SMALL_BLKSZ * OSALMEM_SMALL_BLKCNT) + OSALMEM_LL_BLKSZ)
  107. // Index of the first available osalMemHdr_t after the small-block heap which will be set in-use in
  108. // order to prevent the small-block bucket from being coalesced with the wilderness.
  109. #define OSALMEM_SMALLBLK_HDRCNT (OSALMEM_SMALLBLK_BUCKET / OSALMEM_HDRSZ)
  110. // Index of the first available osalMemHdr_t after the small-block heap which will be set in-use in
  111. #define OSALMEM_BIGBLK_IDX (OSALMEM_SMALLBLK_HDRCNT + 1)
  112. // The size of the wilderness after losing the small-block heap, the wasted header to block the
  113. // small-block heap from being coalesced, and the wasted header to mark the end of the heap.
  114. #define OSALMEM_BIGBLK_SZ (MAXMEMHEAP - OSALMEM_SMALLBLK_BUCKET - OSALMEM_HDRSZ*2)
  115. // Index of the last available osalMemHdr_t at the end of the heap which will be set to zero for
  116. // fast comparisons with zero to determine the end of the heap.
  117. #define OSALMEM_LASTBLK_IDX ((MAXMEMHEAP / OSALMEM_HDRSZ) - 1)
  118. // For information about memory profiling, refer to SWRA204 "Heap Memory Management", section 1.5.
  119. #if !defined OSALMEM_PROFILER
  120. #define OSALMEM_PROFILER FALSE // Enable/disable the memory usage profiling buckets.
  121. #endif
  122. #if !defined OSALMEM_PROFILER_LL
  123. #define OSALMEM_PROFILER_LL FALSE // Special profiling of the Long-Lived bucket.
  124. #endif
  125. #if OSALMEM_PROFILER
  126. #define OSALMEM_INIT 'X'
  127. #define OSALMEM_ALOC 'A'
  128. #define OSALMEM_REIN 'F'
  129. #endif
  130. /* ------------------------------------------------------------------------------------------------
  131. * Typedefs
  132. * ------------------------------------------------------------------------------------------------
  133. */
  134. typedef struct {
  135. // The 15 LSB's of 'val' indicate the total item size, including the header, in 8-bit bytes.
  136. unsigned len : 15;
  137. // The 1 MSB of 'val' is used as a boolean to indicate in-use or freed.
  138. unsigned inUse : 1;
  139. } osalMemHdrHdr_t;
  140. typedef union {
  141. /* Dummy variable so compiler forces structure to alignment of largest element while not wasting
  142. * space on targets when the halDataAlign_t is smaller than a UINT16.
  143. */
  144. halDataAlign_t alignDummy;
  145. uint16 val;
  146. osalMemHdrHdr_t hdr;
  147. } osalMemHdr_t;
  148. /* ------------------------------------------------------------------------------------------------
  149. * Local Variables
  150. * ------------------------------------------------------------------------------------------------
  151. */
  152. static __no_init osalMemHdr_t theHeap[MAXMEMHEAP / OSALMEM_HDRSZ];
  153. static __no_init osalMemHdr_t *ff1; // First free block in the small-block bucket.
  154. static uint8 osalMemStat; // Discrete status flags: 0x01 = kicked.
  155. #if OSALMEM_METRICS
  156. static uint16 blkMax; // Max cnt of all blocks ever seen at once.
  157. static uint16 blkCnt; // Current cnt of all blocks.
  158. static uint16 blkFree; // Current cnt of free blocks.
  159. static uint16 memAlo; // Current total memory allocated.
  160. static uint16 memMax; // Max total memory ever allocated at once.
  161. #endif
  162. #if OSALMEM_PROFILER
  163. #define OSALMEM_PROMAX 8
  164. /* The profiling buckets must differ by at least OSALMEM_MIN_BLKSZ; the
  165. * last bucket must equal the max alloc size. Set the bucket sizes to
  166. * whatever sizes necessary to show how your application is using memory.
  167. */
  168. static uint16 proCnt[OSALMEM_PROMAX] = {
  169. OSALMEM_SMALL_BLKSZ, 48, 112, 176, 192, 224, 256, 65535 };
  170. static uint16 proCur[OSALMEM_PROMAX] = { 0 };
  171. static uint16 proMax[OSALMEM_PROMAX] = { 0 };
  172. static uint16 proTot[OSALMEM_PROMAX] = { 0 };
  173. static uint16 proSmallBlkMiss;
  174. #endif
  175. /* ------------------------------------------------------------------------------------------------
  176. * Global Variables
  177. * ------------------------------------------------------------------------------------------------
  178. */
  179. #ifdef DPRINTF_HEAPTRACE
  180. extern int dprintf(const char *fmt, ...);
  181. #endif /* DPRINTF_HEAPTRACE */
  182. /**************************************************************************************************
  183. * @fn osal_mem_init
  184. *
  185. * @brief This function is the OSAL heap memory management initialization callback.
  186. *
  187. * input parameters
  188. *
  189. * None.
  190. *
  191. * output parameters
  192. *
  193. * None.
  194. *
  195. * @return None.
  196. */
  197. void osal_mem_init(void)
  198. {
  199. HAL_ASSERT(((OSALMEM_MIN_BLKSZ % OSALMEM_HDRSZ) == 0));
  200. HAL_ASSERT(((OSALMEM_LL_BLKSZ % OSALMEM_HDRSZ) == 0));
  201. HAL_ASSERT(((OSALMEM_SMALL_BLKSZ % OSALMEM_HDRSZ) == 0));
  202. #if OSALMEM_PROFILER
  203. (void)osal_memset(theHeap, OSALMEM_INIT, MAXMEMHEAP);
  204. #endif
  205. // Setup a NULL block at the end of the heap for fast comparisons with zero.
  206. theHeap[OSALMEM_LASTBLK_IDX].val = 0;
  207. // Setup the small-block bucket.
  208. ff1 = theHeap;
  209. ff1->val = OSALMEM_SMALLBLK_BUCKET; // Set 'len' & clear 'inUse' field.
  210. // Set 'len' & 'inUse' fields - this is a 'zero data bytes' lifetime allocation to block the
  211. // small-block bucket from ever being coalesced with the wilderness.
  212. theHeap[OSALMEM_SMALLBLK_HDRCNT].val = (OSALMEM_HDRSZ | OSALMEM_IN_USE);
  213. // Setup the wilderness.
  214. theHeap[OSALMEM_BIGBLK_IDX].val = OSALMEM_BIGBLK_SZ; // Set 'len' & clear 'inUse' field.
  215. #if ( OSALMEM_METRICS )
  216. /* Start with the small-block bucket and the wilderness - don't count the
  217. * end-of-heap NULL block nor the end-of-small-block NULL block.
  218. */
  219. blkCnt = blkFree = 2;
  220. #endif
  221. }
  222. /**************************************************************************************************
  223. * @fn osal_mem_kick
  224. *
  225. * @brief This function is the OSAL task initialization callback.
  226. * @brief Kick the ff1 pointer out past the long-lived OSAL Task blocks.
  227. * Invoke this once after all long-lived blocks have been allocated -
  228. * presently at the end of osal_init_system().
  229. *
  230. * input parameters
  231. *
  232. * None.
  233. *
  234. * output parameters
  235. *
  236. * None.
  237. *
  238. * @return None.
  239. */
  240. void osal_mem_kick(void)
  241. {
  242. halIntState_t intState;
  243. osalMemHdr_t *tmp = osal_mem_alloc(1);
  244. HAL_ASSERT((tmp != NULL));
  245. HAL_ENTER_CRITICAL_SECTION(intState); // Hold off interrupts.
  246. /* All long-lived allocations have filled the LL block reserved in the small-block bucket.
  247. * Set 'osalMemStat' so searching for memory in this bucket from here onward will only be done
  248. * for sizes meeting the OSALMEM_SMALL_BLKSZ criteria.
  249. */
  250. ff1 = tmp - 1; // Set 'ff1' to point to the first available memory after the LL block.
  251. osal_mem_free(tmp);
  252. osalMemStat = 0x01; // Set 'osalMemStat' after the free because it enables memory profiling.
  253. HAL_EXIT_CRITICAL_SECTION(intState); // Re-enable interrupts.
  254. }
  255. /**************************************************************************************************
  256. * @fn osal_mem_alloc
  257. *
  258. * @brief This function implements the OSAL dynamic memory allocation functionality.
  259. *
  260. * input parameters
  261. *
  262. * @param size - the number of bytes to allocate from the HEAP.
  263. *
  264. * output parameters
  265. *
  266. * None.
  267. *
  268. * @return None.
  269. */
  270. #ifdef DPRINTF_OSALHEAPTRACE
  271. void *osal_mem_alloc_dbg( uint16 size, const char *fname, unsigned lnum )
  272. #else /* DPRINTF_OSALHEAPTRACE */
  273. void *osal_mem_alloc( uint16 size )
  274. #endif /* DPRINTF_OSALHEAPTRACE */
  275. {
  276. osalMemHdr_t *prev = NULL;
  277. osalMemHdr_t *hdr;
  278. halIntState_t intState;
  279. uint8 coal = 0;
  280. size += OSALMEM_HDRSZ;
  281. // Calculate required bytes to add to 'size' to align to halDataAlign_t.
  282. if ( sizeof( halDataAlign_t ) == 2 )
  283. {
  284. size += (size & 0x01);
  285. }
  286. else if ( sizeof( halDataAlign_t ) != 1 )
  287. {
  288. const uint8 mod = size % sizeof( halDataAlign_t );
  289. if ( mod != 0 )
  290. {
  291. size += (sizeof( halDataAlign_t ) - mod);
  292. }
  293. }
  294. HAL_ENTER_CRITICAL_SECTION( intState ); // Hold off interrupts.
  295. // Smaller allocations are first attempted in the small-block bucket, and all long-lived
  296. // allocations are channeled into the LL block reserved within this bucket.
  297. if ((osalMemStat == 0) || (size <= OSALMEM_SMALL_BLKSZ))
  298. {
  299. hdr = ff1;
  300. }
  301. else
  302. {
  303. hdr = (theHeap + OSALMEM_BIGBLK_IDX);
  304. }
  305. do
  306. {
  307. if ( hdr->hdr.inUse )
  308. {
  309. coal = 0;
  310. }
  311. else
  312. {
  313. if ( coal != 0 )
  314. {
  315. #if ( OSALMEM_METRICS )
  316. blkCnt--;
  317. blkFree--;
  318. #endif
  319. prev->hdr.len += hdr->hdr.len;
  320. if ( prev->hdr.len >= size )
  321. {
  322. hdr = prev;
  323. break;
  324. }
  325. }
  326. else
  327. {
  328. if ( hdr->hdr.len >= size )
  329. {
  330. break;
  331. }
  332. coal = 1;
  333. prev = hdr;
  334. }
  335. }
  336. hdr = (osalMemHdr_t *)((uint8 *)hdr + hdr->hdr.len);
  337. if ( hdr->val == 0 )
  338. {
  339. hdr = NULL;
  340. break;
  341. }
  342. } while (1);
  343. if ( hdr != NULL )
  344. {
  345. uint16 tmp = hdr->hdr.len - size;
  346. // Determine whether the threshold for splitting is met.
  347. if ( tmp >= OSALMEM_MIN_BLKSZ )
  348. {
  349. // Split the block before allocating it.
  350. osalMemHdr_t *next = (osalMemHdr_t *)((uint8 *)hdr + size);
  351. next->val = tmp; // Set 'len' & clear 'inUse' field.
  352. hdr->val = (size | OSALMEM_IN_USE); // Set 'len' & 'inUse' field.
  353. #if ( OSALMEM_METRICS )
  354. blkCnt++;
  355. if ( blkMax < blkCnt )
  356. {
  357. blkMax = blkCnt;
  358. }
  359. memAlo += size;
  360. #endif
  361. }
  362. else
  363. {
  364. #if ( OSALMEM_METRICS )
  365. memAlo += hdr->hdr.len;
  366. blkFree--;
  367. #endif
  368. hdr->hdr.inUse = TRUE;
  369. }
  370. #if ( OSALMEM_METRICS )
  371. if ( memMax < memAlo )
  372. {
  373. memMax = memAlo;
  374. }
  375. #endif
  376. #if ( OSALMEM_PROFILER )
  377. #if !OSALMEM_PROFILER_LL
  378. if (osalMemStat != 0) // Don't profile until after the LL block is filled.
  379. #endif
  380. {
  381. uint8 idx;
  382. for ( idx = 0; idx < OSALMEM_PROMAX; idx++ )
  383. {
  384. if ( hdr->hdr.len <= proCnt[idx] )
  385. {
  386. break;
  387. }
  388. }
  389. proCur[idx]++;
  390. if ( proMax[idx] < proCur[idx] )
  391. {
  392. proMax[idx] = proCur[idx];
  393. }
  394. proTot[idx]++;
  395. /* A small-block could not be allocated in the small-block bucket.
  396. * When this occurs significantly frequently, increase the size of the
  397. * bucket in order to restore better worst case run times. Set the first
  398. * profiling bucket size in proCnt[] to the small-block bucket size and
  399. * divide proSmallBlkMiss by the corresponding proTot[] size to get % miss.
  400. * Best worst case time on TrasmitApp was achieved at a 0-15% miss rate
  401. * during steady state Tx load, 0% during idle and steady state Rx load.
  402. */
  403. if ((hdr->hdr.len <= OSALMEM_SMALL_BLKSZ) && (hdr >= (theHeap + OSALMEM_BIGBLK_IDX)))
  404. {
  405. proSmallBlkMiss++;
  406. }
  407. }
  408. (void)osal_memset((uint8 *)(hdr+1), OSALMEM_ALOC, (hdr->hdr.len - OSALMEM_HDRSZ));
  409. #endif
  410. if ((osalMemStat != 0) && (ff1 == hdr))
  411. {
  412. ff1 = (osalMemHdr_t *)((uint8 *)hdr + hdr->hdr.len);
  413. }
  414. hdr++;
  415. }
  416. HAL_EXIT_CRITICAL_SECTION( intState ); // Re-enable interrupts.
  417. #pragma diag_suppress=Pe767
  418. HAL_ASSERT(((halDataAlign_t)hdr % sizeof(halDataAlign_t)) == 0);
  419. #pragma diag_default=Pe767
  420. #ifdef DPRINTF_OSALHEAPTRACE
  421. dprintf("osal_mem_alloc(%u)->%lx:%s:%u\n", size, (unsigned) hdr, fname, lnum);
  422. #endif /* DPRINTF_OSALHEAPTRACE */
  423. return (void *)hdr;
  424. }
  425. /**************************************************************************************************
  426. * @fn osal_mem_free
  427. *
  428. * @brief This function implements the OSAL dynamic memory de-allocation functionality.
  429. *
  430. * input parameters
  431. *
  432. * @param ptr - A valid pointer (i.e. a pointer returned by osal_mem_alloc()) to the memory to free.
  433. *
  434. * output parameters
  435. *
  436. * None.
  437. *
  438. * @return None.
  439. */
  440. #ifdef DPRINTF_OSALHEAPTRACE
  441. void osal_mem_free_dbg(void *ptr, const char *fname, unsigned lnum)
  442. #else /* DPRINTF_OSALHEAPTRACE */
  443. void osal_mem_free(void *ptr)
  444. #endif /* DPRINTF_OSALHEAPTRACE */
  445. {
  446. osalMemHdr_t *hdr = (osalMemHdr_t *)ptr - 1;
  447. halIntState_t intState;
  448. #ifdef DPRINTF_OSALHEAPTRACE
  449. dprintf("osal_mem_free(%lx):%s:%u\n", (unsigned) ptr, fname, lnum);
  450. #endif /* DPRINTF_OSALHEAPTRACE */
  451. HAL_ASSERT(((uint8 *)ptr >= (uint8 *)theHeap) && ((uint8 *)ptr < (uint8 *)theHeap+MAXMEMHEAP));
  452. HAL_ASSERT(hdr->hdr.inUse);
  453. HAL_ENTER_CRITICAL_SECTION( intState ); // Hold off interrupts.
  454. hdr->hdr.inUse = FALSE;
  455. if (ff1 > hdr)
  456. {
  457. ff1 = hdr;
  458. }
  459. #if OSALMEM_PROFILER
  460. #if !OSALMEM_PROFILER_LL
  461. if (osalMemStat != 0) // Don't profile until after the LL block is filled.
  462. #endif
  463. {
  464. uint8 idx;
  465. for (idx = 0; idx < OSALMEM_PROMAX; idx++)
  466. {
  467. if (hdr->hdr.len <= proCnt[idx])
  468. {
  469. break;
  470. }
  471. }
  472. proCur[idx]--;
  473. }
  474. (void)osal_memset((uint8 *)(hdr+1), OSALMEM_REIN, (hdr->hdr.len - OSALMEM_HDRSZ) );
  475. #endif
  476. #if OSALMEM_METRICS
  477. memAlo -= hdr->hdr.len;
  478. blkFree++;
  479. #endif
  480. HAL_EXIT_CRITICAL_SECTION( intState ); // Re-enable interrupts.
  481. }
  482. #if OSALMEM_METRICS
  483. /*********************************************************************
  484. * @fn osal_heap_block_max
  485. *
  486. * @brief Return the maximum number of blocks ever allocated at once.
  487. *
  488. * @param none
  489. *
  490. * @return Maximum number of blocks ever allocated at once.
  491. */
  492. uint16 osal_heap_block_max( void )
  493. {
  494. return blkMax;
  495. }
  496. /*********************************************************************
  497. * @fn osal_heap_block_cnt
  498. *
  499. * @brief Return the current number of blocks now allocated.
  500. *
  501. * @param none
  502. *
  503. * @return Current number of blocks now allocated.
  504. */
  505. uint16 osal_heap_block_cnt( void )
  506. {
  507. return blkCnt;
  508. }
  509. /*********************************************************************
  510. * @fn osal_heap_block_free
  511. *
  512. * @brief Return the current number of free blocks.
  513. *
  514. * @param none
  515. *
  516. * @return Current number of free blocks.
  517. */
  518. uint16 osal_heap_block_free( void )
  519. {
  520. return blkFree;
  521. }
  522. /*********************************************************************
  523. * @fn osal_heap_mem_used
  524. *
  525. * @brief Return the current number of bytes allocated.
  526. *
  527. * @param none
  528. *
  529. * @return Current number of bytes allocated.
  530. */
  531. uint16 osal_heap_mem_used( void )
  532. {
  533. return memAlo;
  534. }
  535. #endif
  536. #if defined (ZTOOL_P1) || defined (ZTOOL_P2)
  537. /*********************************************************************
  538. * @fn osal_heap_high_water
  539. *
  540. * @brief Return the highest byte ever allocated in the heap.
  541. *
  542. * @param none
  543. *
  544. * @return Highest number of bytes ever used by the stack.
  545. */
  546. uint16 osal_heap_high_water( void )
  547. {
  548. #if ( OSALMEM_METRICS )
  549. return memMax;
  550. #else
  551. return MAXMEMHEAP;
  552. #endif
  553. }
  554. #endif
  555. /**************************************************************************************************
  556. */