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