DVBCore  20.3.0
DVBCore Documentation
stbheap.c
Go to the documentation of this file.
1 /*******************************************************************************
2  * Copyright © 2014 The DTVKit Open Software Foundation Ltd (www.dtvkit.org)
3  * Copyright © 2004 Ocean Blue Software Ltd
4  *
5  * This file is part of a DTVKit Software Component
6  * You are permitted to copy, modify or distribute this file subject to the terms
7  * of the DTVKit 1.0 Licence which can be found in licence.txt or at www.dtvkit.org
8  *
9  * THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
10  * EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES
11  * OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
12  *
13  * If you or your organisation is not a member of DTVKit then you have access
14  * to this source code outside of the terms of the licence agreement
15  * and you are expected to delete this and any associated files immediately.
16  * Further information on DTVKit, membership and terms can be found at www.dtvkit.org
17  *******************************************************************************/
25 #define _STBHEAP_C
26 
27 // uncomment this line to give direct COM port access
28 /* #define STB_DEBUG */
29 
30 // uncomment these lines to give heap debugging
31 /* #define DEBUG_HEAP */
32 /* #define DEBUG_HEAP_STATS */
33 /* #define DEBUG_APP_STATS */
34 /* #define DEBUG_HEAP_FULL */
35 /* #define DEBUG_APP_FULL */
36 
37 // uncomment these lines for additional heap debugging functionality
38 /* #define DEBUG_MEMCOPY */
39 /* #define DEBUG_TEST_APPHEAP */
40 /* #define DEBUG_TEST_STBHEAP */
41 // uncomment this line to disable memcpy debugs for function calls within this source file
42 /* #define IGNORE_MEMCOPY_IN_SOURCEFILE */
43 
44 
45 //---includes for this file----------------------------------------------------
46 // compiler library header files
47 #include <stdlib.h>
48 #include <stdio.h>
49 #include <string.h>
50 #include <stddef.h>
51 
52 // third party header files
53 
54 // Ocean Blue Software header files
55 
56 #include <techtype.h>
57 #include <dbgfuncs.h>
58 
59 #include "stbheap.h"
60 #include "stbhwmem.h"
61 
62 #ifdef PGW_ENABLED
63  #undef DEBUG_HEAP
64  #undef DEBUG_MEMCOPY
65  #undef DEBUG_TEST_APPHEAP
66  #undef DEBUG_TEST_STBHEAP
67  #define STB_DEBUG
68 /*#define PGW_DUMP_ON*/
69 /*#define PGW_LAST_ON*/
70 /* #include "prgwatch.h" */
71 #endif
72 
73 //---constant definitions for this file----------------------------------------
74 #ifdef STB_HEAP_PRINT_REQUIRED
75  #define STB_HEAP_PRINT(x) DEBUG_PRINTX_CONDITIONAL(DEBUG_STB_HEAP) x
76 #else
77  #ifdef STB_DEBUG
78  #define STB_HEAP_PRINT(x) STB_SPDebugWrite x
79  #else
80  #define STB_HEAP_PRINT(x)
81  #endif
82 #endif
83 
84 #ifdef DEBUG_MEMCOPY
85  #ifdef IGNORE_MEMCOPY_IN_SOURCEFILE
86  #ifdef memcpy
87  #undef memcpy
88  #endif
89  #endif
90 #endif
91 
92 #ifdef PGW_ENABLED
93 #define PGW_GOOD_MAGIC 0xdeadbeef
94 #define PGW_BAD_MAGIC 0xfeebdaed
95 #define LAST_FREED_MSK 0x7
96 #endif
97 
98 //---local typedef structs for this file---------------------------------------
99 
100 typedef struct s_stat_mem
101 {
102  U32BIT sum;
103  U32BIT total;
104  U32BIT maximum;
105 } S_STAT_MEM;
106 
107 #ifdef DEBUG_HEAP
108  #define HEAP_HDR_SIZE 16
109  #define HEAP_LIST_SIZE 10000
110  #define TEST_BUFF_SIZE 8
111 typedef struct
112 {
113  U8BIT *addr[HEAP_LIST_SIZE];
114  U32BIT size[HEAP_LIST_SIZE];
115  U16BIT sum;
116  U32BIT total;
117  U32BIT max;
118 } DEBUG_HEAP_STRUCT;
119 #endif
120 
121 #ifdef DEBUG_HEAP_STATS
122  #define SIZEOF_SIZE_FIELD 4
123 #endif
124 
125 typedef struct s_cache_registration
126 {
127  BOOLEAN (*callback_function)(void);
128  struct s_cache_registration *next_ptr;
129 }
131 
132 #ifdef PGW_ENABLED
133 typedef struct mem_info S_MEM_INFO;
134 struct mem_info
135 {
136  unsigned long magic;
137  size_t size;
138  char *filename;
139  int lineno;
140  #ifdef PGW_DUMP_ON
141  S_MEM_INFO *next;
142  S_MEM_INFO *prev;
143  #endif /*PGW_DUMP_ON*/
144  unsigned long align;
145 };
146 #endif
147 
148 //---local (static) variable declarations for this file------------------------
149 // (internal variables declared static to make them local)
150 
151 #ifdef DEBUG_HEAP
152 static DEBUG_HEAP_STRUCT heap_list;
153 static DEBUG_HEAP_STRUCT app_list;
154 static U8BIT test_buffer[TEST_BUFF_SIZE] = {0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef};
155 #endif
156 #ifdef DEBUG_HEAP_STATS
157 static S_STAT_MEM heap_stats;
158 #endif
159 #ifdef DEBUG_APP_STATS
160 static S_STAT_MEM app_stats;
161 #endif
162 
163 
164 static S_CACHE_REGISTRATION *cache_registration_ptr;
165 static S_CACHE_REGISTRATION *cache_marker_ptr;
166 
167 #ifdef PGW_ENABLED
168 #ifdef PGW_DUMP_ON
169 static S_MEM_INFO *sys_head = NULL;
170 static S_MEM_INFO *sys_tail = NULL;
171 static S_MEM_INFO *app_head = NULL;
172 static S_MEM_INFO *app_tail = NULL;
173 static void *pgw_mutex = NULL;
174 #elif defined(PGW_LAST_ON)
175 static S_MEM_INFO sys_last_alloc[LAST_FREED_MSK + 1];
176 static S_MEM_INFO app_last_alloc[LAST_FREED_MSK + 1];
177 static unsigned int sys_alloc_cnt = 0;
178 static unsigned int app_alloc_cnt = 0;
179 static S_MEM_INFO sys_last_freed[LAST_FREED_MSK + 1];
180 static S_MEM_INFO app_last_freed[LAST_FREED_MSK + 1];
181 static unsigned int sys_freed_cnt = 0;
182 static unsigned int app_freed_cnt = 0;
183 #endif /*PGW_DUMP_ON*/
184 #endif
185 
186 //---local function prototypes for this file-----------------------------------
187 // (internal functions declared static to make them local)
188 #ifdef DEBUG_MEMCOPY
189 static void CheckHeapMemory(U8BIT *destn, U16BIT nbytes);
190 #endif
191 
192 //---local function definitions------------------------------------------------
193 
194 //---global function definitions-----------------------------------------------
195 
196 void STB_HeapInitialise(void)
197 {
198 #ifdef PGW_ENABLED
199  #ifdef PGW_DUMP_ON
200  if (pgw_mutex == NULL)
201  {
202  pgw_mutex = STB_OSCreateMutex();
203  ASSERT( pgw_mutex != NULL );
204  }
205  #endif /*PGW_DUMP_ON*/
206 #endif
207 }
208 
220 #ifndef PGW_ENABLED
221 void* STB_GetMemory(U32BIT bytes)
222 {
223  void *ret_addr;
224 
225 // FUNCTION_START(STB_GetMemory);
226 
227  ASSERT(bytes > 0);
228 
229  #ifndef DEBUG_HEAP
230  {
231  #ifndef DEBUG_HEAP_STATS
232  ret_addr = STB_MEMGetSysRAM(bytes);
233  #ifdef DEBUG_HEAP_FULL
234  if (ret_addr == NULL)
235  {
236  STB_HEAP_PRINT(("Heap Malloc FAILED"));
237  }
238  #endif
239  #else
240  {
241  U8BIT *blk_addr;
242  U32BIT blk_size;
243 
244  blk_size = bytes + SIZEOF_SIZE_FIELD;
245  blk_addr = STB_MEMGetSysRAM(blk_size);
246  if (blk_addr != NULL)
247  {
248  *(U32BIT *)blk_addr = blk_size;
249  ret_addr = blk_addr + SIZEOF_SIZE_FIELD;
250 
251  heap_stats.sum++;
252  heap_stats.total += blk_size;
253  if (heap_stats.total > heap_stats.maximum)
254  {
255  heap_stats.maximum = heap_stats.total;
256  }
257  }
258  else
259  {
260  ret_addr = NULL;
261  }
262  STB_HEAP_PRINT(("M(h): % 6d @ %p (num=% 5d tot=% 7d max=% 7d)", bytes, ret_addr, heap_stats.sum, heap_stats.total, heap_stats.maximum));
263  }
264  #endif
265  }
266  #else
267  {
268  U16BIT count;
269  U8BIT *blk_ptr;
270  U32BIT blk_size;
271 
272  // malloc bigger block
273  blk_size = (bytes + (TEST_BUFF_SIZE * 2));
274  blk_ptr = (U8BIT *)STB_MEMGetSysRAM(blk_size);
275  if (blk_ptr != NULL)
276  {
277  // insert test pattern and calc return address
278  memcpy((void *)blk_ptr, (void *)test_buffer, TEST_BUFF_SIZE);
279  memcpy((void *)(blk_ptr + bytes + TEST_BUFF_SIZE), (void *)test_buffer, TEST_BUFF_SIZE);
280  ret_addr = (void *)(blk_ptr + TEST_BUFF_SIZE);
281 
282  // update heap stats
283  for (count = 0; count < HEAP_LIST_SIZE; count++)
284  {
285  if (heap_list.addr[count] == NULL)
286  {
287  heap_list.addr[count] = ret_addr;
288  heap_list.size[count] = bytes;
289  heap_list.sum++;
290  heap_list.total += (bytes + (TEST_BUFF_SIZE * 2));
291  if (heap_list.total > heap_list.max)
292  heap_list.max = heap_list.total;
293 
294  #ifdef DEBUG_HEAP_STATS
295  STB_HEAP_PRINT(("Malloc(heap) : %6lu @ %p - num=%3u tot=%6lu hi=%6lu",
296  bytes, ret_addr, heap_list.sum, heap_list.total, heap_list.max));
297  #endif
298 
299  break;
300  }
301  } //eof for(count...)
302 
303  if (count >= HEAP_LIST_SIZE)
304  {
305  STB_HEAP_PRINT(("Malloc(heap) : ERROR: list full"));
306  return(NULL);
307  }
308  }
309  else
310  {
311  // malloc failed!
312  STB_HEAP_PRINT(("Malloc(heap) : ERROR: refused %lu bytes", bytes));
313  ret_addr = NULL;
314  }
315  }
316  #endif
317 
318  ASSERT(ret_addr != NULL);
319 
320 // FUNCTION_FINISH(STB_GetMemory);
321 
322  return(ret_addr);
323 }
324 
336 void STB_FreeMemory(void *addr)
337 {
338  // FUNCTION_START(STB_FreeMemory);
339 
340  #ifndef DEBUG_HEAP
341  {
342  #ifndef DEBUG_HEAP_STATS
343  STB_MEMFreeSysRAM(addr);
344  #else
345  if (addr != NULL)
346  {
347  U8BIT *blk_addr;
348  U32BIT blk_size;
349 #if defined (STB_HEAP_PRINT_REQUIRED) || defined (STB_DEBUG)
350  U32BIT bytes;
351 #endif
352 
353  blk_addr = (U8BIT *)addr - SIZEOF_SIZE_FIELD;
354  blk_size = *(U32BIT *)blk_addr;
355 #if defined (STB_HEAP_PRINT_REQUIRED) || defined (STB_DEBUG)
356  bytes = blk_size - SIZEOF_SIZE_FIELD;
357 #endif
358 
359  STB_MEMFreeSysRAM(blk_addr);
360 
361  if (heap_stats.sum > 0)
362  {
363  heap_stats.sum--;
364  }
365  if (heap_stats.total > blk_size)
366  {
367  heap_stats.total -= blk_size;
368  }
369  else
370  {
371  heap_stats.total = 0;
372  }
373  STB_HEAP_PRINT(("F(h): % 6d @ %p (num=% 5d tot=% 7d max=% 7d)", bytes, addr, heap_stats.sum, heap_stats.total, heap_stats.maximum));
374  }
375  #endif
376  }
377  #else
378  {
379  U16BIT count;
380  U8BIT *blk_ptr;
381 
382  if (addr != NULL)
383  {
384  // update heap stats
385  for (count = 0; count < HEAP_LIST_SIZE; count++)
386  {
387  if (heap_list.addr[count] == addr)
388  {
389  // found it - calculate real block address
390  blk_ptr = ((U8BIT *)addr - TEST_BUFF_SIZE);
391 
392  // check for corruption
393  if ((memcmp((void *)blk_ptr, (void *)test_buffer, TEST_BUFF_SIZE) != 0) ||
394  (memcmp((void *)(blk_ptr + heap_list.size[count] + TEST_BUFF_SIZE), (void *)test_buffer, TEST_BUFF_SIZE) != 0))
395  {
396  // corrupted!
397  STB_HEAP_PRINT(("Free(heap) : ERROR: this block corrupt..."));
398  return;
399  }
400 
401  heap_list.sum--;
402  heap_list.total -= (heap_list.size[count] + (TEST_BUFF_SIZE * 2));
403 
404  #ifdef DEBUG_HEAP_STATS
405  STB_HEAP_PRINT(("Free(heap) : %6lu @ %p - num=%3u tot=%6lu hi=%6lu",
406  heap_list.size[count], addr, heap_list.sum, heap_list.total,
407  heap_list.max));
408  #endif
409 
410  // this must be last because it releases the entry in the heap list for re-use
411  heap_list.addr[count] = NULL;
412  break;
413  }
414  } //eof for(count...)
415 
416  if (count >= HEAP_LIST_SIZE)
417  {
418  // not malloced!
419  STB_HEAP_PRINT(("Free(heap) : ERROR: unallocated pointer: %p", addr));
420  return;
421  }
422  }
423  else
424  {
425  // NULL address!
426  STB_HEAP_PRINT(("Free(heap) : ERROR: NULL pointer"));
427  blk_ptr = NULL;
428  }
429 
430  // free block
431  STB_MEMFreeSysRAM((void *)blk_ptr);
432  }
433  #endif
434 // FUNCTION_FINISH(STB_FreeMemory);
435 }
436 
437 #ifdef DEBUG_HEAP
438 static void* DbgResizeMemory(void *ptr, U32BIT new_num_bytes, DEBUG_HEAP_STRUCT *hp_ptr )
439 {
440  U8BIT *blk_ptr;
441  U16BIT count;
442 
443  // update heap stats
444  for (count = 0; count != HEAP_LIST_SIZE; count++)
445  {
446  if (hp_ptr->addr[count] == ptr)
447  {
448  // found it - calculate real block address
449  blk_ptr = ((U8BIT *)ptr - TEST_BUFF_SIZE);
450 
451  // check for corruption
452  if ((memcmp((void *)blk_ptr, (void *)test_buffer, TEST_BUFF_SIZE) != 0) ||
453  (memcmp((void *)(blk_ptr + hp_ptr->size[count] + TEST_BUFF_SIZE), (void *)test_buffer, TEST_BUFF_SIZE) != 0))
454  {
455  // corrupted!
456  STB_HEAP_PRINT(("Realloc(heap) : ERROR: this block corrupt.sz=%d, new_sz=%d", hp_ptr->size[count], new_num_bytes));
457  }
458 
459  if (new_num_bytes >= hp_ptr->size[count])
460  {
461  hp_ptr->total += new_num_bytes - hp_ptr->size[count];
462  if (hp_ptr->total > hp_ptr->max)
463  hp_ptr->max = hp_ptr->total;
464  }
465  else
466  {
467  hp_ptr->total -= hp_ptr->size[count] - new_num_bytes;
468  }
469 
470  #ifdef DEBUG_HEAP_STATS
471  STB_HEAP_PRINT(("Realloc(heap) : %6lu @ %p - num=%3u tot=%6lu hi=%6lu",
472  hp_ptr->size[count], addr, hp_ptr->sum, hp_ptr->total,
473  hp_ptr->max));
474  #endif
475 
476  blk_ptr = STB_MEMResizeSysRAM(blk_ptr, new_num_bytes + (TEST_BUFF_SIZE * 2));
477  if (blk_ptr != NULL)
478  {
479  if (memcmp((void *)blk_ptr, (void *)test_buffer, TEST_BUFF_SIZE) != 0)
480  {
481  STB_HEAP_PRINT(("Realloc(heap) : ERROR: Lost header : %p", blk_ptr));
482  }
483  // place test block at new end position
484  memcpy((void *)(blk_ptr + new_num_bytes + TEST_BUFF_SIZE), (void *)test_buffer, TEST_BUFF_SIZE);
485  hp_ptr->size[count] = new_num_bytes;
486  blk_ptr += TEST_BUFF_SIZE;
487  }
488  hp_ptr->addr[count] = blk_ptr;
489  break;
490  }
491  } //eof for(count...)
492 
493  if (count == HEAP_LIST_SIZE)
494  {
495  // not malloced!
496  STB_HEAP_PRINT(("Realloc(heap) : ERROR: unallocated pointer: %p", ptr));
497  blk_ptr = STB_GetMemory(new_num_bytes);
498  }
499  return blk_ptr;
500 }
501 
502 #endif /*DEBUG_HEAP*/
503 
504 #ifdef DEBUG_HEAP_STATS
505 static void* StatResizeMemory(void *ptr, U32BIT new_num_bytes, S_STAT_MEM *stat_ptr )
506 {
507  U8BIT *blk_ptr;
508  U32BIT blk_size;
509  blk_ptr = (U8BIT *)ptr - SIZEOF_SIZE_FIELD;
510  blk_size = *(U32BIT *)blk_ptr;
511  blk_size -= SIZEOF_SIZE_FIELD;
512  if (blk_size < new_num_bytes)
513  {
514  stat_ptr->total += new_num_bytes - blk_size;
515  if (stat_ptr->total > stat_ptr->maximum)
516  stat_ptr->maximum = stat_ptr->total;
517  }
518  else
519  {
520  if (stat_ptr->total > (blk_size - new_num_bytes))
521  {
522  stat_ptr->total -= blk_size - new_num_bytes;
523  }
524  else
525  {
526  stat_ptr->total = 0;
527  }
528  }
529  blk_ptr = STB_MEMResizeSysRAM(blk_ptr, new_num_bytes + SIZEOF_SIZE_FIELD);
530  *(U32BIT *)blk_ptr = new_num_bytes + SIZEOF_SIZE_FIELD;
531  blk_ptr += SIZEOF_SIZE_FIELD;
532  return blk_ptr;
533 }
534 
535 #endif /*DEBUG_HEAP_STATS*/
536 
550 void* STB_ResizeMemory(void *ptr, U32BIT new_num_bytes)
551 {
552  void *retval;
553 
554 // FUNCTION_START(STB_ResizeMemory);
555 
556  retval = NULL;
557 
558  if (new_num_bytes == 0)
559  {
560  if (ptr != NULL)
561  {
562  STB_FreeMemory(ptr);
563  }
564  }
565  else
566  {
567  if (ptr == NULL)
568  {
569  retval = STB_GetMemory(new_num_bytes);
570  }
571  else
572  {
573  #ifndef DEBUG_HEAP
574  #ifndef DEBUG_HEAP_STATS
575  retval = STB_MEMResizeSysRAM(ptr, new_num_bytes);
576  #else
577  retval = StatResizeMemory(ptr, new_num_bytes, &heap_stats );
578  #endif
579  #else
580  retval = DbgResizeMemory(ptr, new_num_bytes, &heap_list);
581  #endif
582  }
583  }
584 // FUNCTION_FINISH(STB_ResizeMemory);
585  return(retval);
586 }
587 
588 #endif /*ifndef PGW_ENABLED*/
589 
590 
591 //**************************************************************************************************
592 // THE FOLLOWING FUNCTIONS PROVIDE MEMORY MANAGEMENT FOR THE APPLICATION TASK. THEY USE A
593 // DIFFERENT HEAP TO THE STB & HW LAYERS TO AVOID THE POSSIBILITY OF THE APPLICATION TAKING TOO MUCH
594 // MEMORY AND CRASHING THE LOWER LAYERS
595 //**************************************************************************************************
596 
597 static BOOLEAN AppFreeCachedMemory(void)
598 {
599  BOOLEAN retval;
601 
602  retval = FALSE;
603 
604  // Do we have any caches registered?
605  if (cache_marker_ptr != NULL)
606  {
607  // If so then set rolling pointer to the next cache registration
608  ptr = cache_marker_ptr;
609 
610  // This loop will attempt to free memory from each registered cache, stopping when one of
611  // them has succeeded, or when all of them have failed.
612  do
613  {
614  // Access the callback function - it will return TRUE if memory was freed
615  retval = (*ptr->callback_function)();
616 
617  // Advance the rolling pointer...
618  ptr = ptr->next_ptr;
619  // ... and roll back to start of registration link-list if at end.
620  if (ptr == NULL)
621  {
622  ptr = cache_registration_ptr;
623  }
624 
625  // If the callback function managed to free some memory, then adjust the marker pointer -
626  // the next call to this function will access the next callback function.
627  if (retval == TRUE)
628  {
629  // NB - we will inherently now leave this do-while loop
630  cache_marker_ptr = ptr;
631  }
632  }
633  while (ptr != cache_marker_ptr);
634  }
635 
636  return(retval);
637 }
638 
650 #ifndef PGW_ENABLED
651 void* STB_AppGetMemory(U32BIT bytes)
652 {
653  void *ret_addr;
654 
655 // FUNCTION_START(STB_AppGetMemory);
656 
657  ASSERT(bytes > 0);
658 
659  #ifndef DEBUG_HEAP
660  {
661  #ifndef DEBUG_APP_STATS
662  ret_addr = STB_MEMGetAppRAM(bytes);
663  #ifdef DEBUG_APP_FULL
664  if (ret_addr == NULL)
665  {
666  STB_HEAP_PRINT(("APP Heap Malloc FAILED"));
667  }
668  #endif
669  #else
670  {
671  U8BIT *blk_addr;
672  U32BIT blk_size;
673 
674  blk_size = bytes + SIZEOF_SIZE_FIELD;
675  blk_addr = STB_MEMGetAppRAM(blk_size);
676  if (blk_addr != NULL)
677  {
678  *(U32BIT *)blk_addr = blk_size;
679  ret_addr = blk_addr + SIZEOF_SIZE_FIELD;
680 
681  app_stats.sum++;
682  app_stats.total += blk_size;
683  if (app_stats.total > app_stats.maximum)
684  {
685  app_stats.maximum = app_stats.total;
686  }
687  }
688  else
689  {
690  ret_addr = NULL;
691  }
692 // STB_HEAP_PRINT(("M(a): % 6d @ %p (num=% 5d tot=% 7d max=% 7d)", bytes, ret_addr, app_stats.sum, app_stats.total, app_stats.maximum));
693  }
694  #endif
695  while ((ret_addr == NULL) && (bytes > 0))
696  {
697  if (AppFreeCachedMemory() == FALSE)
698  {
699  break;
700  }
701  ret_addr = STB_MEMGetAppRAM(bytes);
702  }
703  }
704  #else
705  {
706  U16BIT count;
707  U8BIT *blk_ptr;
708  U32BIT blk_size;
709 
710  // malloc bigger block
711  blk_size = (bytes + (TEST_BUFF_SIZE * 2));
712  blk_ptr = (U8BIT *)STB_MEMGetAppRAM(blk_size);
713  while ((blk_ptr == NULL) && (bytes > 0))
714  {
715  if (AppFreeCachedMemory() == FALSE)
716  {
717  break;
718  }
719  blk_ptr = (U8BIT *)STB_MEMGetAppRAM(blk_size);
720  }
721  if (blk_ptr != NULL)
722  {
723  // insert test pattern and calc return address
724  memcpy((void *)blk_ptr, (void *)test_buffer, TEST_BUFF_SIZE);
725  memcpy((void *)(blk_ptr + bytes + TEST_BUFF_SIZE), (void *)test_buffer, TEST_BUFF_SIZE);
726  ret_addr = (void *)(blk_ptr + TEST_BUFF_SIZE);
727 
728  // update heap stats
729  for (count = 0; count < HEAP_LIST_SIZE; count++)
730  {
731  if (app_list.addr[count] == NULL)
732  {
733  app_list.addr[count] = ret_addr;
734  app_list.size[count] = bytes;
735  app_list.sum++;
736  app_list.total += (bytes + (TEST_BUFF_SIZE * 2));
737  if (app_list.total > app_list.max)
738  app_list.max = app_list.total;
739 
740  #ifdef DEBUG_APP_STATS
741  STB_HEAP_PRINT(("Malloc(app) : %6lu @ %p - num=%3u tot=%6lu hi=%6lu",
742  bytes, ret_addr, app_list.sum, app_list.total, app_list.max));
743  #endif
744  break;
745  }
746  } //eof for(count...)
747 
748  if (count >= HEAP_LIST_SIZE)
749  {
750  STB_HEAP_PRINT(("Malloc(app) : ERROR: list full"));
751  return(NULL);
752  }
753  }
754  else
755  {
756  // malloc failed!
757  STB_HEAP_PRINT(("Malloc(app) : ERROR: refused %lu bytes", bytes));
758  ret_addr = NULL;
759  }
760  }
761  #endif
762 
763  ASSERT(ret_addr != NULL);
764 
765 // FUNCTION_FINISH(STB_AppGetMemory);
766 
767  return(ret_addr);
768 }
769 
781 void STB_AppFreeMemory(void *addr)
782 {
783 // FUNCTION_START(STB_AppFreeMemory);
784 
785  #ifndef DEBUG_HEAP
786  {
787  #ifndef DEBUG_APP_STATS
788  STB_MEMFreeAppRAM(addr);
789  #else
790  if (addr != NULL)
791  {
792  U8BIT *blk_addr;
793  U32BIT blk_size;
794 // U32BIT bytes;
795 
796  blk_addr = (U8BIT *)addr - SIZEOF_SIZE_FIELD;
797  blk_size = *(U32BIT *)blk_addr;
798 // bytes = blk_size - SIZEOF_SIZE_FIELD;
799 
800  STB_MEMFreeAppRAM(blk_addr);
801 
802  if (app_stats.sum > 0)
803  {
804  app_stats.sum--;
805  }
806  if (app_stats.total > blk_size)
807  {
808  app_stats.total -= blk_size;
809  }
810  else
811  {
812  app_stats.total = 0;
813  }
814 // STB_HEAP_PRINT(("F(a): % 6d @ %p (num=% 5d tot=% 7d max=% 7d)", bytes, addr, app_stats.sum, app_stats.total, app_stats.maximum));
815  }
816  #endif
817  }
818  #else
819  {
820  U16BIT count;
821  U8BIT *blk_ptr;
822 
823  if (addr != NULL)
824  {
825  // update heap stats
826  for (count = 0; count < HEAP_LIST_SIZE; count++)
827  {
828  if (app_list.addr[count] == addr)
829  {
830  // found it - calculate real block address
831  blk_ptr = ((U8BIT *)addr - TEST_BUFF_SIZE);
832 
833  // check for corruption
834  if ((memcmp((void *)blk_ptr, (void *)test_buffer, TEST_BUFF_SIZE) != 0) ||
835  (memcmp((void *)(blk_ptr + app_list.size[count] + TEST_BUFF_SIZE), (void *)test_buffer, TEST_BUFF_SIZE) != 0))
836  {
837  // corrupted!
838  STB_HEAP_PRINT(("Free(app) : ERROR: this block corrupt..."));
839  return;
840  }
841 
842  app_list.sum--;
843  app_list.total -= (app_list.size[count] + (TEST_BUFF_SIZE * 2));
844 
845  #ifdef DEBUG_APP_STATS
846  STB_HEAP_PRINT(("Free(app) : %6lu @ %p - num=%3u tot=%6lu hi=%6lu",
847  app_list.size[count], addr, app_list.sum, app_list.total,
848  app_list.max));
849  #endif
850 
851  // this must be last because it releases the entry in the heap list for re-use
852  app_list.addr[count] = NULL;
853  break;
854  }
855  } //eof for(count...)
856 
857  if (count >= HEAP_LIST_SIZE)
858  {
859  // not malloced!
860  STB_HEAP_PRINT(("Free(app) : ERROR: unallocated pointer: %p", addr));
861  return;
862  }
863  }
864  else
865  {
866  // NULL address!
867  STB_HEAP_PRINT(("Free(app) : ERROR: NULL pointer"));
868  blk_ptr = NULL;
869  }
870 
871  // free block
872  STB_MEMFreeAppRAM((void *)blk_ptr);
873  }
874  #endif
875 // FUNCTION_FINISH(STB_AppFreeMemory);
876 }
877 
891 void* STB_AppResizeMemory(void *ptr, U32BIT new_num_bytes)
892 {
893  void *retval;
894 
895 // FUNCTION_START(STB_AppResizeMemory);
896 
897  retval = NULL;
898 
899  if (new_num_bytes == 0)
900  {
901  if (ptr != NULL)
902  {
903  STB_AppFreeMemory(ptr);
904  }
905  }
906  else
907  {
908  if (ptr == NULL)
909  {
910  retval = STB_AppGetMemory(new_num_bytes);
911  }
912  else
913  {
914  #ifndef DEBUG_HEAP
915  #ifndef DEBUG_APP_STATS
916  retval = STB_MEMResizeSysRAM(ptr, new_num_bytes);
917  #else
918  retval = StatResizeMemory(ptr, new_num_bytes, &app_stats );
919  #endif
920  #else
921  retval = DbgResizeMemory(ptr, new_num_bytes, &app_list);
922  #endif
923  }
924  }
925 // FUNCTION_FINISH(STB_AppResizeMemory);
926  return(retval);
927 }
928 
929 #endif /*ifndef PGW_ENABLED*/
930 
931 void STB_AppRegisterCacheFreeFunction(BOOLEAN (*callback_function)(void))
932 {
934 
935  FUNCTION_START(STB_AppRegisterCacheFreeFunction);
936 
937  if (callback_function != NULL)
938  {
939  // Go through cache registrations ensuring that the callback function has not already
940  // been registered
941  ptr = cache_registration_ptr;
942 
943  while (ptr != NULL)
944  {
945  if (ptr->callback_function == callback_function)
946  {
947  break;
948  }
949  }
950 
951  // Pointer is NULL only if this is a new function (address)
952  if (ptr == NULL)
953  {
954  // Generate a new registration record, populate it, ans add it to the link-list.
955  #ifndef PGW_ENABLED
957  #else
958  ptr = (S_CACHE_REGISTRATION *)STB_AppGetMemoryPGW(sizeof(S_CACHE_REGISTRATION), __FILE__, __LINE__);
959  #endif
960 
961  if (ptr != NULL)
962  {
963  ptr->callback_function = callback_function;
964  ptr->next_ptr = cache_registration_ptr;
965 
966  cache_registration_ptr = ptr;
967 
968  // If this is the first registration, then set up the rolling pointer (used for access)
969  if (cache_marker_ptr == NULL)
970  {
971  cache_marker_ptr = cache_registration_ptr;
972  }
973  }
974  }
975  }
976 
977  FUNCTION_FINISH(STB_AppRegisterCacheFreeFunction);
978 }
979 
980 //**************************************************************************************************
981 //
982 // PGW (PROGRAM WATCH) - For Tracking Memory Allocation
983 //
984 //**************************************************************************************************
985 
986 #ifdef PGW_ENABLED
987 /*!**************************************************************************
988  * @brief Allocate a new system memory buffer (with tracking).
989  * @param bytes Size of buffer in bytes
990  * @param filename Name of file where allocation takes place
991  * @param lineno Line number in file
992  * @return A pointer to the newly allocated buffer, NULL if failed
993  ****************************************************************************/
994 void* STB_GetMemoryPGW(U32BIT size, char *filename, int lineno)
995 {
996  S_MEM_INFO *mem_info;
997  void *buffer = NULL;
998 
999  //FUNCTION_START(STB_GetMemoryPGW);
1000 
1001  mem_info = (S_MEM_INFO *)STB_MEMGetSysRAM(sizeof(S_MEM_INFO) + size - sizeof(unsigned long));
1002  if (mem_info != NULL)
1003  {
1004  mem_info->magic = PGW_GOOD_MAGIC;
1005  mem_info->size = size;
1006  mem_info->filename = filename;
1007  mem_info->lineno = lineno;
1008 
1009  #ifdef PGW_DUMP_ON
1010  ASSERT( pgw_mutex != NULL );
1011  mem_info->next = NULL;
1012  STB_OSMutexLock(pgw_mutex);
1013  mem_info->prev = sys_tail;
1014  if (sys_tail != NULL)
1015  {
1016  sys_tail->next = mem_info;
1017  }
1018  sys_tail = mem_info;
1019  if (sys_head == NULL)
1020  {
1021  sys_head = sys_tail;
1022  }
1023  STB_OSMutexUnlock(pgw_mutex);
1024  #elif defined(PGW_LAST_ON)
1025  sys_last_alloc[sys_alloc_cnt & LAST_FREED_MSK] = *mem_info;
1026  sys_alloc_cnt++;
1027  #endif /*PGW_DUMP_ON*/
1028 
1029  buffer = &mem_info->align;
1030  }
1031  else
1032  {
1033  STB_HEAP_PRINT(("PGW: Cannot allocate %d bytes at %s:%d\n", size,
1034  filename, lineno));
1035  }
1036 
1037  //FUNCTION_FINISH(STB_GetMemoryPGW);
1038 
1039  return buffer;
1040 }
1041 
1042 /*!**************************************************************************
1043  * @brief Reallocates a system memory buffer (with tracking).
1044  * @param buffer Pointer to current buffer
1045  * @param bytes Size of buffer in bytes
1046  * @param filename Name of file where allocation takes place
1047  * @param lineno Line number in file
1048  * @return A pointer to the newly allocated buffer, NULL if failed
1049  ****************************************************************************/
1050 void* STB_ResizeMemoryPGW(void *buffer, U32BIT size, char *filename, int lineno)
1051 {
1052  S_MEM_INFO *mem_info;
1053 
1054  //FUNCTION_START(STB_ResizeMemoryPGW);
1055 
1056  if (size == 0)
1057  {
1058  if (buffer != NULL)
1059  {
1060  STB_FreeMemoryPGW(buffer, filename, lineno);
1061  buffer = NULL;
1062  }
1063  }
1064  else if (buffer == NULL)
1065  {
1066  buffer = STB_GetMemoryPGW(size, filename, lineno);
1067  }
1068  else
1069  {
1070  mem_info = (S_MEM_INFO *)((char *)buffer - offsetof(S_MEM_INFO, align));
1071  if (mem_info->magic != PGW_GOOD_MAGIC)
1072  {
1073  STB_HEAP_PRINT(("PGW: Reallocating invalid sys pointer %p at %s:%d\n", buffer,
1074  filename, lineno));
1075  STB_MemoryDumpPGW(0);
1076  }
1077  else
1078  {
1079  mem_info->magic = PGW_BAD_MAGIC;
1080 
1081  #ifdef PGW_DUMP_ON
1082  /* Remove the memory from the list */
1083  ASSERT( pgw_mutex != NULL );
1084  STB_OSMutexLock(pgw_mutex);
1085  if (sys_tail == mem_info)
1086  {
1087  sys_tail = sys_tail->prev;
1088  }
1089  if (sys_head == mem_info)
1090  {
1091  sys_head = sys_head->next;
1092  }
1093  if (mem_info->next != NULL)
1094  {
1095  mem_info->next->prev = mem_info->prev;
1096  }
1097 
1098  if (mem_info->prev != NULL)
1099  {
1100  mem_info->prev->next = mem_info->next;
1101  }
1102  STB_OSMutexUnlock(pgw_mutex);
1103  #endif /*PGW_DUMP_ON*/
1104 
1105  /* Realloc the memory and add it back into the list */
1106  mem_info = STB_MEMResizeSysRAM(mem_info, sizeof(S_MEM_INFO) + size - sizeof(unsigned long));
1107 
1108  mem_info->magic = PGW_GOOD_MAGIC;
1109  mem_info->size = size;
1110  mem_info->filename = filename;
1111  mem_info->lineno = lineno;
1112 
1113  #ifdef PGW_DUMP_ON
1114  mem_info->next = NULL;
1115  STB_OSMutexLock(pgw_mutex);
1116  mem_info->prev = sys_tail;
1117  if (sys_tail != NULL)
1118  {
1119  sys_tail->next = mem_info;
1120  }
1121  sys_tail = mem_info;
1122  if (sys_head == NULL)
1123  {
1124  sys_head = sys_tail;
1125  }
1126  STB_OSMutexUnlock(pgw_mutex);
1127  #elif defined(PGW_LAST_ON)
1128  sys_last_alloc[sys_alloc_cnt & LAST_FREED_MSK] = *mem_info;
1129  sys_alloc_cnt++;
1130  #endif /*PGW_DUMP_ON*/
1131 
1132  buffer = &mem_info->align;
1133  }
1134  }
1135 
1136  //FUNCTION_FINISH(STB_ResizeMemoryPGW);
1137 
1138  return buffer;
1139 }
1140 
1141 /*!**************************************************************************
1142  * @brief Free buffer that was allocated using PGW_sys_malloc or STB_ResizeMemoryPGW
1143  * @param buffer A pointer to the buffer
1144  * @return None.
1145  ****************************************************************************/
1146 void STB_FreeMemoryPGW(void *buffer, char *filename, int lineno)
1147 {
1148  S_MEM_INFO *mem_info;
1149 
1150  //FUNCTION_START(STB_FreeMemoryPGW);
1151 
1152  if (buffer != NULL)
1153  {
1154  mem_info = (S_MEM_INFO *)((char *)buffer - offsetof(S_MEM_INFO, align));
1155  if (mem_info->magic != PGW_GOOD_MAGIC)
1156  {
1157  STB_HEAP_PRINT(("PGW: Freeing invalid pointer %p at %s:%d\n", buffer,
1158  filename, lineno));
1159  STB_MemoryDumpPGW(0);
1160  }
1161  else
1162  {
1163  #ifdef PGW_DUMP_ON
1164  mem_info->magic = PGW_BAD_MAGIC;
1165 
1166  ASSERT( pgw_mutex != NULL );
1167  STB_OSMutexLock(pgw_mutex);
1168  if (sys_tail == mem_info)
1169  {
1170  sys_tail = sys_tail->prev;
1171  }
1172  if (sys_head == mem_info)
1173  {
1174  sys_head = sys_head->next;
1175  }
1176  if (mem_info->next != NULL)
1177  {
1178  mem_info->next->prev = mem_info->prev;
1179  }
1180 
1181  if (mem_info->prev != NULL)
1182  {
1183  mem_info->prev->next = mem_info->next;
1184  }
1185  STB_OSMutexUnlock(pgw_mutex);
1186  #elif defined(PGW_LAST_ON)
1187  sys_last_freed[sys_freed_cnt & LAST_FREED_MSK] = *mem_info;
1188  sys_freed_cnt++;
1189  mem_info->magic = PGW_BAD_MAGIC;
1190  #endif /*PGW_DUMP_ON*/
1191 
1192  STB_MEMFreeSysRAM(mem_info);
1193  }
1194  }
1195 
1196  //FUNCTION_FINISH(STB_FreeMemoryPGW);
1197 }
1198 
1199 /*!**************************************************************************
1200  * @brief Allocate a new app memory buffer (with tracking).
1201  * @param bytes Size of buffer in bytes
1202  * @param filename Name of file where allocation takes place
1203  * @param lineno Line number in file
1204  * @return A pointer to the newly allocated buffer, NULL if failed
1205  ****************************************************************************/
1206 void* STB_AppGetMemoryPGW(U32BIT size, char *filename, int lineno)
1207 {
1208  S_MEM_INFO *mem_info;
1209  void *buffer = NULL;
1210 
1211  //FUNCTION_START(STB_AppGetMemoryPGW);
1212 
1213  ASSERT(size > 0);
1214 
1215  mem_info = (S_MEM_INFO *)STB_MEMGetAppRAM(sizeof(S_MEM_INFO) + size - sizeof(unsigned long));
1216  while (mem_info == NULL && AppFreeCachedMemory())
1217  {
1218  mem_info = (S_MEM_INFO *)STB_MEMGetAppRAM(sizeof(S_MEM_INFO) + size - sizeof(unsigned long));
1219  }
1220  if (mem_info != NULL)
1221  {
1222  mem_info->magic = PGW_GOOD_MAGIC;
1223  mem_info->size = size;
1224  mem_info->filename = filename;
1225  mem_info->lineno = lineno;
1226 
1227  #ifdef PGW_DUMP_ON
1228  ASSERT( pgw_mutex != NULL );
1229  mem_info->next = NULL;
1230  STB_OSMutexLock(pgw_mutex);
1231  mem_info->prev = app_tail;
1232  if (app_tail != NULL)
1233  {
1234  app_tail->next = mem_info;
1235  }
1236  app_tail = mem_info;
1237  if (app_head == NULL)
1238  {
1239  app_head = app_tail;
1240  }
1241  STB_OSMutexUnlock(pgw_mutex);
1242  #elif defined(PGW_LAST_ON)
1243  app_last_alloc[app_alloc_cnt & LAST_FREED_MSK] = *mem_info;
1244  app_alloc_cnt++;
1245  #endif /*PGW_DUMP_ON*/
1246 
1247  buffer = &mem_info->align;
1248  }
1249  else
1250  {
1251  STB_HEAP_PRINT(("PGW: Cannot allocate %d bytes at %s:%d\n", size,
1252  filename, lineno));
1253  }
1254 
1255  //FUNCTION_FINISH(STB_AppGetMemoryPGW);
1256 
1257  return buffer;
1258 }
1259 
1260 /*!**************************************************************************
1261  * @brief Reallocates an app memory buffer (with tracking).
1262  * @param buffer Pointer to current buffer
1263  * @param bytes Size of buffer in bytes
1264  * @param filename Name of file where allocation takes place
1265  * @param lineno Line number in file
1266  * @return A pointer to the newly allocated buffer, NULL if failed
1267  ****************************************************************************/
1268 void* STB_AppResizeMemoryPGW(void *buffer, U32BIT size, char *filename, int lineno)
1269 {
1270  S_MEM_INFO *mem_info;
1271 
1272  //FUNCTION_START(STB_AppResizeMemoryPGW);
1273 
1274 
1275  if (size == 0)
1276  {
1277  if (buffer != NULL)
1278  {
1279  STB_AppFreeMemoryPGW(buffer, filename, lineno);
1280  buffer = NULL;
1281  }
1282  }
1283  else if (buffer == NULL)
1284  {
1285  buffer = STB_AppGetMemoryPGW(size, filename, lineno);
1286  }
1287  else
1288  {
1289  mem_info = (S_MEM_INFO *)((char *)buffer - offsetof(S_MEM_INFO, align));
1290  if (mem_info->magic != PGW_GOOD_MAGIC)
1291  {
1292  STB_HEAP_PRINT(("PGW: Reallocating invalid app pointer %p at %s:%d\n", buffer,
1293  filename, lineno));
1294  STB_MemoryDumpPGW(0);
1295  }
1296  else
1297  {
1298  mem_info->magic = PGW_BAD_MAGIC;
1299 
1300  #ifdef PGW_DUMP_ON
1301  /* Remove the memory from the list */
1302  ASSERT( pgw_mutex != NULL );
1303  STB_OSMutexLock(pgw_mutex);
1304  if (app_tail == mem_info)
1305  {
1306  app_tail = app_tail->prev;
1307  }
1308  if (app_head == mem_info)
1309  {
1310  app_head = app_head->next;
1311  }
1312  if (mem_info->next != NULL)
1313  {
1314  mem_info->next->prev = mem_info->prev;
1315  }
1316 
1317  if (mem_info->prev != NULL)
1318  {
1319  mem_info->prev->next = mem_info->next;
1320  }
1321  STB_OSMutexUnlock(pgw_mutex);
1322  #endif /*PGW_DUMP_ON*/
1323 
1324  /* Realloc the memory and add it back into the list */
1325  mem_info = STB_MEMResizeAppRAM(mem_info, sizeof(S_MEM_INFO) + size - sizeof(unsigned long));
1326 
1327  mem_info->magic = PGW_GOOD_MAGIC;
1328  mem_info->size = size;
1329  mem_info->filename = filename;
1330  mem_info->lineno = lineno;
1331 
1332  #ifdef PGW_DUMP_ON
1333  mem_info->next = NULL;
1334  STB_OSMutexLock(pgw_mutex);
1335  mem_info->prev = app_tail;
1336  if (app_tail != NULL)
1337  {
1338  app_tail->next = mem_info;
1339  }
1340  app_tail = mem_info;
1341  if (app_head == NULL)
1342  {
1343  app_head = app_tail;
1344  }
1345  STB_OSMutexUnlock(pgw_mutex);
1346  #elif defined(PGW_LAST_ON)
1347  app_last_alloc[app_alloc_cnt & LAST_FREED_MSK] = *mem_info;
1348  app_alloc_cnt++;
1349  #endif /*PGW_DUMP_ON*/
1350 
1351  buffer = &mem_info->align;
1352  }
1353  }
1354 
1355  //FUNCTION_FINISH(STB_AppResizeMemoryPGW);
1356 
1357  return buffer;
1358 }
1359 
1360 /*!**************************************************************************
1361  * @brief Free buffer that was allocated using STB_AppGetMemoryPGW or STB_AppResizeMemoryPGW
1362  * @param buffer A pointer to the buffer
1363  * @return None.
1364  ****************************************************************************/
1365 void STB_AppFreeMemoryPGW(void *buffer, char *filename, int lineno)
1366 {
1367  S_MEM_INFO *mem_info;
1368 
1369  //FUNCTION_START(STB_AppFreeMemoryPGW);
1370 
1371  if (buffer != NULL)
1372  {
1373  mem_info = (S_MEM_INFO *)((char *)buffer - offsetof(S_MEM_INFO, align));
1374  if (mem_info->magic != PGW_GOOD_MAGIC)
1375  {
1376  STB_HEAP_PRINT(("PGW: Freeing invalid pointer %p at %s:%d\n", buffer,
1377  filename, lineno));
1378  STB_MemoryDumpPGW(0);
1379  }
1380  else
1381  {
1382  #ifdef PGW_DUMP_ON
1383  mem_info->magic = PGW_BAD_MAGIC;
1384 
1385  ASSERT( pgw_mutex != NULL );
1386  STB_OSMutexLock(pgw_mutex);
1387  if (app_tail == mem_info)
1388  {
1389  app_tail = app_tail->prev;
1390  }
1391  if (app_head == mem_info)
1392  {
1393  app_head = app_head->next;
1394  }
1395  if (mem_info->next != NULL)
1396  {
1397  mem_info->next->prev = mem_info->prev;
1398  }
1399 
1400  if (mem_info->prev != NULL)
1401  {
1402  mem_info->prev->next = mem_info->next;
1403  }
1404  STB_OSMutexUnlock(pgw_mutex);
1405  #elif defined(PGW_LAST_ON)
1406  app_last_freed[app_freed_cnt & LAST_FREED_MSK] = *mem_info;
1407  app_freed_cnt++;
1408  mem_info->magic = PGW_BAD_MAGIC;
1409  #endif /*PGW_DUMP_ON*/
1410 
1411  STB_MEMFreeAppRAM(mem_info);
1412  }
1413  }
1414 
1415  //FUNCTION_FINISH(STB_AppFreeMemoryPGW);
1416 }
1417 
1418 #ifdef PGW_LAST_ON
1419 static void DumpLast( const char *str, S_MEM_INFO *info, unsigned int cnt )
1420 {
1421  S_MEM_INFO *mem_info;
1422  unsigned int c;
1423  STB_HEAP_PRINT(("%s Count=%d", str, cnt));
1424  if (cnt > (LAST_FREED_MSK + 1))
1425  {
1426  c = cnt - (LAST_FREED_MSK + 1);
1427  }
1428  else
1429  {
1430  c = 0;
1431  }
1432  while (cnt != c)
1433  {
1434  cnt--;
1435  mem_info = &info[ cnt & LAST_FREED_MSK ];
1436  STB_HEAP_PRINT(("%s:%d\t%d bytes \tmgc=0x%x", mem_info->filename, mem_info->lineno, mem_info->size, mem_info->magic));
1437  }
1438 }
1439 
1440 #endif
1441 
1442 /*!**************************************************************************
1443  * @brief Dump list of current memory buffers
1444  * @param full Whether to print the full list or just the total
1445  * @return None.
1446  * @warning None.
1447  * @bug None.
1448  ****************************************************************************/
1449 void STB_MemoryDumpPGW(BOOLEAN full)
1450 {
1451  S_MEM_INFO *mem_info;
1452  size_t total = 0;
1453 
1454  FUNCTION_START(STB_MemoryDumpPGW);
1455 
1456 #ifdef PGW_DUMP_ON
1457 
1458  ASSERT( pgw_mutex != NULL );
1459 
1460  STB_OSMutexLock(pgw_mutex);
1461  STB_HEAP_PRINT(("*** SYSTEM MEMORY DUMP BEGIN ***\n"));
1462  for (mem_info = sys_head; mem_info != NULL; mem_info = mem_info->next)
1463  {
1464  if (full)
1465  {
1466  STB_HEAP_PRINT(("%s:%d\t%d bytes", mem_info->filename, mem_info->lineno, mem_info->size));
1467  }
1468  total += mem_info->size;
1469  }
1470  STB_HEAP_PRINT(("TOTAL\t%d bytes\n", total));
1471  total = 0;
1472  STB_HEAP_PRINT(("*** APP MEMORY DUMP BEGIN ***\n"));
1473  for (mem_info = app_head; mem_info != NULL; mem_info = mem_info->next)
1474  {
1475  if (full)
1476  {
1477  STB_HEAP_PRINT(("%s:%d\t%d bytes", mem_info->filename, mem_info->lineno, mem_info->size));
1478  }
1479  total += mem_info->size;
1480  }
1481  STB_HEAP_PRINT(("TOTAL\t%d bytes\n", total));
1482  STB_HEAP_PRINT(("*** MEMORY DUMP END ***\n"));
1483  STB_OSMutexUnlock(pgw_mutex);
1484 
1485 #else
1486 
1487  USE_UNWANTED_PARAM(full);
1488  USE_UNWANTED_PARAM(total);
1489  USE_UNWANTED_PARAM(mem_info);
1490 
1491 #ifdef PGW_LAST_ON
1492  DumpLast( "SYS ALLOC", sys_last_alloc, sys_alloc_cnt );
1493  DumpLast( "SYS FREED", sys_last_freed, sys_freed_cnt );
1494  DumpLast( "APP ALLOC", app_last_alloc, app_alloc_cnt );
1495  DumpLast( "APP FREED", app_last_freed, app_freed_cnt );
1496 #endif
1497 
1498 #endif /*ifdef PGW_DUMP_ON*/
1499 
1500  FUNCTION_FINISH(STB_MemoryDumpPGW);
1501 }
1502 
1503 #endif /* ifdef PGW_ENABLED */
1504 
1505 
1506 //**************************************************************************************************
1507 //
1508 // MEMORY COPY DEBUG FUNCTIONS -- For Detecting Memory Corruption
1509 //
1510 //**************************************************************************************************
1511 #ifdef DEBUG_MEMCOPY
1512 static void CheckHeapMemory(U8BIT *destn, U16BIT nbytes)
1513 {
1514  U16BIT count;
1515  U16BIT sum;
1516  U8BIT *blk_start;
1517  U8BIT *blk_end;
1518 
1519  // check for app heap corruption
1520  for (sum = 0, count = 0; ((count < HEAP_LIST_SIZE) && (sum < app_list.sum)); count++)
1521  {
1522  if (*(app_list.addr + count) != NULL)
1523  {
1524  sum++;
1525  blk_start = *(app_list.addr + count) - TEST_BUFF_SIZE;
1526  blk_end = *(app_list.addr + count) + (*(app_list.size + count));
1527 
1528  if (destn <= (blk_end + TEST_BUFF_SIZE))
1529  {
1530  if ((destn + nbytes) >= blk_start)
1531  {
1532  if (destn < (blk_start + TEST_BUFF_SIZE))
1533  {
1534  STB_HEAP_PRINT(("MemCopy : ERROR: App Heap Corruption"));
1535  }
1536  else if ((destn + nbytes) > blk_end)
1537  {
1538  STB_HEAP_PRINT(("MemCopy : ERROR: App Heap Corruption"));
1539  }
1540  }
1541  }
1542  }
1543  }
1544 
1545  // check for stb heap corruption
1546  for (sum = 0, count = 0; ((count < HEAP_LIST_SIZE) && (sum < heap_list.sum)); count++)
1547  {
1548  if (*(heap_list.addr + count) != NULL)
1549  {
1550  sum++;
1551  blk_start = *(heap_list.addr + count) - TEST_BUFF_SIZE;
1552  blk_end = *(heap_list.addr + count) + (*(heap_list.size + count));
1553 
1554  if (destn <= (blk_end + TEST_BUFF_SIZE))
1555  {
1556  if ((destn + nbytes) >= blk_start)
1557  {
1558  if (destn < (blk_start + TEST_BUFF_SIZE))
1559  {
1560  STB_HEAP_PRINT(("MemCopy : ERROR: Stb Heap Corruption"));
1561  }
1562  else if ((destn + nbytes) > blk_end)
1563  {
1564  STB_HEAP_PRINT(("MemCopy : ERROR: Stb Heap Corruption"));
1565  }
1566  }
1567  }
1568  }
1569  }
1570 }
1571 
1572 #endif //#ifdef DEBUG_MEMCOPY
1573 
1574 
1575 #ifdef DEBUG_TEST_APPHEAP
1576 void STB_CheckAppHeap(void)
1577 {
1578  U16BIT count;
1579  U16BIT sum;
1580  U8BIT *blk_start;
1581  U8BIT *blk_end;
1582 
1583  // check for app heap corruption
1584  for (sum = 0, count = 0; ((count < HEAP_LIST_SIZE) && (sum < app_list.sum)); count++)
1585  {
1586  if (*(app_list.addr + count) != NULL)
1587  {
1588  sum++;
1589  blk_start = *(app_list.addr + count) - TEST_BUFF_SIZE;
1590  blk_end = *(app_list.addr + count) + (*(app_list.size + count));
1591 
1592  if ((memcmp((void *)blk_start, (void *)test_buffer, TEST_BUFF_SIZE) != 0) ||
1593  (memcmp((void *)blk_end, (void *)test_buffer, TEST_BUFF_SIZE) != 0))
1594  {
1595  STB_HEAP_PRINT(("HeapTest(App) : ERROR: Corrupt Block: start = %p end = %p", blk_start, blk_end));
1596  break;
1597  }
1598  }
1599  }
1600 }
1601 
1602 #endif
1603 
1604 #ifdef DEBUG_TEST_STBHEAP
1605 void STB_CheckStbHeap(void)
1606 {
1607  U16BIT count;
1608  U16BIT sum;
1609  U8BIT *blk_start;
1610  U8BIT *blk_end;
1611 
1612  // check for app heap corruption
1613  for (sum = 0, count = 0; ((count < HEAP_LIST_SIZE) && (sum < heap_list.sum)); count++)
1614  {
1615  if (*(heap_list.addr + count) != NULL)
1616  {
1617  sum++;
1618  blk_start = *(heap_list.addr + count) - TEST_BUFF_SIZE;
1619  blk_end = *(heap_list.addr + count) + (*(heap_list.size + count));
1620 
1621  if ((memcmp((void *)blk_start, (void *)test_buffer, TEST_BUFF_SIZE) != 0) ||
1622  (memcmp((void *)blk_end, (void *)test_buffer, TEST_BUFF_SIZE) != 0))
1623  {
1624  STB_HEAP_PRINT(("HeapTest(Stb) : ERROR: Corrupt Block: start = %p end = %p", blk_start, blk_end));
1625  break;
1626  }
1627  }
1628  }
1629 }
1630 
1631 #endif
1632 
1633 
1634 //**************************************************************************************************
1635 //**************************************************************************************************
1636 //**************************************************************************************************
1637 //
1638 // IMPORTANT NOTE: These Functions Must remain at the End of this File in order for them
1639 // to function correctly.
1640 //
1641 //**************************************************************************************************
1642 #ifdef DEBUG_MEMCOPY
1643 void* STB_MemCopy(void *s1, const void *s2, U16BIT n)
1644 {
1645  CheckHeapMemory((U8BIT *)s1, n);
1646 
1647  #ifdef memcpy
1648  #undef memcpy
1649  #endif
1650  return memcpy(s1, s2, n);
1651 }
1652 
1653 void* STB_MemMove(void *s1, const void *s2, U16BIT n)
1654 {
1655  CheckHeapMemory((U8BIT *)s1, n);
1656 
1657  #undef memmove
1658  return memmove(s1, s2, n);
1659 }
1660 
1661 void* STB_MemSet(void *s, int c, U16BIT n)
1662 {
1663  CheckHeapMemory((U8BIT *)s, n);
1664 
1665  #undef memset
1666  return memset(s, c, n);
1667 }
1668 
1669 char* STB_StrCopy(char *s1, const char *s2)
1670 {
1671  CheckHeapMemory((U8BIT *)s1, (U16BIT)strlen(s2));
1672 
1673  #undef strcpy
1674  return strcpy(s1, s2);
1675 }
1676 
1677 char* STB_StrNCopy(char *s1, const char *s2, U16BIT n)
1678 {
1679  CheckHeapMemory((U8BIT *)s1, n);
1680 
1681  #undef strncpy
1682  return strncpy(s1, s2, n);
1683 }
1684 
1685 char* STB_StrCat(char *s1, const char *s2)
1686 {
1687  CheckHeapMemory((U8BIT *)s1 + strlen(s1), strlen(s2) + 1);
1688 
1689  #undef strcat
1690  return strcat(s1, s2);
1691 }
1692 
1693 char* STB_StrNCat(char *s1, const char *s2, U16BIT n)
1694 {
1695  //n == max copy characters (not including terminating null)
1696  #define min_number(a, b) (((a) < (b)) ? (a) : (b))
1697  CheckHeapMemory((U8BIT *)s1 + strlen(s1), min_number(n, strlen(s2)) + 1);
1698 
1699  #undef strncat
1700  return strncat(s1, s2, n);
1701 }
1702 
1703 #undef vsprintf
1704 int STB_VSPrintF(char *s1, const char *fmt, va_list va)
1705 {
1706  int count;
1707 
1708  count = vsprintf(s1, fmt, va);
1709 
1710  //count = num copy characters (not including terminating null)
1711  CheckHeapMemory((U8BIT *)s1, (U16BIT)(count + 1));
1712  return count;
1713 }
1714 
1715 int STB_SPrintF(char *s1, const char *fmt, ...)
1716 {
1717  int count;
1718  va_list va_ptr;
1719 
1720  va_start(va_ptr, fmt);
1721  count = vsprintf(s1, fmt, va_ptr);
1722  va_end(va_ptr);
1723 
1724  //count = num copy characters (not including terminating null)
1725  CheckHeapMemory((U8BIT *)s1, (U16BIT)(count + 1));
1726  return count;
1727 }
1728 
1729 int STB_SNPrintF(char *s1, U16BIT n, const char *fmt, ...)
1730 {
1731  int count;
1732  char *tmpbuff;
1733  va_list va_ptr;
1734 
1735  CheckHeapMemory((U8BIT *)s1, n);
1736 
1737  tmpbuff = (char *)STB_AppGetMemory(16000);
1738 
1739  va_start(va_ptr, fmt);
1740  count = vsprintf(tmpbuff, fmt, va_ptr);
1741  va_end(va_ptr);
1742 
1743  //n == max copy characters (inclusive of terminating null)
1744  //count = num copy characters (not including terminating null)
1745  if (count >= n)
1746  {
1747  count = n - 1;
1748  }
1749 
1750  #ifdef memcpy
1751  #undef memcpy
1752  #endif
1753  memcpy(s1, tmpbuff, count);
1754  *(s1 + count) = '\0';
1755 
1756  STB_AppFreeMemory((void *)tmpbuff);
1757 
1758  return count;
1759 }
1760 
1761 #endif //#ifdef DEBUG_MEMCOPY
1762 
1763 #ifdef DEBUG_HEAP_STATS
1764 #ifdef DEBUG_APP_STATS
1765 void STB_GetHeapStats(U32BIT *total_app, U32BIT *max_app, U32BIT *num_app,
1766  U32BIT *total_mem, U32BIT *max_mem, U32BIT *num_mem)
1767 {
1768  *total_app = app_stats.total;
1769  *max_app = app_stats.maximum;
1770  *num_app = app_stats.sum;
1771 
1772  *total_mem = heap_stats.total;
1773  *max_mem = heap_stats.maximum;
1774  *num_mem = heap_stats.sum;
1775 }
1776 
1777 #endif
1778 #endif
1779 
1780 //*****************************************************************************
1781 // End of file
1782 //*****************************************************************************
1783 
void * STB_MEMResizeAppRAM(void *ptr, U32BIT new_num_bytes)
Changes the size of the given block of memory ensuring data contained within the original memory bloc...
void STB_FreeMemory(void *addr)
Releases previously allocated heap memory.
Definition: stbheap.c:336
void * STB_GetMemory(U32BIT bytes)
Attempts to allocate memory from the heap.
Definition: stbheap.c:221
void STB_OSMutexUnlock(void *mutex)
Unlock a mutex (a.k.a. &#39;leave&#39;, &#39;signal&#39; or &#39;release&#39;)
void * STB_MEMGetSysRAM(U32BIT bytes)
Allocates a new block of memory for system use.
Debug functions header file.
void STB_OSMutexLock(void *mutex)
Lock a mutex (a.k.a. &#39;enter&#39;, &#39;wait&#39; or &#39;get&#39;).
void * STB_MEMGetAppRAM(U32BIT bytes)
Allocates a new block of memory for application use.
void STB_MEMFreeSysRAM(void *block)
Releases a previously allocated block of system memory.
void * STB_AppGetMemory(U32BIT bytes)
Attempts to allocate memory from the application heap.
Definition: stbheap.c:651
Header file - Function prototypes for NVM and Heap.
System Wide Global Technical Data Type Definitions.
void * STB_MEMResizeSysRAM(void *ptr, U32BIT new_num_bytes)
Changes the size of the given block of memory ensuring data contained within the original memory bloc...
Header file - Function prototypes for heap memory.
void * STB_OSCreateMutex(void)
Create a mutex.
void STB_MEMFreeAppRAM(void *block)
Releases a previously allocated block of system memory.
void * STB_ResizeMemory(void *ptr, U32BIT new_num_bytes)
Re-allocates a given memory area to the new size, ensuring data contained within the original memory ...
Definition: stbheap.c:550
void STB_AppFreeMemory(void *addr)
Releases previously allocated application heap memory.
Definition: stbheap.c:781
void * STB_AppResizeMemory(void *ptr, U32BIT new_num_bytes)
Re-allocates a given memory area to the new size, ensuring data contained within the original memory ...
Definition: stbheap.c:891