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)) } \ 71 U8BIT control[CONTROL_SIZE];
73 U16BIT line[MAX_BLK_STRS];
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))
330 rc = MallocFunc(theMemSize);
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;
415 heads = MHEG5getMem( STR_BLCK_SIZE(VTINY_BITS) +
416 STR_BLCK_SIZE(MIGIT_BITS) +
417 STR_BLCK_SIZE(SMALL_BITS) +
418 STR_BLCK_SIZE(MEDUM_BITS) +
419 STR_BLCK_SIZE(LARGE_BITS));
422 TRACE(TERROR, (
"failed to allocate string memory"))
428 heads += STR_BLCK_SIZE(VTINY_BITS);
432 heads += STR_BLCK_SIZE(MIGIT_BITS);
436 heads += STR_BLCK_SIZE(SMALL_BITS);
440 heads += STR_BLCK_SIZE(MEDUM_BITS);
456 for (cx = 0; cx != CONTROL_SIZE; cx++)
458 if (pBlk->control[cx] != 0x00)
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))
477 for (cx = 0; cx != CONTROL_SIZE; cx++)
479 if (pBlk->control[cx] != 0x00)
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))
493 MHEG5freeMem( pBlk );
497 void STR_Shutdown(
void)
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"))
507 MHEG5freeMem( vtiny_strmem_head );
510 static void ReleaseAnyFreeStrBlocks(
S_STRINGS_BLOCK *pBlk,
int dbits )
515 while (pBlk->next != NULL)
521 while (cx != CONTROL_SIZE && pBlk->control[cx] == 0x00)
523 if (cx == CONTROL_SIZE)
525 prev->next = pBlk->next;
526 MHEG5freeMem( pBlk );
533 void STR_TidyUp(
void)
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) 547 static unsigned char* BlkStrAlloc(
S_STRINGS_BLOCK *pBlk,
int dbits,
int line )
549 unsigned char *data = NULL;
553 for (cx = 0; cx != CONTROL_SIZE; cx++)
555 if (pBlk->control[cx] != 0xff)
557 for (bbits = 1, bx = 0; bbits != 0x100; bbits <<= 1, bx++)
559 if (!(pBlk->control[cx] & bbits))
561 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;
572 if (cx == CONTROL_SIZE)
574 if (pBlk->next == NULL)
589 while ((cx == CONTROL_SIZE) && (pBlk != NULL));
594 unsigned char* STR_DataAllocFunc(
unsigned int len,
int line )
596 unsigned char * STR_DataAlloc(
unsigned int len )
600 if (len < (1 << SMALL_BITS))
602 if (len < (1 << MIGIT_BITS))
604 if (len < (1 << VTINY_BITS))
606 data = BlkStrAlloc( vtiny_strmem_head, VTINY_BITS, line );
610 data = BlkStrAlloc( migit_strmem_head, MIGIT_BITS, line );
615 data = BlkStrAlloc( small_strmem_head, SMALL_BITS, line );
620 if (len < (1 << MEDUM_BITS))
622 data = BlkStrAlloc( medum_strmem_head, MEDUM_BITS, line );
626 if (len < (1 << LARGE_BITS))
628 data = BlkStrAlloc( large_strmem_head, LARGE_BITS, line );
632 data = (
unsigned char *)MHEG5getMem( len + 1 );
644 static void BlkStrFree(
S_STRINGS_BLOCK *pBlk,
int bz,
unsigned char *data )
648 unsigned char *blk_data = (
unsigned char *)pBlk +
sizeof(
S_STRINGS_BLOCK);
649 if (data >= blk_data &&
650 data < blk_data + STR_DATA_SIZE(bz))
653 tmp = (data - blk_data) >> bz;
654 pBlk->control[tmp >> 3] &= (U8BIT) ~(1 << (tmp & 7));
659 while (pBlk != NULL);
662 TRACE(TERROR, (
"Not freed %x", data))
668 void STR_DataFree(
unsigned char *data,
unsigned int len )
670 if (len < (1 << SMALL_BITS))
672 if (len < (1 << MIGIT_BITS))
674 if (len < (1 << VTINY_BITS))
676 BlkStrFree( vtiny_strmem_head, VTINY_BITS, data );
680 BlkStrFree( migit_strmem_head, MIGIT_BITS, data );
685 BlkStrFree( small_strmem_head, SMALL_BITS, data );
690 if (len < (1 << MEDUM_BITS))
692 BlkStrFree( medum_strmem_head, MEDUM_BITS, data );
696 if (len < (1 << LARGE_BITS))
698 BlkStrFree( large_strmem_head, LARGE_BITS, data );
702 MHEG5freeMem( data );
708 void MHG_DebugMemStats(
int line)
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;
763 BOOLEAN src_on[MAX_MEM_SRCS];
765 for (ndx = 0; ndx != MAX_MEM_SRCS; ndx++)
767 src_on[ndx] = (which & (1 << ndx)) ? TRUE : FALSE;
770 MHG_DebugMemStats(0);
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;
807 BOOLEAN MH5GlueMemoryInitialise(
void )
813 if (pMh5emt_listTail == NULL)
819 if (vtiny_strmem_head != NULL)
825 result = STR_Initialise();
830 void MH5GlueMemoryTerminate(
void)
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 );
857 rc.zptr = STR_DataAlloc( source.zlen );
861 assert(rc.zptr != source.zptr);
862 memcpy(rc.zptr, source.zptr, source.zlen);
863 rc.zlen = source.zlen;
886 rc.zlen = src1.zlen + src2.zlen;
894 rc.zptr = STR_DataAllocFunc( src1.zlen + src2.zlen, line + 8000 );
896 rc.zptr = STR_DataAlloc( src1.zlen + src2.zlen );
900 if (src1.zptr != NULL && src1.zlen != 0)
902 memcpy(rc.zptr, src1.zptr, src1.zlen);
908 if (src2.zptr != NULL && src2.zlen != 0)
910 memcpy(rc.zptr + src1.zlen, src2.zptr, src2.zlen);
922 S_STRING MH5GlueStringAllocFunc(U32BIT size,
int line )
924 S_STRING MH5GlueStringAlloc(U32BIT size)
932 rc.zptr = STR_DataAllocFunc( size, line + 6000 );
934 rc.zptr = STR_DataAlloc( size );
954 S_STRING MH5GlueStringCreateFunc(U32BIT size, U8BIT *data,
int line )
956 S_STRING MH5GlueStringCreate(U32BIT size, U8BIT * data)
964 rc.zptr = STR_DataAllocFunc( size, line + 6000 );
966 rc.zptr = STR_DataAlloc( size );
971 memcpy(rc.zptr, data, size);
986 void MH5GlueStringFree(
S_STRING *pStr )
988 assert(pStr != NULL);
989 if (pStr->zptr != NULL)
991 STR_DataFree( pStr->zptr, pStr->zlen );
void * MHEG5getMemFunc(int size)
Allocate a block of memory from the free pool. This function should be called using the macro MHEG5ge...
void STB_OSMutexUnlock(void *mutex)
Unlock a mutex (a.k.a. 'leave', 'signal' or 'release')
void * STB_OSCreateMutex(void)
Create a mutex.
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').
Header file - Function prototypes for operating system.