LCOV - code coverage report
Current view: top level - libavutil - mem.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 182 213 85.4 %
Date: 2017-12-14 19:11:59 Functions: 24 26 92.3 %

          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    56380200 : void *av_malloc(size_t size)
      78             : {
      79    56380200 :     void *ptr = NULL;
      80             : 
      81             :     /* let's disallow possibly ambiguous cases */
      82    56380200 :     if (size > (max_alloc_size - 32))
      83           0 :         return NULL;
      84             : 
      85             : #if HAVE_POSIX_MEMALIGN
      86    56380200 :     if (size) //OS X on SDK 10.6 has a broken posix_memalign implementation
      87    56377668 :     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    56380200 :     if(!ptr && !size) {
     125        2532 :         size = 1;
     126        2532 :         ptr= av_malloc(1);
     127             :     }
     128             : #if CONFIG_MEMORY_POISONING
     129    56380200 :     if (ptr)
     130    56380200 :         memset(ptr, FF_MEMORY_POISON, size);
     131             : #endif
     132    56380200 :     return ptr;
     133             : }
     134             : 
     135    11049555 : void *av_realloc(void *ptr, size_t size)
     136             : {
     137             :     /* let's disallow possibly ambiguous cases */
     138    11049555 :     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    11049555 :     return realloc(ptr, size + !size);
     145             : #endif
     146             : }
     147             : 
     148       54648 : void *av_realloc_f(void *ptr, size_t nelem, size_t elsize)
     149             : {
     150             :     size_t size;
     151             :     void *r;
     152             : 
     153       54648 :     if (av_size_mult(elsize, nelem, &size)) {
     154           0 :         av_free(ptr);
     155           0 :         return NULL;
     156             :     }
     157       54648 :     r = av_realloc(ptr, size);
     158       54648 :     if (!r)
     159           0 :         av_free(ptr);
     160       54648 :     return r;
     161             : }
     162             : 
     163       50154 : int av_reallocp(void *ptr, size_t size)
     164             : {
     165             :     void *val;
     166             : 
     167       50154 :     if (!size) {
     168           9 :         av_freep(ptr);
     169           9 :         return 0;
     170             :     }
     171             : 
     172       50145 :     memcpy(&val, ptr, sizeof(val));
     173       50145 :     val = av_realloc(val, size);
     174             : 
     175       50145 :     if (!val) {
     176           0 :         av_freep(ptr);
     177           0 :         return AVERROR(ENOMEM);
     178             :     }
     179             : 
     180       50145 :     memcpy(ptr, &val, sizeof(val));
     181       50145 :     return 0;
     182             : }
     183             : 
     184    40865852 : void *av_malloc_array(size_t nmemb, size_t size)
     185             : {
     186    40865852 :     if (!size || nmemb >= INT_MAX / size)
     187           0 :         return NULL;
     188    40865852 :     return av_malloc(nmemb * size);
     189             : }
     190             : 
     191      650149 : void *av_mallocz_array(size_t nmemb, size_t size)
     192             : {
     193      650149 :     if (!size || nmemb >= INT_MAX / size)
     194           0 :         return NULL;
     195      650149 :     return av_mallocz(nmemb * size);
     196             : }
     197             : 
     198     6130654 : void *av_realloc_array(void *ptr, size_t nmemb, size_t size)
     199             : {
     200     6130654 :     if (!size || nmemb >= INT_MAX / size)
     201           0 :         return NULL;
     202     6130654 :     return av_realloc(ptr, nmemb * size);
     203             : }
     204             : 
     205        3624 : int av_reallocp_array(void *ptr, size_t nmemb, size_t size)
     206             : {
     207             :     void *val;
     208             : 
     209        3624 :     memcpy(&val, ptr, sizeof(val));
     210        3624 :     val = av_realloc_f(val, nmemb, size);
     211        3624 :     memcpy(ptr, &val, sizeof(val));
     212        3624 :     if (!val && nmemb && size)
     213           0 :         return AVERROR(ENOMEM);
     214             : 
     215        3624 :     return 0;
     216             : }
     217             : 
     218    84652063 : void av_free(void *ptr)
     219             : {
     220             : #if HAVE_ALIGNED_MALLOC
     221             :     _aligned_free(ptr);
     222             : #else
     223    84652063 :     free(ptr);
     224             : #endif
     225    84652063 : }
     226             : 
     227    41265750 : void av_freep(void *arg)
     228             : {
     229             :     void *val;
     230             : 
     231    41265750 :     memcpy(&val, arg, sizeof(val));
     232    41265750 :     memcpy(arg, &(void *){ NULL }, sizeof(val));
     233    41265750 :     av_free(val);
     234    41265750 : }
     235             : 
     236    14457940 : void *av_mallocz(size_t size)
     237             : {
     238    14457940 :     void *ptr = av_malloc(size);
     239    14457940 :     if (ptr)
     240    14457940 :         memset(ptr, 0, size);
     241    14457940 :     return ptr;
     242             : }
     243             : 
     244       16649 : void *av_calloc(size_t nmemb, size_t size)
     245             : {
     246       16649 :     if (size <= 0 || nmemb >= INT_MAX / size)
     247           0 :         return NULL;
     248       16649 :     return av_mallocz(nmemb * size);
     249             : }
     250             : 
     251     2638982 : char *av_strdup(const char *s)
     252             : {
     253     2638982 :     char *ptr = NULL;
     254     2638982 :     if (s) {
     255     1807057 :         size_t len = strlen(s) + 1;
     256     1807057 :         ptr = av_realloc(NULL, len);
     257     1807057 :         if (ptr)
     258     1807057 :             memcpy(ptr, s, len);
     259             :     }
     260     2638982 :     return ptr;
     261             : }
     262             : 
     263           0 : char *av_strndup(const char *s, size_t len)
     264             : {
     265           0 :     char *ret = NULL, *end;
     266             : 
     267           0 :     if (!s)
     268           0 :         return NULL;
     269             : 
     270           0 :     end = memchr(s, 0, len);
     271           0 :     if (end)
     272           0 :         len = end - s;
     273             : 
     274           0 :     ret = av_realloc(NULL, len + 1);
     275           0 :     if (!ret)
     276           0 :         return NULL;
     277             : 
     278           0 :     memcpy(ret, s, len);
     279           0 :     ret[len] = 0;
     280           0 :     return ret;
     281             : }
     282             : 
     283       92656 : void *av_memdup(const void *p, size_t size)
     284             : {
     285       92656 :     void *ptr = NULL;
     286       92656 :     if (p) {
     287       87354 :         ptr = av_malloc(size);
     288       87354 :         if (ptr)
     289       87354 :             memcpy(ptr, p, size);
     290             :     }
     291       92656 :     return ptr;
     292             : }
     293             : 
     294          18 : int av_dynarray_add_nofree(void *tab_ptr, int *nb_ptr, void *elem)
     295             : {
     296             :     void **tab;
     297          18 :     memcpy(&tab, tab_ptr, sizeof(tab));
     298             : 
     299          18 :     FF_DYNARRAY_ADD(INT_MAX, sizeof(*tab), tab, *nb_ptr, {
     300             :         tab[*nb_ptr] = elem;
     301             :         memcpy(tab_ptr, &tab, sizeof(tab));
     302             :     }, {
     303             :         return AVERROR(ENOMEM);
     304             :     });
     305          18 :     return 0;
     306             : }
     307             : 
     308       28231 : void av_dynarray_add(void *tab_ptr, int *nb_ptr, void *elem)
     309             : {
     310             :     void **tab;
     311       28231 :     memcpy(&tab, tab_ptr, sizeof(tab));
     312             : 
     313       28231 :     FF_DYNARRAY_ADD(INT_MAX, sizeof(*tab), tab, *nb_ptr, {
     314             :         tab[*nb_ptr] = elem;
     315             :         memcpy(tab_ptr, &tab, sizeof(tab));
     316             :     }, {
     317             :         *nb_ptr = 0;
     318             :         av_freep(tab_ptr);
     319             :     });
     320       28231 : }
     321             : 
     322      469851 : void *av_dynarray2_add(void **tab_ptr, int *nb_ptr, size_t elem_size,
     323             :                        const uint8_t *elem_data)
     324             : {
     325      469851 :     uint8_t *tab_elem_data = NULL;
     326             : 
     327      469851 :     FF_DYNARRAY_ADD(INT_MAX, elem_size, *tab_ptr, *nb_ptr, {
     328             :         tab_elem_data = (uint8_t *)*tab_ptr + (*nb_ptr) * elem_size;
     329             :         if (elem_data)
     330             :             memcpy(tab_elem_data, elem_data, elem_size);
     331             :         else if (CONFIG_MEMORY_POISONING)
     332             :             memset(tab_elem_data, FF_MEMORY_POISON, elem_size);
     333             :     }, {
     334             :         av_freep(tab_ptr);
     335             :         *nb_ptr = 0;
     336             :     });
     337      469851 :     return tab_elem_data;
     338             : }
     339             : 
     340       37823 : static void fill16(uint8_t *dst, int len)
     341             : {
     342       37823 :     uint32_t v = AV_RN16(dst - 2);
     343             : 
     344       37823 :     v |= v << 16;
     345             : 
     346      978047 :     while (len >= 4) {
     347      902401 :         AV_WN32(dst, v);
     348      902401 :         dst += 4;
     349      902401 :         len -= 4;
     350             :     }
     351             : 
     352      138880 :     while (len--) {
     353       63234 :         *dst = dst[-2];
     354       63234 :         dst++;
     355             :     }
     356       37823 : }
     357             : 
     358         502 : static void fill24(uint8_t *dst, int len)
     359             : {
     360             : #if HAVE_BIGENDIAN
     361             :     uint32_t v = AV_RB24(dst - 3);
     362             :     uint32_t a = v << 8  | v >> 16;
     363             :     uint32_t b = v << 16 | v >> 8;
     364             :     uint32_t c = v << 24 | v;
     365             : #else
     366         502 :     uint32_t v = AV_RL24(dst - 3);
     367         502 :     uint32_t a = v       | v << 24;
     368         502 :     uint32_t b = v >> 8  | v << 16;
     369         502 :     uint32_t c = v >> 16 | v << 8;
     370             : #endif
     371             : 
     372        1352 :     while (len >= 12) {
     373         348 :         AV_WN32(dst,     a);
     374         348 :         AV_WN32(dst + 4, b);
     375         348 :         AV_WN32(dst + 8, c);
     376         348 :         dst += 12;
     377         348 :         len -= 12;
     378             :     }
     379             : 
     380         502 :     if (len >= 4) {
     381         139 :         AV_WN32(dst, a);
     382         139 :         dst += 4;
     383         139 :         len -= 4;
     384             :     }
     385             : 
     386         502 :     if (len >= 4) {
     387          13 :         AV_WN32(dst, b);
     388          13 :         dst += 4;
     389          13 :         len -= 4;
     390             :     }
     391             : 
     392        2164 :     while (len--) {
     393        1160 :         *dst = dst[-3];
     394        1160 :         dst++;
     395             :     }
     396         502 : }
     397             : 
     398        9904 : static void fill32(uint8_t *dst, int len)
     399             : {
     400        9904 :     uint32_t v = AV_RN32(dst - 4);
     401             : 
     402      636309 :     while (len >= 4) {
     403      616501 :         AV_WN32(dst, v);
     404      616501 :         dst += 4;
     405      616501 :         len -= 4;
     406             :     }
     407             : 
     408       22074 :     while (len--) {
     409        2266 :         *dst = dst[-4];
     410        2266 :         dst++;
     411             :     }
     412        9904 : }
     413             : 
     414      653750 : void av_memcpy_backptr(uint8_t *dst, int back, int cnt)
     415             : {
     416      653750 :     const uint8_t *src = &dst[-back];
     417      653750 :     if (!back)
     418           0 :         return;
     419             : 
     420      653750 :     if (back == 1) {
     421        4422 :         memset(dst, *src, cnt);
     422      649328 :     } else if (back == 2) {
     423       37823 :         fill16(dst, cnt);
     424      611505 :     } else if (back == 3) {
     425         502 :         fill24(dst, cnt);
     426      611003 :     } else if (back == 4) {
     427        9904 :         fill32(dst, cnt);
     428             :     } else {
     429      601099 :         if (cnt >= 16) {
     430       85275 :             int blocklen = back;
     431      185662 :             while (cnt > blocklen) {
     432       15112 :                 memcpy(dst, src, blocklen);
     433       15112 :                 dst       += blocklen;
     434       15112 :                 cnt       -= blocklen;
     435       15112 :                 blocklen <<= 1;
     436             :             }
     437       85275 :             memcpy(dst, src, cnt);
     438       85275 :             return;
     439             :         }
     440      515824 :         if (cnt >= 8) {
     441      107412 :             AV_COPY32U(dst,     src);
     442      107412 :             AV_COPY32U(dst + 4, src + 4);
     443      107412 :             src += 8;
     444      107412 :             dst += 8;
     445      107412 :             cnt -= 8;
     446             :         }
     447      515824 :         if (cnt >= 4) {
     448      376931 :             AV_COPY32U(dst, src);
     449      376931 :             src += 4;
     450      376931 :             dst += 4;
     451      376931 :             cnt -= 4;
     452             :         }
     453      515824 :         if (cnt >= 2) {
     454      184318 :             AV_COPY16U(dst, src);
     455      184318 :             src += 2;
     456      184318 :             dst += 2;
     457      184318 :             cnt -= 2;
     458             :         }
     459      515824 :         if (cnt)
     460      107745 :             *dst = *src;
     461             :     }
     462             : }
     463             : 
     464     1242038 : void *av_fast_realloc(void *ptr, unsigned int *size, size_t min_size)
     465             : {
     466     1242038 :     if (min_size < *size)
     467     1176197 :         return ptr;
     468             : 
     469       65841 :     min_size = FFMAX(min_size + min_size / 16 + 32, min_size);
     470             : 
     471       65841 :     ptr = av_realloc(ptr, min_size);
     472             :     /* we could set this to the unmodified min_size but this is safer
     473             :      * if the user lost the ptr and uses NULL now
     474             :      */
     475       65841 :     if (!ptr)
     476           0 :         min_size = 0;
     477             : 
     478       65841 :     *size = min_size;
     479             : 
     480       65841 :     return ptr;
     481             : }
     482             : 
     483       70966 : void av_fast_malloc(void *ptr, unsigned int *size, size_t min_size)
     484             : {
     485       70966 :     ff_fast_malloc(ptr, size, min_size, 0);
     486       70966 : }
     487             : 
     488       65318 : void av_fast_mallocz(void *ptr, unsigned int *size, size_t min_size)
     489             : {
     490       65318 :     ff_fast_malloc(ptr, size, min_size, 1);
     491       65318 : }

Generated by: LCOV version 1.13