LCOV - code coverage report
Current view: top level - libavutil - mem.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 176 205 85.9 %
Date: 2017-10-20 23:03:07 Functions: 22 24 91.7 %

          Line data    Source code
       1             : /*
       2             :  * default memory allocator for libavutil
       3             :  * Copyright (c) 2002 Fabrice Bellard
       4             :  *
       5             :  * This file is part of FFmpeg.
       6             :  *
       7             :  * FFmpeg is free software; you can redistribute it and/or
       8             :  * modify it under the terms of the GNU Lesser General Public
       9             :  * License as published by the Free Software Foundation; either
      10             :  * version 2.1 of the License, or (at your option) any later version.
      11             :  *
      12             :  * FFmpeg is distributed in the hope that it will be useful,
      13             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      14             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      15             :  * Lesser General Public License for more details.
      16             :  *
      17             :  * You should have received a copy of the GNU Lesser General Public
      18             :  * License along with FFmpeg; if not, write to the Free Software
      19             :  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
      20             :  */
      21             : 
      22             : /**
      23             :  * @file
      24             :  * default memory allocator for libavutil
      25             :  */
      26             : 
      27             : #define _XOPEN_SOURCE 600
      28             : 
      29             : #include "config.h"
      30             : 
      31             : #include <limits.h>
      32             : #include <stdint.h>
      33             : #include <stdlib.h>
      34             : #include <string.h>
      35             : #if HAVE_MALLOC_H
      36             : #include <malloc.h>
      37             : #endif
      38             : 
      39             : #include "avassert.h"
      40             : #include "avutil.h"
      41             : #include "common.h"
      42             : #include "dynarray.h"
      43             : #include "intreadwrite.h"
      44             : #include "mem.h"
      45             : 
      46             : #ifdef MALLOC_PREFIX
      47             : 
      48             : #define malloc         AV_JOIN(MALLOC_PREFIX, malloc)
      49             : #define memalign       AV_JOIN(MALLOC_PREFIX, memalign)
      50             : #define posix_memalign AV_JOIN(MALLOC_PREFIX, posix_memalign)
      51             : #define realloc        AV_JOIN(MALLOC_PREFIX, realloc)
      52             : #define free           AV_JOIN(MALLOC_PREFIX, free)
      53             : 
      54             : void *malloc(size_t size);
      55             : void *memalign(size_t align, size_t size);
      56             : int   posix_memalign(void **ptr, size_t align, size_t size);
      57             : void *realloc(void *ptr, size_t size);
      58             : void  free(void *ptr);
      59             : 
      60             : #endif /* MALLOC_PREFIX */
      61             : 
      62             : #include "mem_internal.h"
      63             : 
      64             : #define ALIGN (HAVE_AVX ? 32 : 16)
      65             : 
      66             : /* NOTE: if you want to override these functions with your own
      67             :  * implementations (not recommended) you have to link libav* as
      68             :  * dynamic libraries and remove -Wl,-Bsymbolic from the linker flags.
      69             :  * Note that this will cost performance. */
      70             : 
      71             : static size_t max_alloc_size= INT_MAX;
      72             : 
      73           0 : void av_max_alloc(size_t max){
      74           0 :     max_alloc_size = max;
      75           0 : }
      76             : 
      77    54400223 : void *av_malloc(size_t size)
      78             : {
      79    54400223 :     void *ptr = NULL;
      80             : 
      81             :     /* let's disallow possibly ambiguous cases */
      82    54400223 :     if (size > (max_alloc_size - 32))
      83           0 :         return NULL;
      84             : 
      85             : #if HAVE_POSIX_MEMALIGN
      86    54400223 :     if (size) //OS X on SDK 10.6 has a broken posix_memalign implementation
      87    54397922 :     if (posix_memalign(&ptr, ALIGN, size))
      88           0 :         ptr = NULL;
      89             : #elif HAVE_ALIGNED_MALLOC
      90             :     ptr = _aligned_malloc(size, ALIGN);
      91             : #elif HAVE_MEMALIGN
      92             : #ifndef __DJGPP__
      93             :     ptr = memalign(ALIGN, size);
      94             : #else
      95             :     ptr = memalign(size, ALIGN);
      96             : #endif
      97             :     /* Why 64?
      98             :      * Indeed, we should align it:
      99             :      *   on  4 for 386
     100             :      *   on 16 for 486
     101             :      *   on 32 for 586, PPro - K6-III
     102             :      *   on 64 for K7 (maybe for P3 too).
     103             :      * Because L1 and L2 caches are aligned on those values.
     104             :      * But I don't want to code such logic here!
     105             :      */
     106             :     /* Why 32?
     107             :      * For AVX ASM. SSE / NEON needs only 16.
     108             :      * Why not larger? Because I did not see a difference in benchmarks ...
     109             :      */
     110             :     /* benchmarks with P3
     111             :      * memalign(64) + 1          3071, 3051, 3032
     112             :      * memalign(64) + 2          3051, 3032, 3041
     113             :      * memalign(64) + 4          2911, 2896, 2915
     114             :      * memalign(64) + 8          2545, 2554, 2550
     115             :      * memalign(64) + 16         2543, 2572, 2563
     116             :      * memalign(64) + 32         2546, 2545, 2571
     117             :      * memalign(64) + 64         2570, 2533, 2558
     118             :      *
     119             :      * BTW, malloc seems to do 8-byte alignment by default here.
     120             :      */
     121             : #else
     122             :     ptr = malloc(size);
     123             : #endif
     124    54400223 :     if(!ptr && !size) {
     125        2301 :         size = 1;
     126        2301 :         ptr= av_malloc(1);
     127             :     }
     128             : #if CONFIG_MEMORY_POISONING
     129    54400223 :     if (ptr)
     130    54400223 :         memset(ptr, FF_MEMORY_POISON, size);
     131             : #endif
     132    54400223 :     return ptr;
     133             : }
     134             : 
     135    10582318 : void *av_realloc(void *ptr, size_t size)
     136             : {
     137             :     /* let's disallow possibly ambiguous cases */
     138    10582318 :     if (size > (max_alloc_size - 32))
     139           0 :         return NULL;
     140             : 
     141             : #if HAVE_ALIGNED_MALLOC
     142             :     return _aligned_realloc(ptr, size + !size, ALIGN);
     143             : #else
     144    10582318 :     return realloc(ptr, size + !size);
     145             : #endif
     146             : }
     147             : 
     148       54541 : void *av_realloc_f(void *ptr, size_t nelem, size_t elsize)
     149             : {
     150             :     size_t size;
     151             :     void *r;
     152             : 
     153       54541 :     if (av_size_mult(elsize, nelem, &size)) {
     154           0 :         av_free(ptr);
     155           0 :         return NULL;
     156             :     }
     157       54541 :     r = av_realloc(ptr, size);
     158       54541 :     if (!r)
     159           0 :         av_free(ptr);
     160       54541 :     return r;
     161             : }
     162             : 
     163       50137 : int av_reallocp(void *ptr, size_t size)
     164             : {
     165             :     void *val;
     166             : 
     167       50137 :     if (!size) {
     168           9 :         av_freep(ptr);
     169           9 :         return 0;
     170             :     }
     171             : 
     172       50128 :     memcpy(&val, ptr, sizeof(val));
     173       50128 :     val = av_realloc(val, size);
     174             : 
     175       50128 :     if (!val) {
     176           0 :         av_freep(ptr);
     177           0 :         return AVERROR(ENOMEM);
     178             :     }
     179             : 
     180       50128 :     memcpy(ptr, &val, sizeof(val));
     181       50128 :     return 0;
     182             : }
     183             : 
     184     6372480 : void *av_realloc_array(void *ptr, size_t nmemb, size_t size)
     185             : {
     186     6372480 :     if (!size || nmemb >= INT_MAX / size)
     187           0 :         return NULL;
     188     6372480 :     return av_realloc(ptr, nmemb * size);
     189             : }
     190             : 
     191        3602 : int av_reallocp_array(void *ptr, size_t nmemb, size_t size)
     192             : {
     193             :     void *val;
     194             : 
     195        3602 :     memcpy(&val, ptr, sizeof(val));
     196        3602 :     val = av_realloc_f(val, nmemb, size);
     197        3602 :     memcpy(ptr, &val, sizeof(val));
     198        3602 :     if (!val && nmemb && size)
     199           0 :         return AVERROR(ENOMEM);
     200             : 
     201        3602 :     return 0;
     202             : }
     203             : 
     204    81803961 : void av_free(void *ptr)
     205             : {
     206             : #if HAVE_ALIGNED_MALLOC
     207             :     _aligned_free(ptr);
     208             : #else
     209    81803961 :     free(ptr);
     210             : #endif
     211    81803961 : }
     212             : 
     213    39021032 : void av_freep(void *arg)
     214             : {
     215             :     void *val;
     216             : 
     217    39021032 :     memcpy(&val, arg, sizeof(val));
     218    39021032 :     memcpy(arg, &(void *){ NULL }, sizeof(val));
     219    39021032 :     av_free(val);
     220    39021032 : }
     221             : 
     222    13098545 : void *av_mallocz(size_t size)
     223             : {
     224    13098545 :     void *ptr = av_malloc(size);
     225    13098545 :     if (ptr)
     226    13098545 :         memset(ptr, 0, size);
     227    13098545 :     return ptr;
     228             : }
     229             : 
     230       16532 : void *av_calloc(size_t nmemb, size_t size)
     231             : {
     232       16532 :     if (size <= 0 || nmemb >= INT_MAX / size)
     233           0 :         return NULL;
     234       16532 :     return av_mallocz(nmemb * size);
     235             : }
     236             : 
     237     2710573 : char *av_strdup(const char *s)
     238             : {
     239     2710573 :     char *ptr = NULL;
     240     2710573 :     if (s) {
     241     1831500 :         size_t len = strlen(s) + 1;
     242     1831500 :         ptr = av_realloc(NULL, len);
     243     1831500 :         if (ptr)
     244     1831500 :             memcpy(ptr, s, len);
     245             :     }
     246     2710573 :     return ptr;
     247             : }
     248             : 
     249           0 : char *av_strndup(const char *s, size_t len)
     250             : {
     251           0 :     char *ret = NULL, *end;
     252             : 
     253           0 :     if (!s)
     254           0 :         return NULL;
     255             : 
     256           0 :     end = memchr(s, 0, len);
     257           0 :     if (end)
     258           0 :         len = end - s;
     259             : 
     260           0 :     ret = av_realloc(NULL, len + 1);
     261           0 :     if (!ret)
     262           0 :         return NULL;
     263             : 
     264           0 :     memcpy(ret, s, len);
     265           0 :     ret[len] = 0;
     266           0 :     return ret;
     267             : }
     268             : 
     269       91712 : void *av_memdup(const void *p, size_t size)
     270             : {
     271       91712 :     void *ptr = NULL;
     272       91712 :     if (p) {
     273       86422 :         ptr = av_malloc(size);
     274       86422 :         if (ptr)
     275       86422 :             memcpy(ptr, p, size);
     276             :     }
     277       91712 :     return ptr;
     278             : }
     279             : 
     280          18 : int av_dynarray_add_nofree(void *tab_ptr, int *nb_ptr, void *elem)
     281             : {
     282             :     void **tab;
     283          18 :     memcpy(&tab, tab_ptr, sizeof(tab));
     284             : 
     285          18 :     FF_DYNARRAY_ADD(INT_MAX, sizeof(*tab), tab, *nb_ptr, {
     286             :         tab[*nb_ptr] = elem;
     287             :         memcpy(tab_ptr, &tab, sizeof(tab));
     288             :     }, {
     289             :         return AVERROR(ENOMEM);
     290             :     });
     291          18 :     return 0;
     292             : }
     293             : 
     294       28230 : void av_dynarray_add(void *tab_ptr, int *nb_ptr, void *elem)
     295             : {
     296             :     void **tab;
     297       28230 :     memcpy(&tab, tab_ptr, sizeof(tab));
     298             : 
     299       28230 :     FF_DYNARRAY_ADD(INT_MAX, sizeof(*tab), tab, *nb_ptr, {
     300             :         tab[*nb_ptr] = elem;
     301             :         memcpy(tab_ptr, &tab, sizeof(tab));
     302             :     }, {
     303             :         *nb_ptr = 0;
     304             :         av_freep(tab_ptr);
     305             :     });
     306       28230 : }
     307             : 
     308      431233 : void *av_dynarray2_add(void **tab_ptr, int *nb_ptr, size_t elem_size,
     309             :                        const uint8_t *elem_data)
     310             : {
     311      431233 :     uint8_t *tab_elem_data = NULL;
     312             : 
     313      431233 :     FF_DYNARRAY_ADD(INT_MAX, elem_size, *tab_ptr, *nb_ptr, {
     314             :         tab_elem_data = (uint8_t *)*tab_ptr + (*nb_ptr) * elem_size;
     315             :         if (elem_data)
     316             :             memcpy(tab_elem_data, elem_data, elem_size);
     317             :         else if (CONFIG_MEMORY_POISONING)
     318             :             memset(tab_elem_data, FF_MEMORY_POISON, elem_size);
     319             :     }, {
     320             :         av_freep(tab_ptr);
     321             :         *nb_ptr = 0;
     322             :     });
     323      431233 :     return tab_elem_data;
     324             : }
     325             : 
     326       37823 : static void fill16(uint8_t *dst, int len)
     327             : {
     328       37823 :     uint32_t v = AV_RN16(dst - 2);
     329             : 
     330       37823 :     v |= v << 16;
     331             : 
     332      978047 :     while (len >= 4) {
     333      902401 :         AV_WN32(dst, v);
     334      902401 :         dst += 4;
     335      902401 :         len -= 4;
     336             :     }
     337             : 
     338      138880 :     while (len--) {
     339       63234 :         *dst = dst[-2];
     340       63234 :         dst++;
     341             :     }
     342       37823 : }
     343             : 
     344         502 : static void fill24(uint8_t *dst, int len)
     345             : {
     346             : #if HAVE_BIGENDIAN
     347             :     uint32_t v = AV_RB24(dst - 3);
     348             :     uint32_t a = v << 8  | v >> 16;
     349             :     uint32_t b = v << 16 | v >> 8;
     350             :     uint32_t c = v << 24 | v;
     351             : #else
     352         502 :     uint32_t v = AV_RL24(dst - 3);
     353         502 :     uint32_t a = v       | v << 24;
     354         502 :     uint32_t b = v >> 8  | v << 16;
     355         502 :     uint32_t c = v >> 16 | v << 8;
     356             : #endif
     357             : 
     358        1352 :     while (len >= 12) {
     359         348 :         AV_WN32(dst,     a);
     360         348 :         AV_WN32(dst + 4, b);
     361         348 :         AV_WN32(dst + 8, c);
     362         348 :         dst += 12;
     363         348 :         len -= 12;
     364             :     }
     365             : 
     366         502 :     if (len >= 4) {
     367         139 :         AV_WN32(dst, a);
     368         139 :         dst += 4;
     369         139 :         len -= 4;
     370             :     }
     371             : 
     372         502 :     if (len >= 4) {
     373          13 :         AV_WN32(dst, b);
     374          13 :         dst += 4;
     375          13 :         len -= 4;
     376             :     }
     377             : 
     378        2164 :     while (len--) {
     379        1160 :         *dst = dst[-3];
     380        1160 :         dst++;
     381             :     }
     382         502 : }
     383             : 
     384        9904 : static void fill32(uint8_t *dst, int len)
     385             : {
     386        9904 :     uint32_t v = AV_RN32(dst - 4);
     387             : 
     388      636309 :     while (len >= 4) {
     389      616501 :         AV_WN32(dst, v);
     390      616501 :         dst += 4;
     391      616501 :         len -= 4;
     392             :     }
     393             : 
     394       22074 :     while (len--) {
     395        2266 :         *dst = dst[-4];
     396        2266 :         dst++;
     397             :     }
     398        9904 : }
     399             : 
     400      653750 : void av_memcpy_backptr(uint8_t *dst, int back, int cnt)
     401             : {
     402      653750 :     const uint8_t *src = &dst[-back];
     403      653750 :     if (!back)
     404           0 :         return;
     405             : 
     406      653750 :     if (back == 1) {
     407        4422 :         memset(dst, *src, cnt);
     408      649328 :     } else if (back == 2) {
     409       37823 :         fill16(dst, cnt);
     410      611505 :     } else if (back == 3) {
     411         502 :         fill24(dst, cnt);
     412      611003 :     } else if (back == 4) {
     413        9904 :         fill32(dst, cnt);
     414             :     } else {
     415      601099 :         if (cnt >= 16) {
     416       85275 :             int blocklen = back;
     417      185662 :             while (cnt > blocklen) {
     418       15112 :                 memcpy(dst, src, blocklen);
     419       15112 :                 dst       += blocklen;
     420       15112 :                 cnt       -= blocklen;
     421       15112 :                 blocklen <<= 1;
     422             :             }
     423       85275 :             memcpy(dst, src, cnt);
     424       85275 :             return;
     425             :         }
     426      515824 :         if (cnt >= 8) {
     427      107412 :             AV_COPY32U(dst,     src);
     428      107412 :             AV_COPY32U(dst + 4, src + 4);
     429      107412 :             src += 8;
     430      107412 :             dst += 8;
     431      107412 :             cnt -= 8;
     432             :         }
     433      515824 :         if (cnt >= 4) {
     434      376931 :             AV_COPY32U(dst, src);
     435      376931 :             src += 4;
     436      376931 :             dst += 4;
     437      376931 :             cnt -= 4;
     438             :         }
     439      515824 :         if (cnt >= 2) {
     440      184318 :             AV_COPY16U(dst, src);
     441      184318 :             src += 2;
     442      184318 :             dst += 2;
     443      184318 :             cnt -= 2;
     444             :         }
     445      515824 :         if (cnt)
     446      107745 :             *dst = *src;
     447             :     }
     448             : }
     449             : 
     450     1246842 : void *av_fast_realloc(void *ptr, unsigned int *size, size_t min_size)
     451             : {
     452     1246842 :     if (min_size < *size)
     453     1181242 :         return ptr;
     454             : 
     455       65600 :     min_size = FFMAX(min_size + min_size / 16 + 32, min_size);
     456             : 
     457       65600 :     ptr = av_realloc(ptr, min_size);
     458             :     /* we could set this to the unmodified min_size but this is safer
     459             :      * if the user lost the ptr and uses NULL now
     460             :      */
     461       65600 :     if (!ptr)
     462           0 :         min_size = 0;
     463             : 
     464       65600 :     *size = min_size;
     465             : 
     466       65600 :     return ptr;
     467             : }
     468             : 
     469       69858 : void av_fast_malloc(void *ptr, unsigned int *size, size_t min_size)
     470             : {
     471       69858 :     ff_fast_malloc(ptr, size, min_size, 0);
     472       69858 : }
     473             : 
     474       64222 : void av_fast_mallocz(void *ptr, unsigned int *size, size_t min_size)
     475             : {
     476       64222 :     ff_fast_malloc(ptr, size, min_size, 1);
     477       64222 : }

Generated by: LCOV version 1.13