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