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
32 #include <stdint.h>
33 #include <stdlib.h>
34 #include <stdatomic.h>
35 #include <string.h>
36 #if HAVE_MALLOC_H
37 #include <malloc.h>
38 #endif
39
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
63
64 #define ALIGN (HAVE_AVX512 ? 64 : (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
72
75 }
76
78 {
79 size_t t;
80
81 #if (!defined(__INTEL_COMPILER) && AV_GCC_VERSION_AT_LEAST(5,1)) || AV_HAS_BUILTIN(__builtin_mul_overflow)
82 if (__builtin_mul_overflow(
a,
b, &t))
84 #else
86 /* Hack inspired from glibc: don't try the division if nelem and elsize
87 * are both less than sqrt(SIZE_MAX). */
88 if ((
a |
b) >= ((
size_t)1 << (
sizeof(
size_t) * 4)) &&
a && t /
a !=
b)
90 #endif
92 return 0;
93 }
94
96 {
98
101
102 #if HAVE_POSIX_MEMALIGN
103 if (
size)
//OS X on SDK 10.6 has a broken posix_memalign implementation
106 #elif HAVE_ALIGNED_MALLOC
108 #elif HAVE_MEMALIGN
109 #ifndef __DJGPP__
111 #else
113 #endif
114 /* Why 64?
115 * Indeed, we should align it:
116 * on 4 for 386
117 * on 16 for 486
118 * on 32 for 586, PPro - K6-III
119 * on 64 for K7 (maybe for P3 too).
120 * Because L1 and L2 caches are aligned on those values.
121 * But I don't want to code such logic here!
122 */
123 /* Why 32?
124 * For AVX ASM. SSE / NEON needs only 16.
125 * Why not larger? Because I did not see a difference in benchmarks ...
126 */
127 /* benchmarks with P3
128 * memalign(64) + 1 3071, 3051, 3032
129 * memalign(64) + 2 3051, 3032, 3041
130 * memalign(64) + 4 2911, 2896, 2915
131 * memalign(64) + 8 2545, 2554, 2550
132 * memalign(64) + 16 2543, 2572, 2563
133 * memalign(64) + 32 2546, 2545, 2571
134 * memalign(64) + 64 2570, 2533, 2558
135 *
136 * BTW, malloc seems to do 8-byte alignment by default here.
137 */
138 #else
140 #endif
144 }
145 #if CONFIG_MEMORY_POISONING
146 if (ptr)
148 #endif
149 return ptr;
150 }
151
153 {
157
158 #if HAVE_ALIGNED_MALLOC
160 #else
162 #endif
163 #if CONFIG_MEMORY_POISONING
166 #endif
168 }
169
171 {
174
178 }
183 }
184
186 {
188
191 return 0;
192 }
193
194 memcpy(&
val, ptr,
sizeof(
val));
196
200 }
201
202 memcpy(ptr, &
val,
sizeof(
val));
203 return 0;
204 }
205
207 {
212 }
213
214 #if FF_API_AV_MALLOCZ_ARRAY
216 {
221 }
222 #endif
223
225 {
230 }
231
233 {
235
236 memcpy(&
val, ptr,
sizeof(
val));
238 memcpy(ptr, &
val,
sizeof(
val));
241
242 return 0;
243 }
244
246 {
247 #if HAVE_ALIGNED_MALLOC
248 _aligned_free(ptr);
249 #else
250 free(ptr);
251 #endif
252 }
253
255 {
257
261 }
262
264 {
266 if (ptr)
267 memset(ptr, 0,
size);
268 return ptr;
269 }
270
272 {
277 }
278
280 {
283 size_t len = strlen(
s) + 1;
285 if (ptr)
287 }
288 return ptr;
289 }
290
292 {
294
297
298 end = memchr(
s, 0,
len);
299 if (end)
301
305
309 }
310
312 {
314 if (p) {
316 if (ptr)
317 memcpy(ptr, p,
size);
318 }
319 return ptr;
320 }
321
323 {
325 memcpy(&
tab, tab_ptr,
sizeof(
tab));
326
329 memcpy(tab_ptr, &
tab,
sizeof(
tab));
330 }, {
332 });
333 return 0;
334 }
335
337 {
339 memcpy(&
tab, tab_ptr,
sizeof(
tab));
340
343 memcpy(tab_ptr, &
tab,
sizeof(
tab));
344 }, {
345 *nb_ptr = 0;
347 });
348 }
349
351 const uint8_t *elem_data)
352 {
353 uint8_t *tab_elem_data =
NULL;
354
356 tab_elem_data = (uint8_t *)*tab_ptr + (*nb_ptr) * elem_size;
357 if (elem_data)
358 memcpy(tab_elem_data, elem_data, elem_size);
359 else if (CONFIG_MEMORY_POISONING)
361 }, {
363 *nb_ptr = 0;
364 });
365 return tab_elem_data;
366 }
367
369 {
371
372 v |= v << 16;
373
376 dst += 4;
378 }
379
381 *dst = dst[-2];
382 dst++;
383 }
384 }
385
387 {
388 #if HAVE_BIGENDIAN
390 uint32_t
a = v << 8 | v >> 16;
391 uint32_t
b = v << 16 | v >> 8;
392 uint32_t
c = v << 24 | v;
393 #else
395 uint32_t
a = v | v << 24;
396 uint32_t
b = v >> 8 | v << 16;
397 uint32_t
c = v >> 16 | v << 8;
398 #endif
399
404 dst += 12;
406 }
407
410 dst += 4;
412 }
413
416 dst += 4;
418 }
419
421 *dst = dst[-3];
422 dst++;
423 }
424 }
425
427 {
429
430 #if HAVE_FAST_64BIT
431 uint64_t v2= v + ((uint64_t)v<<32);
437 dst += 32;
439 }
440 #endif
441
444 dst += 4;
446 }
447
449 *dst = dst[-4];
450 dst++;
451 }
452 }
453
455 {
456 const uint8_t *
src = &dst[-back];
457 if (!back)
458 return;
459
460 if (back == 1) {
461 memset(dst, *
src, cnt);
462 } else if (back == 2) {
464 } else if (back == 3) {
466 } else if (back == 4) {
468 } else {
469 if (cnt >= 16) {
470 int blocklen = back;
471 while (cnt > blocklen) {
472 memcpy(dst,
src, blocklen);
473 dst += blocklen;
474 cnt -= blocklen;
475 blocklen <<= 1;
476 }
477 memcpy(dst,
src, cnt);
478 return;
479 }
480 if (cnt >= 8) {
484 dst += 8;
485 cnt -= 8;
486 }
487 if (cnt >= 4) {
490 dst += 4;
491 cnt -= 4;
492 }
493 if (cnt >= 2) {
496 dst += 2;
497 cnt -= 2;
498 }
499 if (cnt)
501 }
502 }
503
505 {
506 size_t max_size;
507
508 if (min_size <= *
size)
509 return ptr;
510
512
513 if (min_size > max_size) {
516 }
517
518 min_size =
FFMIN(max_size,
FFMAX(min_size + min_size / 16 + 32, min_size));
519
521 /* we could set this to the unmodified min_size but this is safer
522 * if the user lost the ptr and uses NULL now
523 */
524 if (!ptr)
525 min_size = 0;
526
528
529 return ptr;
530 }
531
532 static inline void fast_malloc(
void *ptr,
unsigned int *
size,
size_t min_size,
int zero_realloc)
533 {
534 size_t max_size;
536
537 memcpy(&
val, ptr,
sizeof(
val));
538 if (min_size <= *
size) {
540 return;
541 }
542
544
545 if (min_size > max_size) {
548 return;
549 }
550 min_size =
FFMIN(max_size,
FFMAX(min_size + min_size / 16 + 32, min_size));
553 memcpy(ptr, &
val,
sizeof(
val));
555 min_size = 0;
557 return;
558 }
559
561 {
563 }
564
566 {
568 }
569
571 {
573 }