graphicscomposition/openwfcompositionengine/common/src/owfmemory.c
changeset 0 5d03bc08d59c
child 152 9f1c3fea0f87
equal deleted inserted replaced
-1:000000000000 0:5d03bc08d59c
       
     1 /* Copyright (c) 2009 The Khronos Group Inc.
       
     2  *
       
     3  * Permission is hereby granted, free of charge, to any person obtaining a
       
     4  * copy of this software and/or associated documentation files (the
       
     5  * "Materials"), to deal in the Materials without restriction, including
       
     6  * without limitation the rights to use, copy, modify, merge, publish,
       
     7  * distribute, sublicense, and/or sell copies of the Materials, and to
       
     8  * permit persons to whom the Materials are furnished to do so, subject to
       
     9  * the following conditions:
       
    10  *
       
    11  * The above copyright notice and this permission notice shall be included
       
    12  * in all copies or substantial portions of the Materials.
       
    13  *
       
    14  * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
       
    15  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
       
    16  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
       
    17  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
       
    18  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
       
    19  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
       
    20  * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
       
    21  */
       
    22 
       
    23 
       
    24 #ifdef __cplusplus
       
    25 extern "C"
       
    26 {
       
    27 #endif
       
    28 
       
    29 
       
    30 #include <string.h>
       
    31 #include <stdlib.h>
       
    32 #include <stdio.h>
       
    33 #include <pthread.h>
       
    34 
       
    35 #include "owfmemory.h"
       
    36 #include "owfdebug.h"
       
    37 
       
    38 #define MAGIK   0x05EAF00D
       
    39 #define FENCE1  0xFACED00D
       
    40 #define FENCE2  0xFACE50FF
       
    41 
       
    42 #define OFFSET(x,y) ((OWFuint32)&(((x*) 0x1000)->y) - 0x1000)
       
    43 
       
    44 typedef struct BLOCK_ {
       
    45     OWFint                      magik;
       
    46     struct BLOCK_*              next;
       
    47     const char*                 file;
       
    48     OWFint                      line;
       
    49     OWFuint32                   size;
       
    50     OWFuint32                   nInts;
       
    51     OWFint                      memory[2];
       
    52 } BLOCK;
       
    53 
       
    54 
       
    55 #ifdef DEBUG
       
    56 
       
    57 static void
       
    58 OWF_Memory_Shutdown(void);
       
    59 
       
    60 #endif
       
    61 
       
    62 static void
       
    63 OWF_Memory_LockUnlockManagedBlocks(OWFboolean lock)
       
    64 {
       
    65 #ifndef DEBUG
       
    66     (void) lock;
       
    67 #endif
       
    68 
       
    69 #ifdef DEBUG
       
    70     /* cannot use OWF_MUTEX because it uses managed memory */
       
    71     static pthread_mutex_t mem_mutex = PTHREAD_MUTEX_INITIALIZER;
       
    72 
       
    73     if (lock)
       
    74     {
       
    75         pthread_mutex_lock(&mem_mutex);
       
    76     }
       
    77     else
       
    78     {
       
    79         pthread_mutex_unlock(&mem_mutex);
       
    80     }
       
    81 #endif
       
    82 }
       
    83 
       
    84 static void
       
    85 OWF_Memory_LockManagedBlocks()
       
    86 {
       
    87     OWF_Memory_LockUnlockManagedBlocks(OWF_TRUE);
       
    88 }
       
    89 
       
    90 static void
       
    91 OWF_Memory_UnlockManagedBlocks()
       
    92 {
       
    93     OWF_Memory_LockUnlockManagedBlocks(OWF_FALSE);
       
    94 }
       
    95 
       
    96 
       
    97 OWF_API_CALL BLOCK*
       
    98 OWF_Memory_GetSetManagedBlocks(BLOCK* b, OWFboolean set)
       
    99 {
       
   100 #ifdef DEBUG
       
   101     static BLOCK* managed_blocks = NULL;
       
   102     static OWFboolean initialized = OWF_FALSE;
       
   103 
       
   104     if (!initialized) {
       
   105         /* add exit handler (leak report) */
       
   106         atexit(OWF_Memory_Shutdown);
       
   107         initialized = OWF_TRUE;
       
   108     }
       
   109 
       
   110     if (set)
       
   111     {
       
   112         managed_blocks = b;
       
   113         return b;
       
   114     }
       
   115     else
       
   116     {
       
   117         return managed_blocks;
       
   118     }
       
   119 #else
       
   120     if (set)
       
   121     {
       
   122         b = b; /* dummy code */
       
   123     }
       
   124     return NULL;
       
   125 #endif
       
   126 }
       
   127 
       
   128 static BLOCK*
       
   129 OWF_Memory_GetManagedBlocks()
       
   130 {
       
   131     return OWF_Memory_GetSetManagedBlocks(NULL, OWF_FALSE);
       
   132 }
       
   133 
       
   134 static void
       
   135 OWF_Memory_SetManagedBlocks(BLOCK* b)
       
   136 {
       
   137     OWF_Memory_GetSetManagedBlocks(b, OWF_TRUE);
       
   138 }
       
   139 
       
   140 OWF_API_CALL void*
       
   141 OWF_Memory_Alloc(const char* file, OWFint line, OWFuint32 size)
       
   142 {
       
   143 #define INT_SIZE sizeof(OWFint)
       
   144 
       
   145     BLOCK* block = NULL;
       
   146 
       
   147     /* size rounded to nearest sizeof(int)*n + 2*sizeof(int) for fences */
       
   148     OWFuint32 nInts = 2 + (((size + INT_SIZE-1) &~ (INT_SIZE-1)) >> 2);
       
   149     OWFuint32 realSize = nInts * INT_SIZE + sizeof(BLOCK);
       
   150 
       
   151     if (realSize > size) /* not int overflow */
       
   152     {
       
   153         block = (BLOCK*) malloc(realSize);
       
   154     }
       
   155 
       
   156     if (!block)
       
   157     {
       
   158         DPRINT(("Couldn't alloc %u bytes\n", size));
       
   159         return NULL;
       
   160     }
       
   161 
       
   162     /* populate block header */
       
   163     memset(block, 0, realSize);
       
   164     block->magik = MAGIK;
       
   165     block->file = file;
       
   166     block->line = line;
       
   167     block->size = size;
       
   168     block->nInts = nInts;
       
   169     block->memory[0] = FENCE1;
       
   170     block->memory[nInts-1] = FENCE2;
       
   171 
       
   172     OWF_Memory_LockManagedBlocks();
       
   173     {
       
   174         /* insert to list at position 0 */
       
   175         block->next = (BLOCK*) OWF_Memory_GetManagedBlocks();
       
   176         OWF_Memory_SetManagedBlocks(block);
       
   177     }
       
   178     OWF_Memory_UnlockManagedBlocks();
       
   179 
       
   180     return &block->memory[1];
       
   181 }
       
   182 
       
   183 OWF_API_CALL void
       
   184 OWF_Memory_Free(void* ptr)
       
   185 {
       
   186     BLOCK* block        = NULL;
       
   187 
       
   188     if (!ptr) {
       
   189         return;
       
   190     }
       
   191 
       
   192     /* POINTER ARITHMETIC HAZARD */
       
   193     block = (BLOCK*) ((OWFuint32) ptr - (OWFuint32) OFFSET(BLOCK,memory[1]));
       
   194 
       
   195     if (!block)
       
   196     {
       
   197         DPRINT(("Sanity check failed. Ptr was zero....\n"));
       
   198         return;
       
   199     }
       
   200 
       
   201     OWF_Memory_LockManagedBlocks();
       
   202     {
       
   203         BLOCK* temp             = NULL;
       
   204         BLOCK* prev             = NULL;
       
   205         OWFboolean stillExists  = OWF_FALSE;
       
   206 
       
   207         temp = OWF_Memory_GetManagedBlocks();
       
   208 
       
   209         while (temp)
       
   210         {
       
   211             /* the block is on the list? */
       
   212             if (temp == block && ptr == &temp->memory[1])
       
   213             {
       
   214                 stillExists = OWF_TRUE;
       
   215                 break;
       
   216             }
       
   217             prev = temp;
       
   218             temp = temp->next;
       
   219         }
       
   220 
       
   221         if (stillExists == OWF_TRUE)
       
   222         {
       
   223             if (MAGIK != temp->magik)
       
   224             {
       
   225                 DPRINT(("Possibly corrupt or invalid block, addr = %p\n", ptr));
       
   226             }
       
   227             if (block->memory[0] != (OWFint)FENCE1)
       
   228             {
       
   229                 DPRINT(("Block's start fence corrupted, addr = %p\n", ptr));
       
   230             }
       
   231             if (block->memory[block->nInts-1] != (OWFint)FENCE2)
       
   232             {
       
   233                 DPRINT(("Block's end fence corrupted, addr = %p\n", ptr));
       
   234             }
       
   235 
       
   236             /* valid block, unlink & free it */
       
   237             if (prev)
       
   238             {
       
   239                 prev->next = temp->next;
       
   240             }
       
   241             else
       
   242             {
       
   243                 OWF_Memory_SetManagedBlocks(temp->next);
       
   244             }
       
   245             free(block);
       
   246         }
       
   247         else
       
   248         {
       
   249             /* possibly already freed, strangled pointer. complain. */
       
   250             DPRINT(("Block possibly freed already! (block = %p, addr = %p)\n",
       
   251                     (void*) block, ptr));
       
   252         }
       
   253     }
       
   254     OWF_Memory_UnlockManagedBlocks();
       
   255 
       
   256 }
       
   257 
       
   258 OWF_API_CALL void
       
   259 OWF_Memory_BlockDump()
       
   260 {
       
   261     BLOCK* block = OWF_Memory_GetManagedBlocks();
       
   262 
       
   263     /* managed blocks locked when this is executed */
       
   264 
       
   265     while (block)
       
   266         {
       
   267         BLOCK* next = (BLOCK*) block->next;
       
   268         if (MAGIK == block->magik)
       
   269             {
       
   270             DPRINT(("Block: %p\nFile: %s(%d)\nSize: %u bytes\n",
       
   271                             (void*) &block->memory[1],
       
   272                             block->file,
       
   273                             block->line,
       
   274                             block->size));
       
   275             }
       
   276         else
       
   277             {
       
   278             DPRINT(("Possibly corrupt or invalid block (addr = %p)\n",
       
   279                                 (void*) block));
       
   280             }
       
   281         block = next;
       
   282         }
       
   283 }
       
   284 
       
   285 #ifdef DEBUG
       
   286 static void
       
   287 OWF_Memory_Shutdown()
       
   288 {
       
   289     BLOCK* block = NULL;
       
   290 
       
   291     OWF_Memory_LockManagedBlocks();
       
   292     {
       
   293 
       
   294         if (OWF_Memory_GetManagedBlocks())
       
   295         {
       
   296             DPRINT(("======================================================================\n"));DPRINT(("MEMORY LEAK REPORT\n"));DPRINT(("======================================================================\n"));
       
   297             OWF_Memory_BlockDump();
       
   298             block = OWF_Memory_GetManagedBlocks();
       
   299             while (block)
       
   300             {
       
   301                 BLOCK* next = (BLOCK*) block->next;
       
   302                 if (MAGIK == block->magik)
       
   303                 {
       
   304                     free(block);
       
   305                 }
       
   306                 block = next;
       
   307             }
       
   308             OWF_Memory_SetManagedBlocks(NULL);
       
   309         }
       
   310 
       
   311     }
       
   312     OWF_Memory_UnlockManagedBlocks();
       
   313 }
       
   314 #endif
       
   315 
       
   316 #ifdef __cplusplus
       
   317 }
       
   318 #endif