You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

511 lines
11KB

  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. * @file
  23. * default memory allocator for libavutil
  24. */
  25. #define _XOPEN_SOURCE 600
  26. #include "config.h"
  27. #include <limits.h>
  28. #include <stdint.h>
  29. #include <stdlib.h>
  30. #include <string.h>
  31. #if HAVE_MALLOC_H
  32. #include <malloc.h>
  33. #endif
  34. #include "avassert.h"
  35. #include "avutil.h"
  36. #include "common.h"
  37. #include "dynarray.h"
  38. #include "intreadwrite.h"
  39. #include "mem.h"
  40. #ifdef MALLOC_PREFIX
  41. #define malloc AV_JOIN(MALLOC_PREFIX, malloc)
  42. #define memalign AV_JOIN(MALLOC_PREFIX, memalign)
  43. #define posix_memalign AV_JOIN(MALLOC_PREFIX, posix_memalign)
  44. #define realloc AV_JOIN(MALLOC_PREFIX, realloc)
  45. #define free AV_JOIN(MALLOC_PREFIX, free)
  46. void *malloc(size_t size);
  47. void *memalign(size_t align, size_t size);
  48. int posix_memalign(void **ptr, size_t align, size_t size);
  49. void *realloc(void *ptr, size_t size);
  50. void free(void *ptr);
  51. #endif /* MALLOC_PREFIX */
  52. #include "mem_internal.h"
  53. #define ALIGN (HAVE_AVX512 ? 64 : (HAVE_AVX ? 32 : 16))
  54. /* NOTE: if you want to override these functions with your own
  55. * implementations (not recommended) you have to link libav* as
  56. * dynamic libraries and remove -Wl,-Bsymbolic from the linker flags.
  57. * Note that this will cost performance. */
  58. static size_t max_alloc_size= INT_MAX;
  59. void av_max_alloc(size_t max){
  60. max_alloc_size = max;
  61. }
  62. void *av_malloc(size_t size)
  63. {
  64. void *ptr = NULL;
  65. if (size > max_alloc_size)
  66. return NULL;
  67. #if HAVE_POSIX_MEMALIGN
  68. if (size) //OS X on SDK 10.6 has a broken posix_memalign implementation
  69. if (posix_memalign(&ptr, ALIGN, size))
  70. ptr = NULL;
  71. #elif HAVE_ALIGNED_MALLOC
  72. ptr = _aligned_malloc(size, ALIGN);
  73. #elif HAVE_MEMALIGN
  74. #ifndef __DJGPP__
  75. ptr = memalign(ALIGN, size);
  76. #else
  77. ptr = memalign(size, ALIGN);
  78. #endif
  79. /* Why 64?
  80. * Indeed, we should align it:
  81. * on 4 for 386
  82. * on 16 for 486
  83. * on 32 for 586, PPro - K6-III
  84. * on 64 for K7 (maybe for P3 too).
  85. * Because L1 and L2 caches are aligned on those values.
  86. * But I don't want to code such logic here!
  87. */
  88. /* Why 32?
  89. * For AVX ASM. SSE / NEON needs only 16.
  90. * Why not larger? Because I did not see a difference in benchmarks ...
  91. */
  92. /* benchmarks with P3
  93. * memalign(64) + 1 3071, 3051, 3032
  94. * memalign(64) + 2 3051, 3032, 3041
  95. * memalign(64) + 4 2911, 2896, 2915
  96. * memalign(64) + 8 2545, 2554, 2550
  97. * memalign(64) + 16 2543, 2572, 2563
  98. * memalign(64) + 32 2546, 2545, 2571
  99. * memalign(64) + 64 2570, 2533, 2558
  100. *
  101. * BTW, malloc seems to do 8-byte alignment by default here.
  102. */
  103. #else
  104. ptr = malloc(size);
  105. #endif
  106. if(!ptr && !size) {
  107. size = 1;
  108. ptr= av_malloc(1);
  109. }
  110. #if CONFIG_MEMORY_POISONING
  111. if (ptr)
  112. memset(ptr, FF_MEMORY_POISON, size);
  113. #endif
  114. return ptr;
  115. }
  116. void *av_realloc(void *ptr, size_t size)
  117. {
  118. if (size > max_alloc_size)
  119. return NULL;
  120. #if HAVE_ALIGNED_MALLOC
  121. return _aligned_realloc(ptr, size + !size, ALIGN);
  122. #else
  123. return realloc(ptr, size + !size);
  124. #endif
  125. }
  126. void *av_realloc_f(void *ptr, size_t nelem, size_t elsize)
  127. {
  128. size_t size;
  129. void *r;
  130. if (av_size_mult(elsize, nelem, &size)) {
  131. av_free(ptr);
  132. return NULL;
  133. }
  134. r = av_realloc(ptr, size);
  135. if (!r)
  136. av_free(ptr);
  137. return r;
  138. }
  139. int av_reallocp(void *ptr, size_t size)
  140. {
  141. void *val;
  142. if (!size) {
  143. av_freep(ptr);
  144. return 0;
  145. }
  146. memcpy(&val, ptr, sizeof(val));
  147. val = av_realloc(val, size);
  148. if (!val) {
  149. av_freep(ptr);
  150. return AVERROR(ENOMEM);
  151. }
  152. memcpy(ptr, &val, sizeof(val));
  153. return 0;
  154. }
  155. void *av_malloc_array(size_t nmemb, size_t size)
  156. {
  157. size_t result;
  158. if (av_size_mult(nmemb, size, &result) < 0)
  159. return NULL;
  160. return av_malloc(result);
  161. }
  162. void *av_mallocz_array(size_t nmemb, size_t size)
  163. {
  164. size_t result;
  165. if (av_size_mult(nmemb, size, &result) < 0)
  166. return NULL;
  167. return av_mallocz(result);
  168. }
  169. void *av_realloc_array(void *ptr, size_t nmemb, size_t size)
  170. {
  171. size_t result;
  172. if (av_size_mult(nmemb, size, &result) < 0)
  173. return NULL;
  174. return av_realloc(ptr, result);
  175. }
  176. int av_reallocp_array(void *ptr, size_t nmemb, size_t size)
  177. {
  178. void *val;
  179. memcpy(&val, ptr, sizeof(val));
  180. val = av_realloc_f(val, nmemb, size);
  181. memcpy(ptr, &val, sizeof(val));
  182. if (!val && nmemb && size)
  183. return AVERROR(ENOMEM);
  184. return 0;
  185. }
  186. void av_free(void *ptr)
  187. {
  188. #if HAVE_ALIGNED_MALLOC
  189. _aligned_free(ptr);
  190. #else
  191. free(ptr);
  192. #endif
  193. }
  194. void av_freep(void *arg)
  195. {
  196. void *val;
  197. memcpy(&val, arg, sizeof(val));
  198. memcpy(arg, &(void *){ NULL }, sizeof(val));
  199. av_free(val);
  200. }
  201. void *av_mallocz(size_t size)
  202. {
  203. void *ptr = av_malloc(size);
  204. if (ptr)
  205. memset(ptr, 0, size);
  206. return ptr;
  207. }
  208. void *av_calloc(size_t nmemb, size_t size)
  209. {
  210. size_t result;
  211. if (av_size_mult(nmemb, size, &result) < 0)
  212. return NULL;
  213. return av_mallocz(result);
  214. }
  215. char *av_strdup(const char *s)
  216. {
  217. char *ptr = NULL;
  218. if (s) {
  219. size_t len = strlen(s) + 1;
  220. ptr = av_realloc(NULL, len);
  221. if (ptr)
  222. memcpy(ptr, s, len);
  223. }
  224. return ptr;
  225. }
  226. char *av_strndup(const char *s, size_t len)
  227. {
  228. char *ret = NULL, *end;
  229. if (!s)
  230. return NULL;
  231. end = memchr(s, 0, len);
  232. if (end)
  233. len = end - s;
  234. ret = av_realloc(NULL, len + 1);
  235. if (!ret)
  236. return NULL;
  237. memcpy(ret, s, len);
  238. ret[len] = 0;
  239. return ret;
  240. }
  241. void *av_memdup(const void *p, size_t size)
  242. {
  243. void *ptr = NULL;
  244. if (p) {
  245. ptr = av_malloc(size);
  246. if (ptr)
  247. memcpy(ptr, p, size);
  248. }
  249. return ptr;
  250. }
  251. int av_dynarray_add_nofree(void *tab_ptr, int *nb_ptr, void *elem)
  252. {
  253. void **tab;
  254. memcpy(&tab, tab_ptr, sizeof(tab));
  255. FF_DYNARRAY_ADD(INT_MAX, sizeof(*tab), tab, *nb_ptr, {
  256. tab[*nb_ptr] = elem;
  257. memcpy(tab_ptr, &tab, sizeof(tab));
  258. }, {
  259. return AVERROR(ENOMEM);
  260. });
  261. return 0;
  262. }
  263. void av_dynarray_add(void *tab_ptr, int *nb_ptr, void *elem)
  264. {
  265. void **tab;
  266. memcpy(&tab, tab_ptr, sizeof(tab));
  267. FF_DYNARRAY_ADD(INT_MAX, sizeof(*tab), tab, *nb_ptr, {
  268. tab[*nb_ptr] = elem;
  269. memcpy(tab_ptr, &tab, sizeof(tab));
  270. }, {
  271. *nb_ptr = 0;
  272. av_freep(tab_ptr);
  273. });
  274. }
  275. void *av_dynarray2_add(void **tab_ptr, int *nb_ptr, size_t elem_size,
  276. const uint8_t *elem_data)
  277. {
  278. uint8_t *tab_elem_data = NULL;
  279. FF_DYNARRAY_ADD(INT_MAX, elem_size, *tab_ptr, *nb_ptr, {
  280. tab_elem_data = (uint8_t *)*tab_ptr + (*nb_ptr) * elem_size;
  281. if (elem_data)
  282. memcpy(tab_elem_data, elem_data, elem_size);
  283. else if (CONFIG_MEMORY_POISONING)
  284. memset(tab_elem_data, FF_MEMORY_POISON, elem_size);
  285. }, {
  286. av_freep(tab_ptr);
  287. *nb_ptr = 0;
  288. });
  289. return tab_elem_data;
  290. }
  291. static void fill16(uint8_t *dst, int len)
  292. {
  293. uint32_t v = AV_RN16(dst - 2);
  294. v |= v << 16;
  295. while (len >= 4) {
  296. AV_WN32(dst, v);
  297. dst += 4;
  298. len -= 4;
  299. }
  300. while (len--) {
  301. *dst = dst[-2];
  302. dst++;
  303. }
  304. }
  305. static void fill24(uint8_t *dst, int len)
  306. {
  307. #if HAVE_BIGENDIAN
  308. uint32_t v = AV_RB24(dst - 3);
  309. uint32_t a = v << 8 | v >> 16;
  310. uint32_t b = v << 16 | v >> 8;
  311. uint32_t c = v << 24 | v;
  312. #else
  313. uint32_t v = AV_RL24(dst - 3);
  314. uint32_t a = v | v << 24;
  315. uint32_t b = v >> 8 | v << 16;
  316. uint32_t c = v >> 16 | v << 8;
  317. #endif
  318. while (len >= 12) {
  319. AV_WN32(dst, a);
  320. AV_WN32(dst + 4, b);
  321. AV_WN32(dst + 8, c);
  322. dst += 12;
  323. len -= 12;
  324. }
  325. if (len >= 4) {
  326. AV_WN32(dst, a);
  327. dst += 4;
  328. len -= 4;
  329. }
  330. if (len >= 4) {
  331. AV_WN32(dst, b);
  332. dst += 4;
  333. len -= 4;
  334. }
  335. while (len--) {
  336. *dst = dst[-3];
  337. dst++;
  338. }
  339. }
  340. static void fill32(uint8_t *dst, int len)
  341. {
  342. uint32_t v = AV_RN32(dst - 4);
  343. #if HAVE_FAST_64BIT
  344. uint64_t v2= v + ((uint64_t)v<<32);
  345. while (len >= 32) {
  346. AV_WN64(dst , v2);
  347. AV_WN64(dst+ 8, v2);
  348. AV_WN64(dst+16, v2);
  349. AV_WN64(dst+24, v2);
  350. dst += 32;
  351. len -= 32;
  352. }
  353. #endif
  354. while (len >= 4) {
  355. AV_WN32(dst, v);
  356. dst += 4;
  357. len -= 4;
  358. }
  359. while (len--) {
  360. *dst = dst[-4];
  361. dst++;
  362. }
  363. }
  364. void av_memcpy_backptr(uint8_t *dst, int back, int cnt)
  365. {
  366. const uint8_t *src = &dst[-back];
  367. if (!back)
  368. return;
  369. if (back == 1) {
  370. memset(dst, *src, cnt);
  371. } else if (back == 2) {
  372. fill16(dst, cnt);
  373. } else if (back == 3) {
  374. fill24(dst, cnt);
  375. } else if (back == 4) {
  376. fill32(dst, cnt);
  377. } else {
  378. if (cnt >= 16) {
  379. int blocklen = back;
  380. while (cnt > blocklen) {
  381. memcpy(dst, src, blocklen);
  382. dst += blocklen;
  383. cnt -= blocklen;
  384. blocklen <<= 1;
  385. }
  386. memcpy(dst, src, cnt);
  387. return;
  388. }
  389. if (cnt >= 8) {
  390. AV_COPY32U(dst, src);
  391. AV_COPY32U(dst + 4, src + 4);
  392. src += 8;
  393. dst += 8;
  394. cnt -= 8;
  395. }
  396. if (cnt >= 4) {
  397. AV_COPY32U(dst, src);
  398. src += 4;
  399. dst += 4;
  400. cnt -= 4;
  401. }
  402. if (cnt >= 2) {
  403. AV_COPY16U(dst, src);
  404. src += 2;
  405. dst += 2;
  406. cnt -= 2;
  407. }
  408. if (cnt)
  409. *dst = *src;
  410. }
  411. }
  412. void *av_fast_realloc(void *ptr, unsigned int *size, size_t min_size)
  413. {
  414. if (min_size <= *size)
  415. return ptr;
  416. if (min_size > max_alloc_size) {
  417. *size = 0;
  418. return NULL;
  419. }
  420. min_size = FFMIN(max_alloc_size, FFMAX(min_size + min_size / 16 + 32, min_size));
  421. ptr = av_realloc(ptr, min_size);
  422. /* we could set this to the unmodified min_size but this is safer
  423. * if the user lost the ptr and uses NULL now
  424. */
  425. if (!ptr)
  426. min_size = 0;
  427. *size = min_size;
  428. return ptr;
  429. }
  430. void av_fast_malloc(void *ptr, unsigned int *size, size_t min_size)
  431. {
  432. ff_fast_malloc(ptr, size, min_size, 0);
  433. }
  434. void av_fast_mallocz(void *ptr, unsigned int *size, size_t min_size)
  435. {
  436. ff_fast_malloc(ptr, size, min_size, 1);
  437. }