Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  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. void av_max_alloc(size_t max){
  74.     max_alloc_size = max;
  75. }
  76.  
  77. void *av_malloc(size_t size)
  78. {
  79.     void *ptr = NULL;
  80. #if CONFIG_MEMALIGN_HACK
  81.     long diff;
  82. #endif
  83.  
  84.     /* let's disallow possibly ambiguous cases */
  85.     if (size > (max_alloc_size - 32))
  86.         return NULL;
  87.  
  88. #if CONFIG_MEMALIGN_HACK
  89.     ptr = malloc(size + ALIGN);
  90.     if (!ptr)
  91.         return ptr;
  92.     diff              = ((~(long)ptr)&(ALIGN - 1)) + 1;
  93.     ptr               = (char *)ptr + diff;
  94.     ((char *)ptr)[-1] = diff;
  95. #elif HAVE_POSIX_MEMALIGN
  96.     if (size) //OS X on SDK 10.6 has a broken posix_memalign implementation
  97.     if (posix_memalign(&ptr, ALIGN, size))
  98.         ptr = NULL;
  99. #elif HAVE_ALIGNED_MALLOC
  100.     ptr = _aligned_malloc(size, ALIGN);
  101. #elif HAVE_MEMALIGN
  102. #ifndef __DJGPP__
  103.     ptr = memalign(ALIGN, size);
  104. #else
  105.     ptr = memalign(size, ALIGN);
  106. #endif
  107.     /* Why 64?
  108.      * Indeed, we should align it:
  109.      *   on  4 for 386
  110.      *   on 16 for 486
  111.      *   on 32 for 586, PPro - K6-III
  112.      *   on 64 for K7 (maybe for P3 too).
  113.      * Because L1 and L2 caches are aligned on those values.
  114.      * But I don't want to code such logic here!
  115.      */
  116.     /* Why 32?
  117.      * For AVX ASM. SSE / NEON needs only 16.
  118.      * Why not larger? Because I did not see a difference in benchmarks ...
  119.      */
  120.     /* benchmarks with P3
  121.      * memalign(64) + 1          3071, 3051, 3032
  122.      * memalign(64) + 2          3051, 3032, 3041
  123.      * memalign(64) + 4          2911, 2896, 2915
  124.      * memalign(64) + 8          2545, 2554, 2550
  125.      * memalign(64) + 16         2543, 2572, 2563
  126.      * memalign(64) + 32         2546, 2545, 2571
  127.      * memalign(64) + 64         2570, 2533, 2558
  128.      *
  129.      * BTW, malloc seems to do 8-byte alignment by default here.
  130.      */
  131. #else
  132.     ptr = malloc(size);
  133. #endif
  134.     if(!ptr && !size) {
  135.         size = 1;
  136.         ptr= av_malloc(1);
  137.     }
  138. #if CONFIG_MEMORY_POISONING
  139.     if (ptr)
  140.         memset(ptr, FF_MEMORY_POISON, size);
  141. #endif
  142.     return ptr;
  143. }
  144.  
  145. void *av_realloc(void *ptr, size_t size)
  146. {
  147. #if CONFIG_MEMALIGN_HACK
  148.     int diff;
  149. #endif
  150.  
  151.     /* let's disallow possibly ambiguous cases */
  152.     if (size > (max_alloc_size - 32))
  153.         return NULL;
  154.  
  155. #if CONFIG_MEMALIGN_HACK
  156.     //FIXME this isn't aligned correctly, though it probably isn't needed
  157.     if (!ptr)
  158.         return av_malloc(size);
  159.     diff = ((char *)ptr)[-1];
  160.     av_assert0(diff>0 && diff<=ALIGN);
  161.     ptr = realloc((char *)ptr - diff, size + diff);
  162.     if (ptr)
  163.         ptr = (char *)ptr + diff;
  164.     return ptr;
  165. #elif HAVE_ALIGNED_MALLOC
  166.     return _aligned_realloc(ptr, size + !size, ALIGN);
  167. #else
  168.     return realloc(ptr, size + !size);
  169. #endif
  170. }
  171.  
  172. void *av_realloc_f(void *ptr, size_t nelem, size_t elsize)
  173. {
  174.     size_t size;
  175.     void *r;
  176.  
  177.     if (av_size_mult(elsize, nelem, &size)) {
  178.         av_free(ptr);
  179.         return NULL;
  180.     }
  181.     r = av_realloc(ptr, size);
  182.     if (!r && size)
  183.         av_free(ptr);
  184.     return r;
  185. }
  186.  
  187. int av_reallocp(void *ptr, size_t size)
  188. {
  189.     void *val;
  190.  
  191.     if (!size) {
  192.         av_freep(ptr);
  193.         return 0;
  194.     }
  195.  
  196.     memcpy(&val, ptr, sizeof(val));
  197.     val = av_realloc(val, size);
  198.  
  199.     if (!val) {
  200.         av_freep(ptr);
  201.         return AVERROR(ENOMEM);
  202.     }
  203.  
  204.     memcpy(ptr, &val, sizeof(val));
  205.     return 0;
  206. }
  207.  
  208. void *av_realloc_array(void *ptr, size_t nmemb, size_t size)
  209. {
  210.     if (!size || nmemb >= INT_MAX / size)
  211.         return NULL;
  212.     return av_realloc(ptr, nmemb * size);
  213. }
  214.  
  215. int av_reallocp_array(void *ptr, size_t nmemb, size_t size)
  216. {
  217.     void *val;
  218.  
  219.     memcpy(&val, ptr, sizeof(val));
  220.     val = av_realloc_f(val, nmemb, size);
  221.     memcpy(ptr, &val, sizeof(val));
  222.     if (!val && nmemb && size)
  223.         return AVERROR(ENOMEM);
  224.  
  225.     return 0;
  226. }
  227.  
  228. void av_free(void *ptr)
  229. {
  230. #if CONFIG_MEMALIGN_HACK
  231.     if (ptr) {
  232.         int v= ((char *)ptr)[-1];
  233.         av_assert0(v>0 && v<=ALIGN);
  234.         free((char *)ptr - v);
  235.     }
  236. #elif HAVE_ALIGNED_MALLOC
  237.     _aligned_free(ptr);
  238. #else
  239.     free(ptr);
  240. #endif
  241. }
  242.  
  243. void av_freep(void *arg)
  244. {
  245.     void *val;
  246.  
  247.     memcpy(&val, arg, sizeof(val));
  248.     memcpy(arg, &(void *){ NULL }, sizeof(val));
  249.     av_free(val);
  250. }
  251.  
  252. void *av_mallocz(size_t size)
  253. {
  254.     void *ptr = av_malloc(size);
  255.     if (ptr)
  256.         memset(ptr, 0, size);
  257.     return ptr;
  258. }
  259.  
  260. void *av_calloc(size_t nmemb, size_t size)
  261. {
  262.     if (size <= 0 || nmemb >= INT_MAX / size)
  263.         return NULL;
  264.     return av_mallocz(nmemb * size);
  265. }
  266.  
  267. char *av_strdup(const char *s)
  268. {
  269.     char *ptr = NULL;
  270.     if (s) {
  271.         size_t len = strlen(s) + 1;
  272.         ptr = av_realloc(NULL, len);
  273.         if (ptr)
  274.             memcpy(ptr, s, len);
  275.     }
  276.     return ptr;
  277. }
  278.  
  279. char *av_strndup(const char *s, size_t len)
  280. {
  281.     char *ret = NULL, *end;
  282.  
  283.     if (!s)
  284.         return NULL;
  285.  
  286.     end = memchr(s, 0, len);
  287.     if (end)
  288.         len = end - s;
  289.  
  290.     ret = av_realloc(NULL, len + 1);
  291.     if (!ret)
  292.         return NULL;
  293.  
  294.     memcpy(ret, s, len);
  295.     ret[len] = 0;
  296.     return ret;
  297. }
  298.  
  299. void *av_memdup(const void *p, size_t size)
  300. {
  301.     void *ptr = NULL;
  302.     if (p) {
  303.         ptr = av_malloc(size);
  304.         if (ptr)
  305.             memcpy(ptr, p, size);
  306.     }
  307.     return ptr;
  308. }
  309.  
  310. int av_dynarray_add_nofree(void *tab_ptr, int *nb_ptr, void *elem)
  311. {
  312.     void **tab;
  313.     memcpy(&tab, tab_ptr, sizeof(tab));
  314.  
  315.     AV_DYNARRAY_ADD(INT_MAX, sizeof(*tab), tab, *nb_ptr, {
  316.         tab[*nb_ptr] = elem;
  317.         memcpy(tab_ptr, &tab, sizeof(tab));
  318.     }, {
  319.         return AVERROR(ENOMEM);
  320.     });
  321.     return 0;
  322. }
  323.  
  324. void av_dynarray_add(void *tab_ptr, int *nb_ptr, void *elem)
  325. {
  326.     void **tab;
  327.     memcpy(&tab, tab_ptr, sizeof(tab));
  328.  
  329.     AV_DYNARRAY_ADD(INT_MAX, sizeof(*tab), tab, *nb_ptr, {
  330.         tab[*nb_ptr] = elem;
  331.         memcpy(tab_ptr, &tab, sizeof(tab));
  332.     }, {
  333.         *nb_ptr = 0;
  334.         av_freep(tab_ptr);
  335.     });
  336. }
  337.  
  338. void *av_dynarray2_add(void **tab_ptr, int *nb_ptr, size_t elem_size,
  339.                        const uint8_t *elem_data)
  340. {
  341.     uint8_t *tab_elem_data = NULL;
  342.  
  343.     AV_DYNARRAY_ADD(INT_MAX, elem_size, *tab_ptr, *nb_ptr, {
  344.         tab_elem_data = (uint8_t *)*tab_ptr + (*nb_ptr) * elem_size;
  345.         if (elem_data)
  346.             memcpy(tab_elem_data, elem_data, elem_size);
  347.         else if (CONFIG_MEMORY_POISONING)
  348.             memset(tab_elem_data, FF_MEMORY_POISON, elem_size);
  349.     }, {
  350.         av_freep(tab_ptr);
  351.         *nb_ptr = 0;
  352.     });
  353.     return tab_elem_data;
  354. }
  355.  
  356. static void fill16(uint8_t *dst, int len)
  357. {
  358.     uint32_t v = AV_RN16(dst - 2);
  359.  
  360.     v |= v << 16;
  361.  
  362.     while (len >= 4) {
  363.         AV_WN32(dst, v);
  364.         dst += 4;
  365.         len -= 4;
  366.     }
  367.  
  368.     while (len--) {
  369.         *dst = dst[-2];
  370.         dst++;
  371.     }
  372. }
  373.  
  374. static void fill24(uint8_t *dst, int len)
  375. {
  376. #if HAVE_BIGENDIAN
  377.     uint32_t v = AV_RB24(dst - 3);
  378.     uint32_t a = v << 8  | v >> 16;
  379.     uint32_t b = v << 16 | v >> 8;
  380.     uint32_t c = v << 24 | v;
  381. #else
  382.     uint32_t v = AV_RL24(dst - 3);
  383.     uint32_t a = v       | v << 24;
  384.     uint32_t b = v >> 8  | v << 16;
  385.     uint32_t c = v >> 16 | v << 8;
  386. #endif
  387.  
  388.     while (len >= 12) {
  389.         AV_WN32(dst,     a);
  390.         AV_WN32(dst + 4, b);
  391.         AV_WN32(dst + 8, c);
  392.         dst += 12;
  393.         len -= 12;
  394.     }
  395.  
  396.     if (len >= 4) {
  397.         AV_WN32(dst, a);
  398.         dst += 4;
  399.         len -= 4;
  400.     }
  401.  
  402.     if (len >= 4) {
  403.         AV_WN32(dst, b);
  404.         dst += 4;
  405.         len -= 4;
  406.     }
  407.  
  408.     while (len--) {
  409.         *dst = dst[-3];
  410.         dst++;
  411.     }
  412. }
  413.  
  414. static void fill32(uint8_t *dst, int len)
  415. {
  416.     uint32_t v = AV_RN32(dst - 4);
  417.  
  418.     while (len >= 4) {
  419.         AV_WN32(dst, v);
  420.         dst += 4;
  421.         len -= 4;
  422.     }
  423.  
  424.     while (len--) {
  425.         *dst = dst[-4];
  426.         dst++;
  427.     }
  428. }
  429.  
  430. void av_memcpy_backptr(uint8_t *dst, int back, int cnt)
  431. {
  432.     const uint8_t *src = &dst[-back];
  433.     if (!back)
  434.         return;
  435.  
  436.     if (back == 1) {
  437.         memset(dst, *src, cnt);
  438.     } else if (back == 2) {
  439.         fill16(dst, cnt);
  440.     } else if (back == 3) {
  441.         fill24(dst, cnt);
  442.     } else if (back == 4) {
  443.         fill32(dst, cnt);
  444.     } else {
  445.         if (cnt >= 16) {
  446.             int blocklen = back;
  447.             while (cnt > blocklen) {
  448.                 memcpy(dst, src, blocklen);
  449.                 dst       += blocklen;
  450.                 cnt       -= blocklen;
  451.                 blocklen <<= 1;
  452.             }
  453.             memcpy(dst, src, cnt);
  454.             return;
  455.         }
  456.         if (cnt >= 8) {
  457.             AV_COPY32U(dst,     src);
  458.             AV_COPY32U(dst + 4, src + 4);
  459.             src += 8;
  460.             dst += 8;
  461.             cnt -= 8;
  462.         }
  463.         if (cnt >= 4) {
  464.             AV_COPY32U(dst, src);
  465.             src += 4;
  466.             dst += 4;
  467.             cnt -= 4;
  468.         }
  469.         if (cnt >= 2) {
  470.             AV_COPY16U(dst, src);
  471.             src += 2;
  472.             dst += 2;
  473.             cnt -= 2;
  474.         }
  475.         if (cnt)
  476.             *dst = *src;
  477.     }
  478. }
  479.  
  480. void *av_fast_realloc(void *ptr, unsigned int *size, size_t min_size)
  481. {
  482.     if (min_size < *size)
  483.         return ptr;
  484.  
  485.     min_size = FFMAX(min_size + min_size / 16 + 32, min_size);
  486.  
  487.     ptr = av_realloc(ptr, min_size);
  488.     /* we could set this to the unmodified min_size but this is safer
  489.      * if the user lost the ptr and uses NULL now
  490.      */
  491.     if (!ptr)
  492.         min_size = 0;
  493.  
  494.     *size = min_size;
  495.  
  496.     return ptr;
  497. }
  498.  
  499. void av_fast_malloc(void *ptr, unsigned int *size, size_t min_size)
  500. {
  501.     ff_fast_malloc(ptr, size, min_size, 0);
  502. }
  503.  
  504.