Commit | Line | Data |
---|---|---|
d01fe86d | 1 | /* |
cea8f6f3 | 2 | * default memory allocator for libavutil |
d01fe86d FB |
3 | * Copyright (c) 2002 Fabrice Bellard. |
4 | * | |
5 | * This library is free software; you can redistribute it and/or | |
6 | * modify it under the terms of the GNU Lesser General Public | |
7 | * License as published by the Free Software Foundation; either | |
8 | * version 2 of the License, or (at your option) any later version. | |
9 | * | |
10 | * This library is distributed in the hope that it will be useful, | |
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
13 | * Lesser General Public License for more details. | |
14 | * | |
15 | * You should have received a copy of the GNU Lesser General Public | |
16 | * License along with this library; if not, write to the Free Software | |
5509bffa | 17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
d01fe86d | 18 | */ |
115329f1 | 19 | |
983e3246 MN |
20 | /** |
21 | * @file mem.c | |
cea8f6f3 | 22 | * default memory allocator for libavutil. |
983e3246 | 23 | */ |
115329f1 | 24 | |
cea8f6f3 | 25 | #include "common.h" |
8e1e6f31 FB |
26 | |
27 | /* here we can use OS dependant allocation functions */ | |
28 | #undef malloc | |
29 | #undef free | |
30 | #undef realloc | |
31 | ||
d01fe86d FB |
32 | #ifdef HAVE_MALLOC_H |
33 | #include <malloc.h> | |
34 | #endif | |
35 | ||
36 | /* you can redefine av_malloc and av_free in your project to use your | |
37 | memory allocator. You do not need to suppress this file because the | |
38 | linker will do it automatically */ | |
39 | ||
115329f1 | 40 | /** |
8e1e6f31 FB |
41 | * Memory allocation of size byte with alignment suitable for all |
42 | * memory accesses (including vectors if available on the | |
43 | * CPU). av_malloc(0) must return a non NULL pointer. | |
44 | */ | |
18f77016 | 45 | void *av_malloc(unsigned int size) |
d01fe86d FB |
46 | { |
47 | void *ptr; | |
88730be6 | 48 | #ifdef MEMALIGN_HACK |
ed96aeea | 49 | long diff; |
88730be6 | 50 | #endif |
0ecca7a4 | 51 | |
7d77d5f6 | 52 | /* let's disallow possible ambiguous cases */ |
0a7c36af | 53 | if(size > (INT_MAX-16) ) |
0ecca7a4 | 54 | return NULL; |
115329f1 | 55 | |
da9b170c | 56 | #ifdef MEMALIGN_HACK |
a9493601 H |
57 | ptr = malloc(size+16); |
58 | if(!ptr) | |
59 | return ptr; | |
ed96aeea | 60 | diff= ((-(long)ptr - 1)&15) + 1; |
da9b170c MN |
61 | ptr += diff; |
62 | ((char*)ptr)[-1]= diff; | |
115329f1 | 63 | #elif defined (HAVE_MEMALIGN) |
8f2b21a8 | 64 | ptr = memalign(16,size); |
115329f1 | 65 | /* Why 64? |
d01fe86d FB |
66 | Indeed, we should align it: |
67 | on 4 for 386 | |
68 | on 16 for 486 | |
bb270c08 DB |
69 | on 32 for 586, PPro - k6-III |
70 | on 64 for K7 (maybe for P3 too). | |
d01fe86d FB |
71 | Because L1 and L2 caches are aligned on those values. |
72 | But I don't want to code such logic here! | |
73 | */ | |
8f2b21a8 MN |
74 | /* Why 16? |
75 | because some cpus need alignment, for example SSE2 on P4, & most RISC cpus | |
76 | it will just trigger an exception and the unaligned load will be done in the | |
77 | exception handler or it will just segfault (SSE2 on P4) | |
78 | Why not larger? because i didnt see a difference in benchmarks ... | |
79 | */ | |
80 | /* benchmarks with p3 | |
bb270c08 DB |
81 | memalign(64)+1 3071,3051,3032 |
82 | memalign(64)+2 3051,3032,3041 | |
83 | memalign(64)+4 2911,2896,2915 | |
84 | memalign(64)+8 2545,2554,2550 | |
85 | memalign(64)+16 2543,2572,2563 | |
86 | memalign(64)+32 2546,2545,2571 | |
87 | memalign(64)+64 2570,2533,2558 | |
115329f1 | 88 | |
8f2b21a8 MN |
89 | btw, malloc seems to do 8 byte alignment by default here |
90 | */ | |
d01fe86d FB |
91 | #else |
92 | ptr = malloc(size); | |
93 | #endif | |
d01fe86d FB |
94 | return ptr; |
95 | } | |
96 | ||
b7a22d84 | 97 | /** |
8e1e6f31 FB |
98 | * av_realloc semantics (same as glibc): if ptr is NULL and size > 0, |
99 | * identical to malloc(size). If size is zero, it is identical to | |
115329f1 | 100 | * free(ptr) and NULL is returned. |
b7a22d84 | 101 | */ |
8e1e6f31 FB |
102 | void *av_realloc(void *ptr, unsigned int size) |
103 | { | |
0a7c36af MN |
104 | #ifdef MEMALIGN_HACK |
105 | int diff; | |
106 | #endif | |
88730be6 | 107 | |
7d77d5f6 | 108 | /* let's disallow possible ambiguous cases */ |
a9493601 | 109 | if(size > (INT_MAX-16) ) |
0ecca7a4 MN |
110 | return NULL; |
111 | ||
0a7c36af MN |
112 | #ifdef MEMALIGN_HACK |
113 | //FIXME this isn't aligned correctly, though it probably isn't needed | |
114 | if(!ptr) return av_malloc(size); | |
115 | diff= ((char*)ptr)[-1]; | |
116 | return realloc(ptr - diff, size + diff) + diff; | |
117 | #else | |
118 | return realloc(ptr, size); | |
da9b170c | 119 | #endif |
b7a22d84 MN |
120 | } |
121 | ||
1499e0be MN |
122 | /** |
123 | * Free memory which has been allocated with av_malloc(z)() or av_realloc(). | |
4f59b684 | 124 | * NOTE: ptr = NULL is explicetly allowed |
da2e9781 | 125 | * Note2: it is recommended that you use av_freep() instead |
1499e0be | 126 | */ |
d01fe86d FB |
127 | void av_free(void *ptr) |
128 | { | |
129 | /* XXX: this test should not be needed on most libcs */ | |
130 | if (ptr) | |
da9b170c MN |
131 | #ifdef MEMALIGN_HACK |
132 | free(ptr - ((char*)ptr)[-1]); | |
133 | #else | |
d01fe86d | 134 | free(ptr); |
da9b170c | 135 | #endif |
d01fe86d FB |
136 | } |
137 | ||
79e47000 LB |
138 | /** |
139 | * Frees memory and sets the pointer to NULL. | |
140 | * @param arg pointer to the pointer which should be freed | |
141 | */ | |
142 | void av_freep(void *arg) | |
143 | { | |
144 | void **ptr= (void**)arg; | |
145 | av_free(*ptr); | |
146 | *ptr = NULL; | |
147 | } | |
148 | ||
149 | void *av_mallocz(unsigned int size) | |
150 | { | |
151 | void *ptr; | |
152 | ||
153 | ptr = av_malloc(size); | |
154 | if (ptr) | |
155 | memset(ptr, 0, size); | |
156 | return ptr; | |
157 | } | |
158 | ||
159 | char *av_strdup(const char *s) | |
160 | { | |
161 | char *ptr; | |
162 | int len; | |
163 | len = strlen(s) + 1; | |
164 | ptr = av_malloc(len); | |
165 | if (ptr) | |
166 | memcpy(ptr, s, len); | |
167 | return ptr; | |
168 | } | |
169 |