Libav
|
00001 /* 00002 * default memory allocator for libavutil 00003 * Copyright (c) 2002 Fabrice Bellard 00004 * 00005 * This file is part of FFmpeg. 00006 * 00007 * FFmpeg is free software; you can redistribute it and/or 00008 * modify it under the terms of the GNU Lesser General Public 00009 * License as published by the Free Software Foundation; either 00010 * version 2.1 of the License, or (at your option) any later version. 00011 * 00012 * FFmpeg is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00015 * Lesser General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU Lesser General Public 00018 * License along with FFmpeg; if not, write to the Free Software 00019 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00020 */ 00021 00027 #include "config.h" 00028 00029 #include <limits.h> 00030 #include <stdlib.h> 00031 #include <string.h> 00032 #if HAVE_MALLOC_H 00033 #include <malloc.h> 00034 #endif 00035 00036 #include "avutil.h" 00037 #include "mem.h" 00038 00039 /* here we can use OS-dependent allocation functions */ 00040 #undef free 00041 #undef malloc 00042 #undef realloc 00043 00044 #ifdef MALLOC_PREFIX 00045 00046 #define malloc AV_JOIN(MALLOC_PREFIX, malloc) 00047 #define memalign AV_JOIN(MALLOC_PREFIX, memalign) 00048 #define posix_memalign AV_JOIN(MALLOC_PREFIX, posix_memalign) 00049 #define realloc AV_JOIN(MALLOC_PREFIX, realloc) 00050 #define free AV_JOIN(MALLOC_PREFIX, free) 00051 00052 void *malloc(size_t size); 00053 void *memalign(size_t align, size_t size); 00054 int posix_memalign(void **ptr, size_t align, size_t size); 00055 void *realloc(void *ptr, size_t size); 00056 void free(void *ptr); 00057 00058 #endif /* MALLOC_PREFIX */ 00059 00060 /* You can redefine av_malloc and av_free in your project to use your 00061 memory allocator. You do not need to suppress this file because the 00062 linker will do it automatically. */ 00063 00064 void *av_malloc(unsigned int size) 00065 { 00066 void *ptr = NULL; 00067 #if CONFIG_MEMALIGN_HACK 00068 long diff; 00069 #endif 00070 00071 /* let's disallow possible ambiguous cases */ 00072 if(size > (INT_MAX-16) ) 00073 return NULL; 00074 00075 #if CONFIG_MEMALIGN_HACK 00076 ptr = malloc(size+16); 00077 if(!ptr) 00078 return ptr; 00079 diff= ((-(long)ptr - 1)&15) + 1; 00080 ptr = (char*)ptr + diff; 00081 ((char*)ptr)[-1]= diff; 00082 #elif HAVE_POSIX_MEMALIGN 00083 if (posix_memalign(&ptr,16,size)) 00084 ptr = NULL; 00085 #elif HAVE_MEMALIGN 00086 ptr = memalign(16,size); 00087 /* Why 64? 00088 Indeed, we should align it: 00089 on 4 for 386 00090 on 16 for 486 00091 on 32 for 586, PPro - K6-III 00092 on 64 for K7 (maybe for P3 too). 00093 Because L1 and L2 caches are aligned on those values. 00094 But I don't want to code such logic here! 00095 */ 00096 /* Why 16? 00097 Because some CPUs need alignment, for example SSE2 on P4, & most RISC CPUs 00098 it will just trigger an exception and the unaligned load will be done in the 00099 exception handler or it will just segfault (SSE2 on P4). 00100 Why not larger? Because I did not see a difference in benchmarks ... 00101 */ 00102 /* benchmarks with P3 00103 memalign(64)+1 3071,3051,3032 00104 memalign(64)+2 3051,3032,3041 00105 memalign(64)+4 2911,2896,2915 00106 memalign(64)+8 2545,2554,2550 00107 memalign(64)+16 2543,2572,2563 00108 memalign(64)+32 2546,2545,2571 00109 memalign(64)+64 2570,2533,2558 00110 00111 BTW, malloc seems to do 8-byte alignment by default here. 00112 */ 00113 #else 00114 ptr = malloc(size); 00115 #endif 00116 return ptr; 00117 } 00118 00119 void *av_realloc(void *ptr, unsigned int size) 00120 { 00121 #if CONFIG_MEMALIGN_HACK 00122 int diff; 00123 #endif 00124 00125 /* let's disallow possible ambiguous cases */ 00126 if(size > (INT_MAX-16) ) 00127 return NULL; 00128 00129 #if CONFIG_MEMALIGN_HACK 00130 //FIXME this isn't aligned correctly, though it probably isn't needed 00131 if(!ptr) return av_malloc(size); 00132 diff= ((char*)ptr)[-1]; 00133 return (char*)realloc((char*)ptr - diff, size + diff) + diff; 00134 #else 00135 return realloc(ptr, size); 00136 #endif 00137 } 00138 00139 void av_free(void *ptr) 00140 { 00141 /* XXX: this test should not be needed on most libcs */ 00142 if (ptr) 00143 #if CONFIG_MEMALIGN_HACK 00144 free((char*)ptr - ((char*)ptr)[-1]); 00145 #else 00146 free(ptr); 00147 #endif 00148 } 00149 00150 void av_freep(void *arg) 00151 { 00152 void **ptr= (void**)arg; 00153 av_free(*ptr); 00154 *ptr = NULL; 00155 } 00156 00157 void *av_mallocz(unsigned int size) 00158 { 00159 void *ptr = av_malloc(size); 00160 if (ptr) 00161 memset(ptr, 0, size); 00162 return ptr; 00163 } 00164 00165 char *av_strdup(const char *s) 00166 { 00167 char *ptr= NULL; 00168 if(s){ 00169 int len = strlen(s) + 1; 00170 ptr = av_malloc(len); 00171 if (ptr) 00172 memcpy(ptr, s, len); 00173 } 00174 return ptr; 00175 } 00176