From 7fe60435bce6595a9c58a9bfd8244d74b5320e96 Mon Sep 17 00:00:00 2001 From: Benjamin Franzke Date: Tue, 15 Jan 2013 08:46:13 +0100 Subject: Import DirectFB141_2k11R3_beta5 --- Source/DirectFB/lib/direct/mem.c | 350 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 350 insertions(+) create mode 100755 Source/DirectFB/lib/direct/mem.c (limited to 'Source/DirectFB/lib/direct/mem.c') diff --git a/Source/DirectFB/lib/direct/mem.c b/Source/DirectFB/lib/direct/mem.c new file mode 100755 index 0000000..7b65a32 --- /dev/null +++ b/Source/DirectFB/lib/direct/mem.c @@ -0,0 +1,350 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include + +#include + + +#if DIRECT_BUILD_DEBUGS /* Build with debug support? */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + + +D_DEBUG_DOMAIN( Direct_Mem, "Direct/Mem", "libdirect memory allocation (debugging)" ); + +/**********************************************************************************************************************/ + +typedef struct { + const void *mem; + size_t bytes; + const char *func; + const char *file; + int line; + DirectTraceBuffer *trace; +} MemDesc; + +/**********************************************************************************************************************/ + +static int alloc_count = 0; +static int alloc_capacity = 0; +static MemDesc *alloc_list = NULL; +static pthread_mutex_t alloc_lock = PTHREAD_MUTEX_INITIALIZER; + +/**********************************************************************************************************************/ + +void +direct_print_memleaks( void ) +{ + unsigned int i; + + /* Debug only. */ + pthread_mutex_lock( &alloc_lock ); + + if (alloc_count && (!direct_config || direct_config->debugmem)) { + direct_log_printf( NULL, "Local memory allocations remaining (%d): \n", alloc_count ); + + for (i=0; ibytes, desc->mem, desc->func, desc->file, desc->line ); + + if (desc->trace) + direct_trace_print_stack( desc->trace ); + } + } + + pthread_mutex_unlock( &alloc_lock ); +} + +/**********************************************************************************************************************/ + +/* FIXME: Replace array by linked list, or at least avoid the memmove on free of an item. */ + +static MemDesc * +allocate_mem_desc( void ) +{ + int cap = alloc_capacity; + + if (!cap) + cap = 64; + else if (cap == alloc_count) + cap <<= 1; + + if (cap != alloc_capacity) { + void *new_list = malloc( sizeof(MemDesc) * cap ); + + if (!new_list) { + D_WARN( "could not allocate more descriptors (%d->%d)", alloc_capacity, cap ); + return NULL; + } + + direct_memcpy( new_list, alloc_list, sizeof(MemDesc) * alloc_count ); + + free( alloc_list ); + + alloc_capacity = cap; + alloc_list = new_list; + } + + return &alloc_list[alloc_count++]; +} + +static inline void +fill_mem_desc( MemDesc *desc, const void *mem, int bytes, + const char *func, const char *file, int line, DirectTraceBuffer *trace ) +{ + desc->mem = mem; + desc->bytes = bytes; + desc->func = func; + desc->file = file; + desc->line = line; + desc->trace = trace; +} + +/**********************************************************************************************************************/ + +void * +direct_malloc( const char* file, int line, const char *func, size_t bytes ) +{ + void *mem; + MemDesc *desc; + + D_DEBUG_AT( Direct_Mem, " +%6zu bytes [%s:%d in %s()]\n", bytes, file, line, func ); + + mem = malloc( bytes ); + if (!mem) + return NULL; + + if (!direct_config->debugmem) + return mem; + + + /* Debug only. */ + pthread_mutex_lock( &alloc_lock ); + desc = allocate_mem_desc(); + pthread_mutex_unlock( &alloc_lock ); + + if (desc) + fill_mem_desc( desc, mem, bytes, func, file, line, direct_trace_copy_buffer(NULL) ); + + return mem; +} + +void * +direct_calloc( const char* file, int line, const char *func, size_t count, size_t bytes ) +{ + void *mem; + MemDesc *desc; + + D_DEBUG_AT( Direct_Mem, " +%6zu bytes [%s:%d in %s()]\n", count * bytes, file, line, func ); + + mem = calloc( count, bytes ); + if (!mem) + return NULL; + + if (!direct_config->debugmem) + return mem; + + + /* Debug only. */ + pthread_mutex_lock( &alloc_lock ); + desc = allocate_mem_desc(); + pthread_mutex_unlock( &alloc_lock ); + + if (desc) + fill_mem_desc( desc, mem, count * bytes, func, file, line, direct_trace_copy_buffer(NULL) ); + + return mem; +} + +void * +direct_realloc( const char *file, int line, const char *func, const char *what, void *mem, size_t bytes ) +{ + int i; + + if (!mem) + return direct_malloc( file, line, func, bytes ); + + if (!bytes) { + direct_free( file, line, func, what, mem ); + return NULL; + } + + if (!direct_config->debugmem) { + D_DEBUG_AT( Direct_Mem, " *%6zu bytes [%s:%d in %s()] '%s'\n", bytes, file, line, func, what ); + return realloc( mem, bytes ); + } + + + /* Debug only. */ + pthread_mutex_lock( &alloc_lock ); + + for (i=0; imem == mem) { + void *new_mem = realloc( mem, bytes ); + + D_DEBUG_AT( Direct_Mem, " %c%6zu bytes [%s:%d in %s()] (%s%zu) <- %p -> %p '%s'\n", + (bytes > desc->bytes) ? '>' : '<', bytes, file, line, func, + (bytes > desc->bytes) ? "+" : "", bytes - desc->bytes, mem, new_mem, what); + + if (desc->trace) { + direct_trace_free_buffer( desc->trace ); + desc->trace = NULL; + } + + if (!new_mem) { + D_WARN( "could not reallocate memory (%p: %zu->%zu)", mem, desc->bytes, bytes ); + + alloc_count--; + + /* FIXME: This can be very slow. */ + if (i < alloc_count) + direct_memmove( desc, desc + 1, (alloc_count - i) * sizeof(MemDesc) ); + } + else + fill_mem_desc( desc, new_mem, bytes, func, file, line, direct_trace_copy_buffer(NULL) ); + + pthread_mutex_unlock( &alloc_lock ); + + return new_mem; + } + } + + pthread_mutex_unlock( &alloc_lock ); + + D_ERROR( "Direct/Mem: Not reallocating unknown %p (%s) from [%s:%d in %s()] - corrupt/incomplete list?\n", + mem, what, file, line, func ); + + return direct_malloc( file, line, func, bytes ); +} + +void +direct_free( const char *file, int line, const char *func, const char *what, void *mem ) +{ + unsigned int i; + + if (!mem) { + D_WARN( "%s (NULL) called", __FUNCTION__ ); + return; + } + + if (!direct_config->debugmem) { + D_DEBUG_AT( Direct_Mem, " - number of bytes of %s [%s:%d in %s()] -> %p\n", what, file, line, func, mem ); + free( mem ); + return; + } + + + /* Debug only. */ + pthread_mutex_lock( &alloc_lock ); + + for (i=0; imem == mem) { + free( mem ); + + D_DEBUG_AT( Direct_Mem, " -%6zu bytes [%s:%d in %s()] -> %p '%s'\n", + desc->bytes, file, line, func, mem, what ); + + if (desc->trace) + direct_trace_free_buffer( desc->trace ); + + alloc_count--; + + /* FIXME: This can be very slow. */ + if (i < alloc_count) + direct_memmove( desc, desc + 1, (alloc_count - i) * sizeof(MemDesc) ); + + pthread_mutex_unlock( &alloc_lock ); + + return; + } + } + + pthread_mutex_unlock( &alloc_lock ); + + D_ERROR( "Direct/Mem: Not freeing unknown %p (%s) from [%s:%d in %s()] - corrupt/incomplete list?\n", + mem, what, file, line, func ); +} + +char * +direct_strdup( const char* file, int line, const char *func, const char *string ) +{ + void *mem; + MemDesc *desc; + size_t length = strlen( string ) + 1; + + mem = malloc( length ); + D_DEBUG_AT( Direct_Mem, " +%6zu bytes [%s:%d in %s()] -> %p \"%30s\"\n", length, file, line, func, mem, string ); + if (!mem) + return NULL; + + direct_memcpy( mem, string, length ); + + if (!direct_config->debugmem) + return mem; + + + /* Debug only. */ + pthread_mutex_lock( &alloc_lock ); + desc = allocate_mem_desc(); + pthread_mutex_unlock( &alloc_lock ); + + if (desc) + fill_mem_desc( desc, mem, length, func, file, line, direct_trace_copy_buffer(NULL) ); + + return mem; +} + +/**********************************************************************************************************************/ + +#else + +void +direct_print_memleaks( void ) +{ +} + +#endif + -- cgit