38 #define MallocFunc STB_MemAlloc 39 #define FreeFunc STB_MemFree 42 #define MAX_BLK_STRS 0x80 48 #define STR_DATA_SIZE(bz) (MAX_BLK_STRS << bz) 49 #define STR_BLCK_SIZE(bz) STR_DATA_SIZE(bz) + sizeof(S_STRINGS_BLOCK) 50 #define CONTROL_SIZE (MAX_BLK_STRS >> 3) 52 #define BlkStrFree( head, bz, data ) \ 53 { S_STRINGS_BLOCK *pBlk = head; \ 55 unsigned char *blk_data = (unsigned char *)pBlk + sizeof(S_STRINGS_BLOCK); \ 56 if (data >= blk_data \ 57 && data < blk_data + STR_DATA_SIZE(bz)) \ 59 tmp = (data - blk_data) >> bz; \ 60 pBlk->control[tmp >> 3] &= (U8BIT) ~(1 << (tmp & 7)); \ 64 } while (pBlk != NULL); \ 65 if (pBlk == NULL) { TRACE(TERROR, ("Not freed %x", data)) } \ 79 #define MH5EMT_MAGIC 0xE579A36D 81 typedef struct _mh5emtEntry_struct mh5emtEntry_t, *pMh5emtEntry_t;
83 struct _mh5emtEntry_struct
88 const char *callingFunc;
104 #define TOTAL_GRPS 24 105 static int mem_prints = 0;
106 static int mem_alloc_failed[TOTAL_GRPS];
107 static int mem_alloc_counts[TOTAL_GRPS];
108 static int mem_grp_max_sz[TOTAL_GRPS];
112 static void *mh5emt_mutex = NULL;
113 static mh5emtEntry_t mh5emt_listHead;
114 static pMh5emtEntry_t pMh5emt_listTail = NULL;
116 const char *mem_strings[MAX_MEM_SRCS] = {
117 "TOTALMEM",
"SYSTEM ",
"DSM-CC ",
"SI_QUERY",
"SSFCACHE",
"FREETYPE",
"MHENGINE",
"GRAPHICS",
"SURFACES" 120 static unsigned long cur_mem_total[MAX_MEM_SRCS] = { 0, 0, 0, 0, 0, 0, 0, 0, 0 };
121 static unsigned long max_mem_total[MAX_MEM_SRCS] = { 0, 0, 0, 0, 0, 0, 0, 0, 0 };
124 #define MAX_SAVED_MALLOCS 0x1000 125 mh5emtEntry_t saved_mallocs[MAX_SAVED_MALLOCS];
126 int saved_malloc_cnt = 0;
137 void mh5emt_init(
void)
141 for (g = 0, sz = 2; g != TOTAL_GRPS; g++)
143 mem_grp_max_sz[g] = sz;
144 if ((sz >= 32) && (sz <= 1024))
163 if (pMh5emt_listTail == NULL)
168 mh5emt_listHead.magic = 0;
169 mh5emt_listHead.callingFunc = NULL;
170 mh5emt_listHead.size = 0;
171 mh5emt_listHead.addr = NULL;
172 mh5emt_listHead.prev = NULL;
173 mh5emt_listHead.next = NULL;
175 pMh5emt_listTail = &mh5emt_listHead;
179 void mh5emt_close(
void)
193 pMh5emtEntry_t pEmtHdr = (pMh5emtEntry_t)what;
197 TRACE(TERROR, (
"**** WARNING: Attempt to free NULL MHEG5 memory block ****"))
201 unsigned char *pByte = (
unsigned char *)what;
208 if ((pEmtHdr->magic == MH5EMT_MAGIC) &&
209 (pEmtHdr->addr == pEmtHdr) &&
210 (pEmtHdr->prev != NULL))
213 pEmtHdr->prev->next = pEmtHdr->next;
216 pEmtHdr->next->prev = pEmtHdr->prev;
221 pMh5emt_listTail = pEmtHdr->prev;
224 if (cur_mem_total[0] < pEmtHdr->size)
226 TRACE(TERROR, (
"now=%ld, size=%ld", cur_mem_total[0], pEmtHdr->size))
230 cur_mem_total[0] -= pEmtHdr->size;
232 if (pEmtHdr->src > 0 && pEmtHdr->src < MAX_MEM_SRCS)
234 if (cur_mem_total[pEmtHdr->src] < pEmtHdr->size)
236 TRACE(TERROR, (
"src=%d, now=%ld, size=%ld", pEmtHdr->src, cur_mem_total[pEmtHdr->src], pEmtHdr->size))
240 cur_mem_total[pEmtHdr->src] -= pEmtHdr->size;
245 TRACE(TERROR, (
"free with invalid src id %d", pEmtHdr->src))
248 pByte += pEmtHdr->size;
249 if (pByte[0] !=
'e' || pByte[1] !=
'n' || pByte[2] !=
'd' || pByte[3] !=
'm')
251 TRACE(TERROR, (
"**** ERROR: free MHEG5 memory block with data corruption ****"))
255 pEmtHdr->callingFunc = NULL;
259 pEmtHdr->addr = NULL;
260 pEmtHdr->prev = NULL;
261 pEmtHdr->next = NULL;
265 TRACE(TERROR, (
"**** ERROR: Attempt to free invalid MHEG5 memory block ****"))
289 void*
MHEG5getMemFunc(
void *callingFunction,
int size,
int line,
int src)
299 pMh5emtEntry_t pEmtHdr;
300 unsigned char *pByte;
302 if (pMh5emt_listTail == NULL)
306 #define theMemSize size + sizeof(mh5emtEntry_t) + 4 308 #define theMemSize size 314 TRACE(TERROR, (
"%s:%d requested size: %d\n", (
const char *)callingFunction, line, size));
316 TRACE(TERROR, (
"requested size: %d", size));
323 while ((mem_grp_max_sz[grp] < size) && (grp != TOTAL_GRPS - 1))
333 TRACER(mem_alloc_failed[grp]++; )
334 TRACE(TERROR, (
"ERROR: Failed to alloc memory, sz=%d\n", size))
336 MHEG5LogPrintf(MHEG5ERROR,
"*** Out of memory Error *** Calling Function: %p , requested size: %d\n", callingFunction, size);
339 TRACE(TMEMORY, (
"*** Out of memory (total %ld) *** %s:%d size: %d\n", cur_mem_total[0], (
const char *)callingFunction, line, size))
345 TRACER(mem_alloc_counts[grp]++; )
347 assert( src > 0 && src < MAX_MEM_SRCS );
349 pEmtHdr = (pMh5emtEntry_t)rc;
352 pByte = (
unsigned char *)rc;
354 pByte[0] =
'e'; pByte[1] =
'n'; pByte[2] =
'd'; pByte[3] =
'm';
356 pEmtHdr->magic = MH5EMT_MAGIC;
357 pEmtHdr->callingFunc = (
const char *)callingFunction;
358 pEmtHdr->line = line;
360 pEmtHdr->size = (
unsigned int)size;
361 pEmtHdr->addr = pEmtHdr;
363 cur_mem_total[src] += (
unsigned int)size;
364 if (cur_mem_total[src] > max_mem_total[src])
365 max_mem_total[src] = cur_mem_total[src];
366 cur_mem_total[0] += (
unsigned int)size;
367 if (cur_mem_total[0] > max_mem_total[0])
368 max_mem_total[0] = cur_mem_total[0];
372 pEmtHdr->prev = pMh5emt_listTail;
373 pEmtHdr->next = NULL;
374 pMh5emt_listTail->next = pEmtHdr;
377 pMh5emt_listTail = pEmtHdr;
381 saved_mallocs[saved_malloc_cnt].next = pEmtHdr;
383 if (saved_malloc_cnt == MAX_SAVED_MALLOCS)
385 saved_malloc_cnt = 1;
387 memcpy(saved_mallocs + saved_malloc_cnt, pEmtHdr,
sizeof(mh5emtEntry_t));
411 static BOOLEAN STR_Initialise(
void)
413 unsigned char *heads;
422 TRACE(TERROR, (
"failed to allocate string memory"))
460 for (bbits = 1, bx = 0; bbits != 0x100; bbits <<= 1, bx++)
462 if ((pBlk->
control[cx] & bbits))
464 data = (
unsigned char *)pBlk +
sizeof(
S_STRINGS_BLOCK) + (((cx << 3) + bx) << dbits);
465 TRACE(TMEMORY, (
"(%d,%d) line=%d Not freed \"%s\"", cx, bx, pBlk->line[(cx << 3) + bx], data))
481 for (bbits = 1, bx = 0; bbits != 0x100; bbits <<= 1, bx++)
483 if ((pBlk->
control[cx] & bbits))
485 data = (
unsigned char *)pBlk +
sizeof(
S_STRINGS_BLOCK) + (((cx << 3) + bx) << dbits);
486 TRACE(TMEMORY, (
"(%d,%d) line=%d Not freed \"%s\"", cx, bx, pBlk->line[(cx << 3) + bx], data))
499 TRACE(TMEMORY, (
"freeing extra string memory"))
500 FreeStrBlocks( large_strmem_head,
LARGE_BITS );
501 FreeStrBlocks( medum_strmem_head,
MEDUM_BITS );
502 FreeStrBlocks( small_strmem_head,
SMALL_BITS );
503 FreeStrBlocks( migit_strmem_head,
MIGIT_BITS );
504 FreeStrBlocks( vtiny_strmem_head,
VTINY_BITS );
506 TRACE(TMEMORY, (
"freeing header string memory"))
510 static void ReleaseAnyFreeStrBlocks(
S_STRINGS_BLOCK *pBlk,
int dbits )
515 while (pBlk->
next != NULL)
535 assert( vtiny_strmem_head );
536 ReleaseAnyFreeStrBlocks( large_strmem_head,
LARGE_BITS );
537 ReleaseAnyFreeStrBlocks( medum_strmem_head,
MEDUM_BITS );
538 ReleaseAnyFreeStrBlocks( small_strmem_head,
SMALL_BITS );
539 ReleaseAnyFreeStrBlocks( migit_strmem_head,
MIGIT_BITS );
540 ReleaseAnyFreeStrBlocks( vtiny_strmem_head,
VTINY_BITS );
543 #ifndef MHG_TRACK_MEM 544 #define BlkStrAlloc(bk, bz, ln) BlkStrAlloc(bk, bz) 549 unsigned char *
data = NULL;
557 for (bbits = 1, bx = 0; bbits != 0x100; bbits <<= 1, bx++)
559 if (!(pBlk->
control[cx] & bbits))
562 data = (
unsigned char *)pBlk +
sizeof(
S_STRINGS_BLOCK) + (((cx << 3) + bx) << dbits);
564 pBlk->line[(cx << 3) + bx] = (
U16BIT)line;
574 if (pBlk->
next == NULL)
594 unsigned char* STR_DataAllocFunc(
unsigned int len,
int line )
648 unsigned char *blk_data = (
unsigned char *)pBlk +
sizeof(
S_STRINGS_BLOCK);
649 if (data >= blk_data &&
653 tmp = (data - blk_data) >> bz;
659 while (pBlk != NULL);
662 TRACE(TERROR, (
"Not freed %x", data))
715 for (nx = 0; nx != TOTAL_GRPS; nx++)
717 sprintf(tmp,
"(%03x-%03x)=%03d ", last, mem_grp_max_sz[nx] - 1, mem_alloc_counts[nx]);
718 last = mem_grp_max_sz[nx];
722 TRACE(TMEMORY, (
"%s", str))
725 mem_alloc_counts[nx] = 0;
728 for (nx = 0; nx != MAX_MEM_SRCS; nx++)
730 TRACE(TMEMORY, (
"Src=%s \tNow= %03ld\tMax= %03ld", mem_strings[nx], cur_mem_total[nx], max_mem_total[nx]))
735 for (nx = 0; nx != TOTAL_GRPS; nx++)
737 if (mem_alloc_failed[nx])
739 TRACE(TMEMORY, (
"Had failures: %d, %d", nx, mem_alloc_failed[nx]));
740 mem_alloc_failed[nx] = 0;
746 for (nx = 0; nx != TOTAL_GRPS; nx++)
748 mem_alloc_failed[nx] = 0;
757 void mh5emt_print(
unsigned int which)
759 const char dig[16] =
"0123456789ABCDEF";
762 pMh5emtEntry_t pEmtHdr;
765 for (ndx = 0; ndx != MAX_MEM_SRCS; ndx++)
767 src_on[ndx] = (which & (1 << ndx)) ?
TRUE :
FALSE;
772 TPRINT(TMEMORY, (
"\n#### ALLOCATED ENGINE MEMORY OBJECTS ####\n"))
775 pEmtHdr = mh5emt_listHead.next;
777 while (pEmtHdr != NULL)
779 if (src_on[pEmtHdr->src])
781 TPRINT(TMEMORY, (
"\"\n%s:%d Size: %u, Addr: %p \"",
782 pEmtHdr->callingFunc, pEmtHdr->line, pEmtHdr->size, pEmtHdr->addr))
783 pch = (
U8BIT *)(pEmtHdr->addr + 1);
784 for (ndx = 0; (ndx < pEmtHdr->size); pch++, ndx++)
786 if ((*pch >= 0x20) && (*pch < 0x7e) && (*pch !=
'='))
788 TPRINT(TMEMORY, (
"%c", *pch))
792 TPRINT(TMEMORY, (
"=%c%c", dig[*pch >> 4], dig[*pch & 0xf]))
798 pEmtHdr = pEmtHdr->next;
813 if (pMh5emt_listTail == NULL)
819 if (vtiny_strmem_head != NULL)
825 result = STR_Initialise();
832 if (vtiny_strmem_head != NULL)
835 vtiny_strmem_head = NULL;
852 if (source.
zlen != 0)
855 rc.
zptr = STR_DataAllocFunc( source.
zlen, line + 7000 );
894 rc.
zptr = STR_DataAllocFunc( src1.
zlen + src2.
zlen, line + 8000 );
900 if (src1.
zptr != NULL && src1.
zlen != 0)
908 if (src2.
zptr != NULL && src2.
zlen != 0)
932 rc.
zptr = STR_DataAllocFunc( size, line + 6000 );
964 rc.
zptr = STR_DataAllocFunc( size, line + 6000 );
971 memcpy(rc.
zptr, data, size);
988 assert(pStr != NULL);
989 if (pStr->
zptr != NULL)
S_STRINGS_BLOCK * large_strmem_head
S_STRING MH5GlueStringCopy(S_STRING source)
S_STRING MH5GlueStringCreate(U32BIT size, U8BIT *data)
S_STRINGS_BLOCK * vtiny_strmem_head
S_STRINGS_BLOCK * migit_strmem_head
struct s_strings_block S_STRINGS_BLOCK
void * MHEG5getMemFunc(int size)
Allocate a block of memory from the free pool. This function should be called using the macro MHEG5ge...
S_STRING MH5GlueStringAlloc(U32BIT size)
S_STRINGS_BLOCK * medum_strmem_head
U8BIT control[CONTROL_SIZE]
void MH5GlueStringFree(S_STRING *pStr)
void STB_OSMutexUnlock(void *mutex)
Unlock a mutex (a.k.a. 'leave', 'signal' or 'release')
unsigned char * STR_DataAlloc(unsigned int len)
void MH5GlueMemoryTerminate(void)
#define BlkStrFree(head, bz, data)
void * STB_OSCreateMutex(void)
Create a mutex.
BOOLEAN MH5GlueMemoryInitialise(void)
void MHEG5freeMemFunc(void *what)
Free some memory allocated by a call to MHEG5getMemFunc.
void STB_OSMutexLock(void *mutex)
Lock a mutex (a.k.a. 'enter', 'wait' or 'get').
#define STR_BLCK_SIZE(bz)
S_STRING MH5GlueStringConcat(S_STRING src1, S_STRING src2)
void MHG_DebugMemStats(int line)
struct s_strings_block * next
#define BlkStrAlloc(bk, bz, ln)
#define STR_DATA_SIZE(bz)
void STR_DataFree(unsigned char *data, unsigned int len)
S_STRINGS_BLOCK * small_strmem_head
Header file - Function prototypes for operating system.