First public contribution.
1 /* Copyright (c) 2009 The Khronos Group Inc.
2 * Portions copyright (c) 2009-2010 Nokia Corporation and/or its subsidiary(-ies)
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:
12 * The above copyright notice and this permission notice shall be included
13 * in all copies or substantial portions of the Materials.
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.
36 #include "owfmemory.h"
41 #define MAGIK 0x05EAF00D
42 #define FENCE1 0xFACED00D
43 #define FENCE2 0xFACE50FF
45 #define OFFSET(x,y) ((OWFuint32)&(((x*) 0x1000)->y) - 0x1000)
47 typedef struct BLOCK_ {
61 OWF_Memory_Shutdown(void);
66 OWF_Memory_LockUnlockManagedBlocks(OWFboolean lock)
73 /* cannot use OWF_MUTEX because it uses managed memory */
74 static pthread_mutex_t mem_mutex = PTHREAD_MUTEX_INITIALIZER;
78 pthread_mutex_lock(&mem_mutex);
82 pthread_mutex_unlock(&mem_mutex);
88 OWF_Memory_LockManagedBlocks()
90 OWF_Memory_LockUnlockManagedBlocks(OWF_TRUE);
94 OWF_Memory_UnlockManagedBlocks()
96 OWF_Memory_LockUnlockManagedBlocks(OWF_FALSE);
101 OWF_Memory_GetSetManagedBlocks(BLOCK* b, OWFboolean set)
104 static BLOCK* managed_blocks = NULL;
105 static OWFboolean initialized = OWF_FALSE;
108 /* add exit handler (leak report) */
109 atexit(OWF_Memory_Shutdown);
110 initialized = OWF_TRUE;
120 return managed_blocks;
125 b = b; /* dummy code */
132 OWF_Memory_GetManagedBlocks()
134 return OWF_Memory_GetSetManagedBlocks(NULL, OWF_FALSE);
138 OWF_Memory_SetManagedBlocks(BLOCK* b)
140 OWF_Memory_GetSetManagedBlocks(b, OWF_TRUE);
144 OWF_Memory_Alloc(const char* file, OWFint line, OWFuint32 size)
146 #define INT_SIZE sizeof(OWFint)
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);
154 if (realSize > size) /* not int overflow */
156 block = (BLOCK*) malloc(realSize);
161 DPRINT(("Couldn't alloc %u bytes\n", size));
165 /* populate block header */
166 memset(block, 0, realSize);
167 block->magik = MAGIK;
171 block->nInts = nInts;
172 block->memory[0] = FENCE1;
173 block->memory[nInts-1] = FENCE2;
175 OWF_Memory_LockManagedBlocks();
177 /* insert to list at position 0 */
178 block->next = (BLOCK*) OWF_Memory_GetManagedBlocks();
179 OWF_Memory_SetManagedBlocks(block);
181 OWF_Memory_UnlockManagedBlocks();
183 return &block->memory[1];
187 OWF_Memory_Free(void* ptr)
195 /* POINTER ARITHMETIC HAZARD */
196 block = (BLOCK*) ((OWFuint32) ptr - (OWFuint32) OFFSET(BLOCK,memory[1]));
200 DPRINT(("Sanity check failed. Ptr was zero....\n"));
204 OWF_Memory_LockManagedBlocks();
208 OWFboolean stillExists = OWF_FALSE;
210 temp = OWF_Memory_GetManagedBlocks();
214 /* the block is on the list? */
215 if (temp == block && ptr == &temp->memory[1])
217 stillExists = OWF_TRUE;
224 if (stillExists == OWF_TRUE)
226 if (MAGIK != temp->magik)
228 DPRINT(("Possibly corrupt or invalid block, addr = %p\n", ptr));
230 if (block->memory[0] != (OWFint)FENCE1)
232 DPRINT(("Block's start fence corrupted, addr = %p\n", ptr));
234 if (block->memory[block->nInts-1] != (OWFint)FENCE2)
236 DPRINT(("Block's end fence corrupted, addr = %p\n", ptr));
239 /* valid block, unlink & free it */
242 prev->next = temp->next;
246 OWF_Memory_SetManagedBlocks(temp->next);
252 /* possibly already freed, strangled pointer. complain. */
253 DPRINT(("Block possibly freed already! (block = %p, addr = %p)\n",
254 (void*) block, ptr));
257 OWF_Memory_UnlockManagedBlocks();
262 OWF_Memory_BlockDump()
264 BLOCK* block = OWF_Memory_GetManagedBlocks();
266 /* managed blocks locked when this is executed */
270 BLOCK* next = (BLOCK*) block->next;
271 if (MAGIK == block->magik)
273 DPRINT(("Block: %p\nFile: %s(%d)\nSize: %u bytes\n",
274 (void*) &block->memory[1],
281 DPRINT(("Possibly corrupt or invalid block (addr = %p)\n",
290 OWF_Memory_Shutdown()
294 OWF_Memory_LockManagedBlocks();
297 if (OWF_Memory_GetManagedBlocks())
299 DPRINT(("======================================================================\n"));DPRINT(("MEMORY LEAK REPORT\n"));DPRINT(("======================================================================\n"));
300 OWF_Memory_BlockDump();
301 block = OWF_Memory_GetManagedBlocks();
304 BLOCK* next = (BLOCK*) block->next;
305 if (MAGIK == block->magik)
311 OWF_Memory_SetManagedBlocks(NULL);
315 OWF_Memory_UnlockManagedBlocks();