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 #define _XOPEN_SOURCE 600 00028 00029 #include "config.h" 00030 00031 #include <limits.h> 00032 #include <stdlib.h> 00033 #include <string.h> 00034 #if HAVE_MALLOC_H 00035 #include <malloc.h> 00036 #endif 00037 00038 #include "avutil.h" 00039 #include "mem.h" 00040 00041 /* here we can use OS-dependent allocation functions */ 00042 #undef free 00043 #undef malloc 00044 #undef realloc 00045 00046 #ifdef MALLOC_PREFIX 00047 00048 #define malloc AV_JOIN(MALLOC_PREFIX, malloc) 00049 #define memalign AV_JOIN(MALLOC_PREFIX, memalign) 00050 #define posix_memalign AV_JOIN(MALLOC_PREFIX, posix_memalign) 00051 #define realloc AV_JOIN(MALLOC_PREFIX, realloc) 00052 #define free AV_JOIN(MALLOC_PREFIX, free) 00053 00054 void *malloc(size_t size); 00055 void *memalign(size_t align, size_t size); 00056 int posix_memalign(void **ptr, size_t align, size_t size); 00057 void *realloc(void *ptr, size_t size); 00058 void free(void *ptr); 00059 00060 #endif /* MALLOC_PREFIX */ 00061 00062 #define ALIGN (HAVE_AVX ? 32 : 16) 00063 00064 /* You can redefine av_malloc and av_free in your project to use your 00065 memory allocator. You do not need to suppress this file because the 00066 linker will do it automatically. */ 00067 00068 #define MAX_MALLOC_SIZE INT_MAX 00069 00070 void *av_malloc(size_t size) 00071 { 00072 void *ptr = NULL; 00073 #if CONFIG_MEMALIGN_HACK 00074 long diff; 00075 #endif 00076 00077 /* let's disallow possible ambiguous cases */ 00078 if (size > (MAX_MALLOC_SIZE-32)) 00079 return NULL; 00080 00081 #if CONFIG_MEMALIGN_HACK 00082 ptr = malloc(size+ALIGN); 00083 if(!ptr) 00084 return ptr; 00085 diff= ((-(long)ptr - 1)&(ALIGN-1)) + 1; 00086 ptr = (char*)ptr + diff; 00087 ((char*)ptr)[-1]= diff; 00088 #elif HAVE_POSIX_MEMALIGN 00089 if (size) //OS X on SDK 10.6 has a broken posix_memalign implementation 00090 if (posix_memalign(&ptr,ALIGN,size)) 00091 ptr = NULL; 00092 #elif HAVE_MEMALIGN 00093 ptr = memalign(ALIGN,size); 00094 /* Why 64? 00095 Indeed, we should align it: 00096 on 4 for 386 00097 on 16 for 486 00098 on 32 for 586, PPro - K6-III 00099 on 64 for K7 (maybe for P3 too). 00100 Because L1 and L2 caches are aligned on those values. 00101 But I don't want to code such logic here! 00102 */ 00103 /* Why 32? 00104 For AVX ASM. SSE / NEON needs only 16. 00105 Why not larger? Because I did not see a difference in benchmarks ... 00106 */ 00107 /* benchmarks with P3 00108 memalign(64)+1 3071,3051,3032 00109 memalign(64)+2 3051,3032,3041 00110 memalign(64)+4 2911,2896,2915 00111 memalign(64)+8 2545,2554,2550 00112 memalign(64)+16 2543,2572,2563 00113 memalign(64)+32 2546,2545,2571 00114 memalign(64)+64 2570,2533,2558 00115 00116 BTW, malloc seems to do 8-byte alignment by default here. 00117 */ 00118 #else 00119 ptr = malloc(size); 00120 #endif 00121 if(!ptr && !size) 00122 ptr= av_malloc(1); 00123 return ptr; 00124 } 00125 00126 void *av_realloc(void *ptr, size_t size) 00127 { 00128 #if CONFIG_MEMALIGN_HACK 00129 int diff; 00130 #endif 00131 00132 /* let's disallow possible ambiguous cases */ 00133 if (size > (MAX_MALLOC_SIZE-16)) 00134 return NULL; 00135 00136 #if CONFIG_MEMALIGN_HACK 00137 //FIXME this isn't aligned correctly, though it probably isn't needed 00138 if(!ptr) return av_malloc(size); 00139 diff= ((char*)ptr)[-1]; 00140 ptr= realloc((char*)ptr - diff, size + diff); 00141 if(ptr) ptr = (char*)ptr + diff; 00142 return ptr; 00143 #else 00144 return realloc(ptr, size + !size); 00145 #endif 00146 } 00147 00148 void *av_realloc_f(void *ptr, size_t nelem, size_t elsize) 00149 { 00150 size_t size; 00151 void *r; 00152 00153 if (av_size_mult(elsize, nelem, &size)) { 00154 av_free(ptr); 00155 return NULL; 00156 } 00157 r = av_realloc(ptr, size); 00158 if (!r && size) 00159 av_free(ptr); 00160 return r; 00161 } 00162 00163 void av_free(void *ptr) 00164 { 00165 #if CONFIG_MEMALIGN_HACK 00166 if (ptr) 00167 free((char*)ptr - ((char*)ptr)[-1]); 00168 #else 00169 free(ptr); 00170 #endif 00171 } 00172 00173 void av_freep(void *arg) 00174 { 00175 void **ptr= (void**)arg; 00176 av_free(*ptr); 00177 *ptr = NULL; 00178 } 00179 00180 void *av_mallocz(size_t size) 00181 { 00182 void *ptr = av_malloc(size); 00183 if (ptr) 00184 memset(ptr, 0, size); 00185 return ptr; 00186 } 00187 00188 void *av_calloc(size_t nmemb, size_t size) 00189 { 00190 if (size <= 0 || nmemb >= INT_MAX / size) 00191 return NULL; 00192 return av_mallocz(nmemb * size); 00193 } 00194 00195 char *av_strdup(const char *s) 00196 { 00197 char *ptr= NULL; 00198 if(s){ 00199 int len = strlen(s) + 1; 00200 ptr = av_malloc(len); 00201 if (ptr) 00202 memcpy(ptr, s, len); 00203 } 00204 return ptr; 00205 } 00206 00207 /* add one element to a dynamic array */ 00208 void av_dynarray_add(void *tab_ptr, int *nb_ptr, void *elem) 00209 { 00210 /* see similar ffmpeg.c:grow_array() */ 00211 int nb, nb_alloc; 00212 intptr_t *tab; 00213 00214 nb = *nb_ptr; 00215 tab = *(intptr_t**)tab_ptr; 00216 if ((nb & (nb - 1)) == 0) { 00217 if (nb == 0) 00218 nb_alloc = 1; 00219 else 00220 nb_alloc = nb * 2; 00221 tab = av_realloc(tab, nb_alloc * sizeof(intptr_t)); 00222 *(intptr_t**)tab_ptr = tab; 00223 } 00224 tab[nb++] = (intptr_t)elem; 00225 *nb_ptr = nb; 00226 }