diff -r 000000000000 -r 5d03bc08d59c graphicscomposition/openwfcompositionengine/common/src/owfmemory.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graphicscomposition/openwfcompositionengine/common/src/owfmemory.c Tue Feb 02 01:47:50 2010 +0200 @@ -0,0 +1,318 @@ +/* Copyright (c) 2009 The Khronos Group Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and/or associated documentation files (the + * "Materials"), to deal in the Materials without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Materials, and to + * permit persons to whom the Materials are furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Materials. + * + * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. + */ + + +#ifdef __cplusplus +extern "C" +{ +#endif + + +#include +#include +#include +#include + +#include "owfmemory.h" +#include "owfdebug.h" + +#define MAGIK 0x05EAF00D +#define FENCE1 0xFACED00D +#define FENCE2 0xFACE50FF + +#define OFFSET(x,y) ((OWFuint32)&(((x*) 0x1000)->y) - 0x1000) + +typedef struct BLOCK_ { + OWFint magik; + struct BLOCK_* next; + const char* file; + OWFint line; + OWFuint32 size; + OWFuint32 nInts; + OWFint memory[2]; +} BLOCK; + + +#ifdef DEBUG + +static void +OWF_Memory_Shutdown(void); + +#endif + +static void +OWF_Memory_LockUnlockManagedBlocks(OWFboolean lock) +{ +#ifndef DEBUG + (void) lock; +#endif + +#ifdef DEBUG + /* cannot use OWF_MUTEX because it uses managed memory */ + static pthread_mutex_t mem_mutex = PTHREAD_MUTEX_INITIALIZER; + + if (lock) + { + pthread_mutex_lock(&mem_mutex); + } + else + { + pthread_mutex_unlock(&mem_mutex); + } +#endif +} + +static void +OWF_Memory_LockManagedBlocks() +{ + OWF_Memory_LockUnlockManagedBlocks(OWF_TRUE); +} + +static void +OWF_Memory_UnlockManagedBlocks() +{ + OWF_Memory_LockUnlockManagedBlocks(OWF_FALSE); +} + + +OWF_API_CALL BLOCK* +OWF_Memory_GetSetManagedBlocks(BLOCK* b, OWFboolean set) +{ +#ifdef DEBUG + static BLOCK* managed_blocks = NULL; + static OWFboolean initialized = OWF_FALSE; + + if (!initialized) { + /* add exit handler (leak report) */ + atexit(OWF_Memory_Shutdown); + initialized = OWF_TRUE; + } + + if (set) + { + managed_blocks = b; + return b; + } + else + { + return managed_blocks; + } +#else + if (set) + { + b = b; /* dummy code */ + } + return NULL; +#endif +} + +static BLOCK* +OWF_Memory_GetManagedBlocks() +{ + return OWF_Memory_GetSetManagedBlocks(NULL, OWF_FALSE); +} + +static void +OWF_Memory_SetManagedBlocks(BLOCK* b) +{ + OWF_Memory_GetSetManagedBlocks(b, OWF_TRUE); +} + +OWF_API_CALL void* +OWF_Memory_Alloc(const char* file, OWFint line, OWFuint32 size) +{ +#define INT_SIZE sizeof(OWFint) + + BLOCK* block = NULL; + + /* size rounded to nearest sizeof(int)*n + 2*sizeof(int) for fences */ + OWFuint32 nInts = 2 + (((size + INT_SIZE-1) &~ (INT_SIZE-1)) >> 2); + OWFuint32 realSize = nInts * INT_SIZE + sizeof(BLOCK); + + if (realSize > size) /* not int overflow */ + { + block = (BLOCK*) malloc(realSize); + } + + if (!block) + { + DPRINT(("Couldn't alloc %u bytes\n", size)); + return NULL; + } + + /* populate block header */ + memset(block, 0, realSize); + block->magik = MAGIK; + block->file = file; + block->line = line; + block->size = size; + block->nInts = nInts; + block->memory[0] = FENCE1; + block->memory[nInts-1] = FENCE2; + + OWF_Memory_LockManagedBlocks(); + { + /* insert to list at position 0 */ + block->next = (BLOCK*) OWF_Memory_GetManagedBlocks(); + OWF_Memory_SetManagedBlocks(block); + } + OWF_Memory_UnlockManagedBlocks(); + + return &block->memory[1]; +} + +OWF_API_CALL void +OWF_Memory_Free(void* ptr) +{ + BLOCK* block = NULL; + + if (!ptr) { + return; + } + + /* POINTER ARITHMETIC HAZARD */ + block = (BLOCK*) ((OWFuint32) ptr - (OWFuint32) OFFSET(BLOCK,memory[1])); + + if (!block) + { + DPRINT(("Sanity check failed. Ptr was zero....\n")); + return; + } + + OWF_Memory_LockManagedBlocks(); + { + BLOCK* temp = NULL; + BLOCK* prev = NULL; + OWFboolean stillExists = OWF_FALSE; + + temp = OWF_Memory_GetManagedBlocks(); + + while (temp) + { + /* the block is on the list? */ + if (temp == block && ptr == &temp->memory[1]) + { + stillExists = OWF_TRUE; + break; + } + prev = temp; + temp = temp->next; + } + + if (stillExists == OWF_TRUE) + { + if (MAGIK != temp->magik) + { + DPRINT(("Possibly corrupt or invalid block, addr = %p\n", ptr)); + } + if (block->memory[0] != (OWFint)FENCE1) + { + DPRINT(("Block's start fence corrupted, addr = %p\n", ptr)); + } + if (block->memory[block->nInts-1] != (OWFint)FENCE2) + { + DPRINT(("Block's end fence corrupted, addr = %p\n", ptr)); + } + + /* valid block, unlink & free it */ + if (prev) + { + prev->next = temp->next; + } + else + { + OWF_Memory_SetManagedBlocks(temp->next); + } + free(block); + } + else + { + /* possibly already freed, strangled pointer. complain. */ + DPRINT(("Block possibly freed already! (block = %p, addr = %p)\n", + (void*) block, ptr)); + } + } + OWF_Memory_UnlockManagedBlocks(); + +} + +OWF_API_CALL void +OWF_Memory_BlockDump() +{ + BLOCK* block = OWF_Memory_GetManagedBlocks(); + + /* managed blocks locked when this is executed */ + + while (block) + { + BLOCK* next = (BLOCK*) block->next; + if (MAGIK == block->magik) + { + DPRINT(("Block: %p\nFile: %s(%d)\nSize: %u bytes\n", + (void*) &block->memory[1], + block->file, + block->line, + block->size)); + } + else + { + DPRINT(("Possibly corrupt or invalid block (addr = %p)\n", + (void*) block)); + } + block = next; + } +} + +#ifdef DEBUG +static void +OWF_Memory_Shutdown() +{ + BLOCK* block = NULL; + + OWF_Memory_LockManagedBlocks(); + { + + if (OWF_Memory_GetManagedBlocks()) + { + DPRINT(("======================================================================\n"));DPRINT(("MEMORY LEAK REPORT\n"));DPRINT(("======================================================================\n")); + OWF_Memory_BlockDump(); + block = OWF_Memory_GetManagedBlocks(); + while (block) + { + BLOCK* next = (BLOCK*) block->next; + if (MAGIK == block->magik) + { + free(block); + } + block = next; + } + OWF_Memory_SetManagedBlocks(NULL); + } + + } + OWF_Memory_UnlockManagedBlocks(); +} +#endif + +#ifdef __cplusplus +} +#endif