graphicscomposition/openwfcompositionengine/common/src/owfmemory.c
changeset 0 5d03bc08d59c
child 152 9f1c3fea0f87
--- /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 <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <pthread.h>
+
+#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