Line | Branch | Exec | Source |
---|---|---|---|
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 <stdatomic.h> | ||
35 | #include <string.h> | ||
36 | #if HAVE_MALLOC_H | ||
37 | #include <malloc.h> | ||
38 | #endif | ||
39 | |||
40 | #include "attributes.h" | ||
41 | #include "avassert.h" | ||
42 | #include "dynarray.h" | ||
43 | #include "error.h" | ||
44 | #include "internal.h" | ||
45 | #include "intreadwrite.h" | ||
46 | #include "macros.h" | ||
47 | #include "mem.h" | ||
48 | |||
49 | #ifdef MALLOC_PREFIX | ||
50 | |||
51 | #define malloc AV_JOIN(MALLOC_PREFIX, malloc) | ||
52 | #define memalign AV_JOIN(MALLOC_PREFIX, memalign) | ||
53 | #define posix_memalign AV_JOIN(MALLOC_PREFIX, posix_memalign) | ||
54 | #define realloc AV_JOIN(MALLOC_PREFIX, realloc) | ||
55 | #define free AV_JOIN(MALLOC_PREFIX, free) | ||
56 | |||
57 | void *malloc(size_t size); | ||
58 | void *memalign(size_t align, size_t size); | ||
59 | int posix_memalign(void **ptr, size_t align, size_t size); | ||
60 | void *realloc(void *ptr, size_t size); | ||
61 | void free(void *ptr); | ||
62 | |||
63 | #endif /* MALLOC_PREFIX */ | ||
64 | |||
65 | #define ALIGN (HAVE_SIMD_ALIGN_64 ? 64 : (HAVE_SIMD_ALIGN_32 ? 32 : 16)) | ||
66 | |||
67 | #define FF_MEMORY_POISON 0x2a | ||
68 | |||
69 | /* NOTE: if you want to override these functions with your own | ||
70 | * implementations (not recommended) you have to link libav* as | ||
71 | * dynamic libraries and remove -Wl,-Bsymbolic from the linker flags. | ||
72 | * Note that this will cost performance. */ | ||
73 | |||
74 | static atomic_size_t max_alloc_size = INT_MAX; | ||
75 | |||
76 | ✗ | void av_max_alloc(size_t max){ | |
77 | ✗ | atomic_store_explicit(&max_alloc_size, max, memory_order_relaxed); | |
78 | ✗ | } | |
79 | |||
80 | 8871674 | static int size_mult(size_t a, size_t b, size_t *r) | |
81 | { | ||
82 | size_t t; | ||
83 | |||
84 | #if (!defined(__INTEL_COMPILER) && AV_GCC_VERSION_AT_LEAST(5,1)) || AV_HAS_BUILTIN(__builtin_mul_overflow) | ||
85 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 8871674 times.
|
8871674 | if (__builtin_mul_overflow(a, b, &t)) |
86 | ✗ | return AVERROR(EINVAL); | |
87 | #else | ||
88 | t = a * b; | ||
89 | /* Hack inspired from glibc: don't try the division if nelem and elsize | ||
90 | * are both less than sqrt(SIZE_MAX). */ | ||
91 | if ((a | b) >= ((size_t)1 << (sizeof(size_t) * 4)) && a && t / a != b) | ||
92 | return AVERROR(EINVAL); | ||
93 | #endif | ||
94 | 8871674 | *r = t; | |
95 | 8871674 | return 0; | |
96 | } | ||
97 | |||
98 | 25943783 | void *av_malloc(size_t size) | |
99 | { | ||
100 | 25943783 | void *ptr = NULL; | |
101 | |||
102 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 25943783 times.
|
25943783 | if (size > atomic_load_explicit(&max_alloc_size, memory_order_relaxed)) |
103 | ✗ | return NULL; | |
104 | |||
105 | #if HAVE_POSIX_MEMALIGN | ||
106 |
2/2✓ Branch 0 taken 25925172 times.
✓ Branch 1 taken 18611 times.
|
25943783 | if (size) //OS X on SDK 10.6 has a broken posix_memalign implementation |
107 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 25925172 times.
|
25925172 | if (posix_memalign(&ptr, ALIGN, size)) |
108 | ✗ | ptr = NULL; | |
109 | #elif HAVE_ALIGNED_MALLOC | ||
110 | ptr = _aligned_malloc(size, ALIGN); | ||
111 | #elif HAVE_MEMALIGN | ||
112 | #ifndef __DJGPP__ | ||
113 | ptr = memalign(ALIGN, size); | ||
114 | #else | ||
115 | ptr = memalign(size, ALIGN); | ||
116 | #endif | ||
117 | /* Why 64? | ||
118 | * Indeed, we should align it: | ||
119 | * on 4 for 386 | ||
120 | * on 16 for 486 | ||
121 | * on 32 for 586, PPro - K6-III | ||
122 | * on 64 for K7 (maybe for P3 too). | ||
123 | * Because L1 and L2 caches are aligned on those values. | ||
124 | * But I don't want to code such logic here! | ||
125 | */ | ||
126 | /* Why 32? | ||
127 | * For AVX ASM. SSE / NEON needs only 16. | ||
128 | * Why not larger? Because I did not see a difference in benchmarks ... | ||
129 | */ | ||
130 | /* benchmarks with P3 | ||
131 | * memalign(64) + 1 3071, 3051, 3032 | ||
132 | * memalign(64) + 2 3051, 3032, 3041 | ||
133 | * memalign(64) + 4 2911, 2896, 2915 | ||
134 | * memalign(64) + 8 2545, 2554, 2550 | ||
135 | * memalign(64) + 16 2543, 2572, 2563 | ||
136 | * memalign(64) + 32 2546, 2545, 2571 | ||
137 | * memalign(64) + 64 2570, 2533, 2558 | ||
138 | * | ||
139 | * BTW, malloc seems to do 8-byte alignment by default here. | ||
140 | */ | ||
141 | #else | ||
142 | ptr = malloc(size); | ||
143 | #endif | ||
144 |
3/4✓ Branch 0 taken 18611 times.
✓ Branch 1 taken 25925172 times.
✓ Branch 2 taken 18611 times.
✗ Branch 3 not taken.
|
25943783 | if(!ptr && !size) { |
145 | 18611 | size = 1; | |
146 | 18611 | ptr= av_malloc(1); | |
147 | } | ||
148 | #if CONFIG_MEMORY_POISONING | ||
149 |
1/2✓ Branch 0 taken 25943783 times.
✗ Branch 1 not taken.
|
25943783 | if (ptr) |
150 | 25943783 | memset(ptr, FF_MEMORY_POISON, size); | |
151 | #endif | ||
152 | 25943783 | return ptr; | |
153 | } | ||
154 | |||
155 | 11553306 | void *av_realloc(void *ptr, size_t size) | |
156 | { | ||
157 | void *ret; | ||
158 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 11553306 times.
|
11553306 | if (size > atomic_load_explicit(&max_alloc_size, memory_order_relaxed)) |
159 | ✗ | return NULL; | |
160 | |||
161 | #if HAVE_ALIGNED_MALLOC | ||
162 | ret = _aligned_realloc(ptr, size + !size, ALIGN); | ||
163 | #else | ||
164 | 11553306 | ret = realloc(ptr, size + !size); | |
165 | #endif | ||
166 | #if CONFIG_MEMORY_POISONING | ||
167 |
3/4✓ Branch 0 taken 11553306 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6398174 times.
✓ Branch 3 taken 5155132 times.
|
11553306 | if (ret && !ptr) |
168 | 6398174 | memset(ret, FF_MEMORY_POISON, size); | |
169 | #endif | ||
170 | 11553306 | return ret; | |
171 | } | ||
172 | |||
173 | 63635 | void *av_realloc_f(void *ptr, size_t nelem, size_t elsize) | |
174 | { | ||
175 | size_t size; | ||
176 | void *r; | ||
177 | |||
178 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 63635 times.
|
63635 | if (size_mult(elsize, nelem, &size)) { |
179 | ✗ | av_free(ptr); | |
180 | ✗ | return NULL; | |
181 | } | ||
182 | 63635 | r = av_realloc(ptr, size); | |
183 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 63635 times.
|
63635 | if (!r) |
184 | ✗ | av_free(ptr); | |
185 | 63635 | return r; | |
186 | } | ||
187 | |||
188 | 20407 | int av_reallocp(void *ptr, size_t size) | |
189 | { | ||
190 | void *val; | ||
191 | |||
192 |
2/2✓ Branch 0 taken 9 times.
✓ Branch 1 taken 20398 times.
|
20407 | if (!size) { |
193 | 9 | av_freep(ptr); | |
194 | 9 | return 0; | |
195 | } | ||
196 | |||
197 | 20398 | memcpy(&val, ptr, sizeof(val)); | |
198 | 20398 | val = av_realloc(val, size); | |
199 | |||
200 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 20398 times.
|
20398 | if (!val) { |
201 | ✗ | av_freep(ptr); | |
202 | ✗ | return AVERROR(ENOMEM); | |
203 | } | ||
204 | |||
205 | 20398 | memcpy(ptr, &val, sizeof(val)); | |
206 | 20398 | return 0; | |
207 | } | ||
208 | |||
209 | 359193 | void *av_malloc_array(size_t nmemb, size_t size) | |
210 | { | ||
211 | size_t result; | ||
212 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 359193 times.
|
359193 | if (size_mult(nmemb, size, &result) < 0) |
213 | ✗ | return NULL; | |
214 | 359193 | return av_malloc(result); | |
215 | } | ||
216 | |||
217 | 5665557 | void *av_realloc_array(void *ptr, size_t nmemb, size_t size) | |
218 | { | ||
219 | size_t result; | ||
220 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 5665557 times.
|
5665557 | if (size_mult(nmemb, size, &result) < 0) |
221 | ✗ | return NULL; | |
222 | 5665557 | return av_realloc(ptr, result); | |
223 | } | ||
224 | |||
225 | 5904 | int av_reallocp_array(void *ptr, size_t nmemb, size_t size) | |
226 | { | ||
227 | void *val; | ||
228 | |||
229 | 5904 | memcpy(&val, ptr, sizeof(val)); | |
230 | 5904 | val = av_realloc_f(val, nmemb, size); | |
231 | 5904 | memcpy(ptr, &val, sizeof(val)); | |
232 |
1/6✗ Branch 0 not taken.
✓ Branch 1 taken 5904 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
5904 | if (!val && nmemb && size) |
233 | ✗ | return AVERROR(ENOMEM); | |
234 | |||
235 | 5904 | return 0; | |
236 | } | ||
237 | |||
238 | 73577439 | void av_free(void *ptr) | |
239 | { | ||
240 | #if HAVE_ALIGNED_MALLOC | ||
241 | _aligned_free(ptr); | ||
242 | #else | ||
243 | 73577439 | free(ptr); | |
244 | #endif | ||
245 | 73577439 | } | |
246 | |||
247 | 63038544 | void av_freep(void *arg) | |
248 | { | ||
249 | void *val; | ||
250 | |||
251 | 63038544 | memcpy(&val, arg, sizeof(val)); | |
252 | 63038544 | memcpy(arg, &(void *){ NULL }, sizeof(val)); | |
253 | 63038544 | av_free(val); | |
254 | 63038544 | } | |
255 | |||
256 | 21309713 | void *av_mallocz(size_t size) | |
257 | { | ||
258 | 21309713 | void *ptr = av_malloc(size); | |
259 |
1/2✓ Branch 0 taken 21309713 times.
✗ Branch 1 not taken.
|
21309713 | if (ptr) |
260 | 21309713 | memset(ptr, 0, size); | |
261 | 21309713 | return ptr; | |
262 | } | ||
263 | |||
264 | 2782649 | void *av_calloc(size_t nmemb, size_t size) | |
265 | { | ||
266 | size_t result; | ||
267 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 2782649 times.
|
2782649 | if (size_mult(nmemb, size, &result) < 0) |
268 | ✗ | return NULL; | |
269 | 2782649 | return av_mallocz(result); | |
270 | } | ||
271 | |||
272 | 2149448 | char *av_strdup(const char *s) | |
273 | { | ||
274 | 2149448 | char *ptr = NULL; | |
275 |
2/2✓ Branch 0 taken 2149447 times.
✓ Branch 1 taken 1 times.
|
2149448 | if (s) { |
276 | 2149447 | size_t len = strlen(s) + 1; | |
277 | 2149447 | ptr = av_realloc(NULL, len); | |
278 |
1/2✓ Branch 0 taken 2149447 times.
✗ Branch 1 not taken.
|
2149447 | if (ptr) |
279 | 2149447 | memcpy(ptr, s, len); | |
280 | } | ||
281 | 2149448 | return ptr; | |
282 | } | ||
283 | |||
284 | 1 | char *av_strndup(const char *s, size_t len) | |
285 | { | ||
286 | 1 | char *ret = NULL, *end; | |
287 | |||
288 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (!s) |
289 | ✗ | return NULL; | |
290 | |||
291 | 1 | end = memchr(s, 0, len); | |
292 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (end) |
293 | ✗ | len = end - s; | |
294 | |||
295 | 1 | ret = av_realloc(NULL, len + 1); | |
296 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (!ret) |
297 | ✗ | return NULL; | |
298 | |||
299 | 1 | memcpy(ret, s, len); | |
300 | 1 | ret[len] = 0; | |
301 | 1 | return ret; | |
302 | } | ||
303 | |||
304 | 126142 | void *av_memdup(const void *p, size_t size) | |
305 | { | ||
306 | 126142 | void *ptr = NULL; | |
307 |
1/2✓ Branch 0 taken 126142 times.
✗ Branch 1 not taken.
|
126142 | if (p) { |
308 | 126142 | ptr = av_malloc(size); | |
309 |
1/2✓ Branch 0 taken 126142 times.
✗ Branch 1 not taken.
|
126142 | if (ptr) |
310 | 126142 | memcpy(ptr, p, size); | |
311 | } | ||
312 | 126142 | return ptr; | |
313 | } | ||
314 | |||
315 | 100172 | int av_dynarray_add_nofree(void *tab_ptr, int *nb_ptr, void *elem) | |
316 | { | ||
317 | void **tab; | ||
318 | 100172 | memcpy(&tab, tab_ptr, sizeof(tab)); | |
319 | |||
320 |
7/10✓ Branch 0 taken 96057 times.
✓ Branch 1 taken 4115 times.
✓ Branch 2 taken 17575 times.
✓ Branch 3 taken 78482 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 96057 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 96057 times.
✓ Branch 9 taken 100172 times.
✗ Branch 10 not taken.
|
100172 | FF_DYNARRAY_ADD(INT_MAX, sizeof(*tab), tab, *nb_ptr, { |
321 | tab[*nb_ptr] = elem; | ||
322 | memcpy(tab_ptr, &tab, sizeof(tab)); | ||
323 | }, { | ||
324 | return AVERROR(ENOMEM); | ||
325 | }); | ||
326 | 100172 | return 0; | |
327 | } | ||
328 | |||
329 | 1223 | void av_dynarray_add(void *tab_ptr, int *nb_ptr, void *elem) | |
330 | { | ||
331 | void **tab; | ||
332 | 1223 | memcpy(&tab, tab_ptr, sizeof(tab)); | |
333 | |||
334 |
7/10✓ Branch 0 taken 227 times.
✓ Branch 1 taken 996 times.
✓ Branch 2 taken 146 times.
✓ Branch 3 taken 81 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 227 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 227 times.
✓ Branch 9 taken 1223 times.
✗ Branch 10 not taken.
|
1223 | FF_DYNARRAY_ADD(INT_MAX, sizeof(*tab), tab, *nb_ptr, { |
335 | tab[*nb_ptr] = elem; | ||
336 | memcpy(tab_ptr, &tab, sizeof(tab)); | ||
337 | }, { | ||
338 | *nb_ptr = 0; | ||
339 | av_freep(tab_ptr); | ||
340 | }); | ||
341 | 1223 | } | |
342 | |||
343 | 531972 | void *av_dynarray2_add(void **tab_ptr, int *nb_ptr, size_t elem_size, | |
344 | const uint8_t *elem_data) | ||
345 | { | ||
346 | 531972 | uint8_t *tab_elem_data = NULL; | |
347 | |||
348 |
9/12✓ Branch 0 taken 321322 times.
✓ Branch 1 taken 210650 times.
✓ Branch 2 taken 187516 times.
✓ Branch 3 taken 133806 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 321322 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 321322 times.
✓ Branch 9 taken 531972 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 191 times.
✓ Branch 12 taken 531781 times.
|
531972 | FF_DYNARRAY_ADD(INT_MAX, elem_size, *tab_ptr, *nb_ptr, { |
349 | tab_elem_data = (uint8_t *)*tab_ptr + (*nb_ptr) * elem_size; | ||
350 | if (elem_data) | ||
351 | memcpy(tab_elem_data, elem_data, elem_size); | ||
352 | else if (CONFIG_MEMORY_POISONING) | ||
353 | memset(tab_elem_data, FF_MEMORY_POISON, elem_size); | ||
354 | }, { | ||
355 | av_freep(tab_ptr); | ||
356 | *nb_ptr = 0; | ||
357 | }); | ||
358 | 531972 | return tab_elem_data; | |
359 | } | ||
360 | |||
361 | 141628 | static void fill16(uint8_t *dst, int len) | |
362 | { | ||
363 | 141628 | uint32_t v = AV_RN16(dst - 2); | |
364 | |||
365 | 141628 | v |= v << 16; | |
366 | |||
367 |
2/2✓ Branch 0 taken 81792938 times.
✓ Branch 1 taken 141628 times.
|
81934566 | while (len >= 4) { |
368 | 81792938 | AV_WN32(dst, v); | |
369 | 81792938 | dst += 4; | |
370 | 81792938 | len -= 4; | |
371 | } | ||
372 | |||
373 |
2/2✓ Branch 0 taken 271085 times.
✓ Branch 1 taken 141628 times.
|
412713 | while (len--) { |
374 | 271085 | *dst = dst[-2]; | |
375 | 271085 | dst++; | |
376 | } | ||
377 | 141628 | } | |
378 | |||
379 | 738 | static void fill24(uint8_t *dst, int len) | |
380 | { | ||
381 | #if HAVE_BIGENDIAN | ||
382 | uint32_t v = AV_RB24(dst - 3); | ||
383 | uint32_t a = v << 8 | v >> 16; | ||
384 | uint32_t b = v << 16 | v >> 8; | ||
385 | uint32_t c = v << 24 | v; | ||
386 | #else | ||
387 | 738 | uint32_t v = AV_RL24(dst - 3); | |
388 | 738 | uint32_t a = v | v << 24; | |
389 | 738 | uint32_t b = v >> 8 | v << 16; | |
390 | 738 | uint32_t c = v >> 16 | v << 8; | |
391 | #endif | ||
392 | |||
393 |
2/2✓ Branch 0 taken 2508 times.
✓ Branch 1 taken 738 times.
|
3246 | while (len >= 12) { |
394 | 2508 | AV_WN32(dst, a); | |
395 | 2508 | AV_WN32(dst + 4, b); | |
396 | 2508 | AV_WN32(dst + 8, c); | |
397 | 2508 | dst += 12; | |
398 | 2508 | len -= 12; | |
399 | } | ||
400 | |||
401 |
2/2✓ Branch 0 taken 283 times.
✓ Branch 1 taken 455 times.
|
738 | if (len >= 4) { |
402 | 283 | AV_WN32(dst, a); | |
403 | 283 | dst += 4; | |
404 | 283 | len -= 4; | |
405 | } | ||
406 | |||
407 |
2/2✓ Branch 0 taken 157 times.
✓ Branch 1 taken 581 times.
|
738 | if (len >= 4) { |
408 | 157 | AV_WN32(dst, b); | |
409 | 157 | dst += 4; | |
410 | 157 | len -= 4; | |
411 | } | ||
412 | |||
413 |
2/2✓ Branch 0 taken 1580 times.
✓ Branch 1 taken 738 times.
|
2318 | while (len--) { |
414 | 1580 | *dst = dst[-3]; | |
415 | 1580 | dst++; | |
416 | } | ||
417 | 738 | } | |
418 | |||
419 | 14992 | static void fill32(uint8_t *dst, int len) | |
420 | { | ||
421 | 14992 | uint32_t v = AV_RN32(dst - 4); | |
422 | |||
423 | #if HAVE_FAST_64BIT | ||
424 | 14992 | uint64_t v2= v + ((uint64_t)v<<32); | |
425 |
2/2✓ Branch 0 taken 101874 times.
✓ Branch 1 taken 14992 times.
|
116866 | while (len >= 32) { |
426 | 101874 | AV_WN64(dst , v2); | |
427 | 101874 | AV_WN64(dst+ 8, v2); | |
428 | 101874 | AV_WN64(dst+16, v2); | |
429 | 101874 | AV_WN64(dst+24, v2); | |
430 | 101874 | dst += 32; | |
431 | 101874 | len -= 32; | |
432 | } | ||
433 | #endif | ||
434 | |||
435 |
2/2✓ Branch 0 taken 57541 times.
✓ Branch 1 taken 14992 times.
|
72533 | while (len >= 4) { |
436 | 57541 | AV_WN32(dst, v); | |
437 | 57541 | dst += 4; | |
438 | 57541 | len -= 4; | |
439 | } | ||
440 | |||
441 |
2/2✓ Branch 0 taken 2266 times.
✓ Branch 1 taken 14992 times.
|
17258 | while (len--) { |
442 | 2266 | *dst = dst[-4]; | |
443 | 2266 | dst++; | |
444 | } | ||
445 | 14992 | } | |
446 | |||
447 | 801947 | void av_memcpy_backptr(uint8_t *dst, int back, int cnt) | |
448 | { | ||
449 | 801947 | const uint8_t *src = &dst[-back]; | |
450 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 801947 times.
|
801947 | if (!back) |
451 | ✗ | return; | |
452 | |||
453 |
2/2✓ Branch 0 taken 5265 times.
✓ Branch 1 taken 796682 times.
|
801947 | if (back == 1) { |
454 | 5265 | memset(dst, *src, cnt); | |
455 |
2/2✓ Branch 0 taken 141628 times.
✓ Branch 1 taken 655054 times.
|
796682 | } else if (back == 2) { |
456 | 141628 | fill16(dst, cnt); | |
457 |
2/2✓ Branch 0 taken 738 times.
✓ Branch 1 taken 654316 times.
|
655054 | } else if (back == 3) { |
458 | 738 | fill24(dst, cnt); | |
459 |
2/2✓ Branch 0 taken 14992 times.
✓ Branch 1 taken 639324 times.
|
654316 | } else if (back == 4) { |
460 | 14992 | fill32(dst, cnt); | |
461 | } else { | ||
462 |
2/2✓ Branch 0 taken 104546 times.
✓ Branch 1 taken 534778 times.
|
639324 | if (cnt >= 16) { |
463 | 104546 | int blocklen = back; | |
464 |
2/2✓ Branch 0 taken 35976 times.
✓ Branch 1 taken 104546 times.
|
140522 | while (cnt > blocklen) { |
465 | 35976 | memcpy(dst, src, blocklen); | |
466 | 35976 | dst += blocklen; | |
467 | 35976 | cnt -= blocklen; | |
468 | 35976 | blocklen <<= 1; | |
469 | } | ||
470 | 104546 | memcpy(dst, src, cnt); | |
471 | 104546 | return; | |
472 | } | ||
473 |
2/2✓ Branch 0 taken 116277 times.
✓ Branch 1 taken 418501 times.
|
534778 | if (cnt >= 8) { |
474 | 116277 | AV_COPY32U(dst, src); | |
475 | 116277 | AV_COPY32U(dst + 4, src + 4); | |
476 | 116277 | src += 8; | |
477 | 116277 | dst += 8; | |
478 | 116277 | cnt -= 8; | |
479 | } | ||
480 |
2/2✓ Branch 0 taken 383459 times.
✓ Branch 1 taken 151319 times.
|
534778 | if (cnt >= 4) { |
481 | 383459 | AV_COPY32U(dst, src); | |
482 | 383459 | src += 4; | |
483 | 383459 | dst += 4; | |
484 | 383459 | cnt -= 4; | |
485 | } | ||
486 |
2/2✓ Branch 0 taken 192819 times.
✓ Branch 1 taken 341959 times.
|
534778 | if (cnt >= 2) { |
487 | 192819 | AV_COPY16U(dst, src); | |
488 | 192819 | src += 2; | |
489 | 192819 | dst += 2; | |
490 | 192819 | cnt -= 2; | |
491 | } | ||
492 |
2/2✓ Branch 0 taken 118885 times.
✓ Branch 1 taken 415893 times.
|
534778 | if (cnt) |
493 | 118885 | *dst = *src; | |
494 | } | ||
495 | } | ||
496 | |||
497 | 2032492 | void *av_fast_realloc(void *ptr, unsigned int *size, size_t min_size) | |
498 | { | ||
499 | size_t max_size; | ||
500 | |||
501 |
2/2✓ Branch 0 taken 1919960 times.
✓ Branch 1 taken 112532 times.
|
2032492 | if (min_size <= *size) |
502 | 1919960 | return ptr; | |
503 | |||
504 | 112532 | max_size = atomic_load_explicit(&max_alloc_size, memory_order_relaxed); | |
505 | /* *size is an unsigned, so the real maximum is <= UINT_MAX. */ | ||
506 | 112532 | max_size = FFMIN(max_size, UINT_MAX); | |
507 | |||
508 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 112532 times.
|
112532 | if (min_size > max_size) { |
509 | ✗ | *size = 0; | |
510 | ✗ | return NULL; | |
511 | } | ||
512 | |||
513 | 112532 | min_size = FFMIN(max_size, FFMAX(min_size + min_size / 16 + 32, min_size)); | |
514 | |||
515 | 112532 | ptr = av_realloc(ptr, min_size); | |
516 | /* we could set this to the unmodified min_size but this is safer | ||
517 | * if the user lost the ptr and uses NULL now | ||
518 | */ | ||
519 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 112532 times.
|
112532 | if (!ptr) |
520 | ✗ | min_size = 0; | |
521 | |||
522 | 112532 | *size = min_size; | |
523 | |||
524 | 112532 | return ptr; | |
525 | } | ||
526 | |||
527 | 370003 | static inline void fast_malloc(void *ptr, unsigned int *size, size_t min_size, int zero_realloc) | |
528 | { | ||
529 | size_t max_size; | ||
530 | void *val; | ||
531 | |||
532 | 370003 | memcpy(&val, ptr, sizeof(val)); | |
533 |
2/2✓ Branch 0 taken 325515 times.
✓ Branch 1 taken 44488 times.
|
370003 | if (min_size <= *size) { |
534 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 325515 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
325515 | av_assert0(val || !min_size); |
535 | 325515 | return; | |
536 | } | ||
537 | |||
538 | 44488 | max_size = atomic_load_explicit(&max_alloc_size, memory_order_relaxed); | |
539 | /* *size is an unsigned, so the real maximum is <= UINT_MAX. */ | ||
540 | 44488 | max_size = FFMIN(max_size, UINT_MAX); | |
541 | |||
542 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 44488 times.
|
44488 | if (min_size > max_size) { |
543 | ✗ | av_freep(ptr); | |
544 | ✗ | *size = 0; | |
545 | ✗ | return; | |
546 | } | ||
547 | 44488 | min_size = FFMIN(max_size, FFMAX(min_size + min_size / 16 + 32, min_size)); | |
548 | 44488 | av_freep(ptr); | |
549 |
2/2✓ Branch 0 taken 42335 times.
✓ Branch 1 taken 2153 times.
|
44488 | val = zero_realloc ? av_mallocz(min_size) : av_malloc(min_size); |
550 | 44488 | memcpy(ptr, &val, sizeof(val)); | |
551 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 44488 times.
|
44488 | if (!val) |
552 | ✗ | min_size = 0; | |
553 | 44488 | *size = min_size; | |
554 | 44488 | return; | |
555 | } | ||
556 | |||
557 | 91947 | void av_fast_malloc(void *ptr, unsigned int *size, size_t min_size) | |
558 | { | ||
559 | 91947 | fast_malloc(ptr, size, min_size, 0); | |
560 | 91947 | } | |
561 | |||
562 | 278056 | void av_fast_mallocz(void *ptr, unsigned int *size, size_t min_size) | |
563 | { | ||
564 | 278056 | fast_malloc(ptr, size, min_size, 1); | |
565 | 278056 | } | |
566 | |||
567 | 640 | int av_size_mult(size_t a, size_t b, size_t *r) | |
568 | { | ||
569 | 640 | return size_mult(a, b, r); | |
570 | } | ||
571 |