libavutil/mem.c
d01fe86d
 /*
cea8f6f3
  * default memory allocator for libavutil
406792e7
  * Copyright (c) 2002 Fabrice Bellard
d01fe86d
  *
b78e7197
  * This file is part of FFmpeg.
  *
  * FFmpeg is free software; you can redistribute it and/or
d01fe86d
  * modify it under the terms of the GNU Lesser General Public
  * License as published by the Free Software Foundation; either
b78e7197
  * version 2.1 of the License, or (at your option) any later version.
d01fe86d
  *
b78e7197
  * FFmpeg is distributed in the hope that it will be useful,
d01fe86d
  * 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
b78e7197
  * License along with FFmpeg; if not, write to the Free Software
5509bffa
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
d01fe86d
  */
115329f1
 
983e3246
 /**
bad5537e
  * @file libavutil/mem.c
89c9ff50
  * default memory allocator for libavutil
983e3246
  */
115329f1
 
dfcb6b56
 #include "config.h"
8e1e6f31
 
dfcb6b56
 #include <limits.h>
1f91cdce
 #include <stdlib.h>
dfcb6b56
 #include <string.h>
b250f9c6
 #if HAVE_MALLOC_H
d01fe86d
 #include <malloc.h>
 #endif
 
77652a6a
 #include "mem.h"
 
89c9ff50
 /* here we can use OS-dependent allocation functions */
1e60e933
 #undef free
 #undef malloc
 #undef realloc
 
89c9ff50
 /* You can redefine av_malloc and av_free in your project to use your
d01fe86d
    memory allocator. You do not need to suppress this file because the
89c9ff50
    linker will do it automatically. */
d01fe86d
 
18f77016
 void *av_malloc(unsigned int size)
d01fe86d
 {
1f91cdce
     void *ptr = NULL;
b250f9c6
 #if CONFIG_MEMALIGN_HACK
ed96aeea
     long diff;
88730be6
 #endif
0ecca7a4
 
7d77d5f6
     /* let's disallow possible ambiguous cases */
0a7c36af
     if(size > (INT_MAX-16) )
0ecca7a4
         return NULL;
115329f1
 
b250f9c6
 #if CONFIG_MEMALIGN_HACK
a9493601
     ptr = malloc(size+16);
     if(!ptr)
         return ptr;
ed96aeea
     diff= ((-(long)ptr - 1)&15) + 1;
90d30570
     ptr = (char*)ptr + diff;
da9b170c
     ((char*)ptr)[-1]= diff;
b250f9c6
 #elif HAVE_POSIX_MEMALIGN
a90de11d
     if (posix_memalign(&ptr,16,size))
         ptr = NULL;
b250f9c6
 #elif HAVE_MEMALIGN
8f2b21a8
     ptr = memalign(16,size);
115329f1
     /* Why 64?
d01fe86d
        Indeed, we should align it:
          on 4 for 386
          on 16 for 486
89c9ff50
          on 32 for 586, PPro - K6-III
bb270c08
          on 64 for K7 (maybe for P3 too).
d01fe86d
        Because L1 and L2 caches are aligned on those values.
        But I don't want to code such logic here!
      */
8f2b21a8
      /* Why 16?
7ce68923
         Because some CPUs need alignment, for example SSE2 on P4, & most RISC CPUs
8f2b21a8
         it will just trigger an exception and the unaligned load will be done in the
89c9ff50
         exception handler or it will just segfault (SSE2 on P4).
2cab6401
         Why not larger? Because I did not see a difference in benchmarks ...
8f2b21a8
      */
89c9ff50
      /* benchmarks with P3
bb270c08
         memalign(64)+1          3071,3051,3032
         memalign(64)+2          3051,3032,3041
         memalign(64)+4          2911,2896,2915
         memalign(64)+8          2545,2554,2550
         memalign(64)+16         2543,2572,2563
         memalign(64)+32         2546,2545,2571
         memalign(64)+64         2570,2533,2558
115329f1
 
89c9ff50
         BTW, malloc seems to do 8-byte alignment by default here.
8f2b21a8
      */
d01fe86d
 #else
     ptr = malloc(size);
 #endif
     return ptr;
 }
 
8e1e6f31
 void *av_realloc(void *ptr, unsigned int size)
 {
b250f9c6
 #if CONFIG_MEMALIGN_HACK
0a7c36af
     int diff;
 #endif
88730be6
 
7d77d5f6
     /* let's disallow possible ambiguous cases */
a9493601
     if(size > (INT_MAX-16) )
0ecca7a4
         return NULL;
 
b250f9c6
 #if CONFIG_MEMALIGN_HACK
0a7c36af
     //FIXME this isn't aligned correctly, though it probably isn't needed
     if(!ptr) return av_malloc(size);
     diff= ((char*)ptr)[-1];
36e4be0a
     ptr= realloc((char*)ptr - diff, size + diff);
     if(ptr) ptr = (char*)ptr + diff;
     return ptr;
0a7c36af
 #else
     return realloc(ptr, size);
da9b170c
 #endif
b7a22d84
 }
 
d01fe86d
 void av_free(void *ptr)
 {
     /* XXX: this test should not be needed on most libcs */
     if (ptr)
b250f9c6
 #if CONFIG_MEMALIGN_HACK
90d30570
         free((char*)ptr - ((char*)ptr)[-1]);
da9b170c
 #else
d01fe86d
         free(ptr);
da9b170c
 #endif
d01fe86d
 }
 
79e47000
 void av_freep(void *arg)
 {
     void **ptr= (void**)arg;
     av_free(*ptr);
     *ptr = NULL;
 }
 
 void *av_mallocz(unsigned int size)
 {
11362767
     void *ptr = av_malloc(size);
79e47000
     if (ptr)
         memset(ptr, 0, size);
     return ptr;
 }
 
 char *av_strdup(const char *s)
 {
fdf35f26
     char *ptr= NULL;
     if(s){
19757f61
         int len = strlen(s) + 1;
         ptr = av_malloc(len);
         if (ptr)
             memcpy(ptr, s, len);
fdf35f26
     }
79e47000
     return ptr;
 }