diff options
author | Igor Pavlov <87184205+ip7z@users.noreply.github.com> | 2023-06-21 00:00:00 +0000 |
---|---|---|
committer | Igor Pavlov <87184205+ip7z@users.noreply.github.com> | 2023-12-17 14:59:19 +0500 |
commit | 5b39dc76f1bc82f941d5c800ab9f34407a06b53a (patch) | |
tree | fe5e17420300b715021a76328444088d32047963 /C/Alloc.c | |
parent | 93be7d4abfd4233228f58ee1fbbcd76d91be66a4 (diff) | |
download | 7zip-5b39dc76f1bc82f941d5c800ab9f34407a06b53a.tar.gz 7zip-5b39dc76f1bc82f941d5c800ab9f34407a06b53a.tar.bz2 7zip-5b39dc76f1bc82f941d5c800ab9f34407a06b53a.zip |
23.0123.01
Diffstat (limited to 'C/Alloc.c')
-rw-r--r-- | C/Alloc.c | 192 |
1 files changed, 132 insertions, 60 deletions
@@ -1,38 +1,54 @@ | |||
1 | /* Alloc.c -- Memory allocation functions | 1 | /* Alloc.c -- Memory allocation functions |
2 | 2021-07-13 : Igor Pavlov : Public domain */ | 2 | 2023-04-02 : Igor Pavlov : Public domain */ |
3 | 3 | ||
4 | #include "Precomp.h" | 4 | #include "Precomp.h" |
5 | 5 | ||
6 | #include <stdio.h> | ||
7 | |||
8 | #ifdef _WIN32 | 6 | #ifdef _WIN32 |
9 | #include <Windows.h> | 7 | #include "7zWindows.h" |
10 | #endif | 8 | #endif |
11 | #include <stdlib.h> | 9 | #include <stdlib.h> |
12 | 10 | ||
13 | #include "Alloc.h" | 11 | #include "Alloc.h" |
14 | 12 | ||
15 | /* #define _SZ_ALLOC_DEBUG */ | 13 | #ifdef _WIN32 |
14 | #ifdef Z7_LARGE_PAGES | ||
15 | #if defined(__clang__) || defined(__GNUC__) | ||
16 | typedef void (*Z7_voidFunction)(void); | ||
17 | #define MY_CAST_FUNC (Z7_voidFunction) | ||
18 | #elif defined(_MSC_VER) && _MSC_VER > 1920 | ||
19 | #define MY_CAST_FUNC (void *) | ||
20 | // #pragma warning(disable : 4191) // 'type cast': unsafe conversion from 'FARPROC' to 'void (__cdecl *)()' | ||
21 | #else | ||
22 | #define MY_CAST_FUNC | ||
23 | #endif | ||
24 | #endif // Z7_LARGE_PAGES | ||
25 | #endif // _WIN32 | ||
26 | |||
27 | // #define SZ_ALLOC_DEBUG | ||
28 | /* #define SZ_ALLOC_DEBUG */ | ||
16 | 29 | ||
17 | /* use _SZ_ALLOC_DEBUG to debug alloc/free operations */ | 30 | /* use SZ_ALLOC_DEBUG to debug alloc/free operations */ |
18 | #ifdef _SZ_ALLOC_DEBUG | 31 | #ifdef SZ_ALLOC_DEBUG |
19 | 32 | ||
33 | #include <string.h> | ||
20 | #include <stdio.h> | 34 | #include <stdio.h> |
21 | int g_allocCount = 0; | 35 | static int g_allocCount = 0; |
22 | int g_allocCountMid = 0; | 36 | #ifdef _WIN32 |
23 | int g_allocCountBig = 0; | 37 | static int g_allocCountMid = 0; |
38 | static int g_allocCountBig = 0; | ||
39 | #endif | ||
24 | 40 | ||
25 | 41 | ||
26 | #define CONVERT_INT_TO_STR(charType, tempSize) \ | 42 | #define CONVERT_INT_TO_STR(charType, tempSize) \ |
27 | unsigned char temp[tempSize]; unsigned i = 0; \ | 43 | char temp[tempSize]; unsigned i = 0; \ |
28 | while (val >= 10) { temp[i++] = (unsigned char)('0' + (unsigned)(val % 10)); val /= 10; } \ | 44 | while (val >= 10) { temp[i++] = (char)('0' + (unsigned)(val % 10)); val /= 10; } \ |
29 | *s++ = (charType)('0' + (unsigned)val); \ | 45 | *s++ = (charType)('0' + (unsigned)val); \ |
30 | while (i != 0) { i--; *s++ = temp[i]; } \ | 46 | while (i != 0) { i--; *s++ = temp[i]; } \ |
31 | *s = 0; | 47 | *s = 0; |
32 | 48 | ||
33 | static void ConvertUInt64ToString(UInt64 val, char *s) | 49 | static void ConvertUInt64ToString(UInt64 val, char *s) |
34 | { | 50 | { |
35 | CONVERT_INT_TO_STR(char, 24); | 51 | CONVERT_INT_TO_STR(char, 24) |
36 | } | 52 | } |
37 | 53 | ||
38 | #define GET_HEX_CHAR(t) ((char)(((t < 10) ? ('0' + t) : ('A' + (t - 10))))) | 54 | #define GET_HEX_CHAR(t) ((char)(((t < 10) ? ('0' + t) : ('A' + (t - 10))))) |
@@ -77,7 +93,7 @@ static void PrintAligned(const char *s, size_t align) | |||
77 | Print(s); | 93 | Print(s); |
78 | } | 94 | } |
79 | 95 | ||
80 | static void PrintLn() | 96 | static void PrintLn(void) |
81 | { | 97 | { |
82 | Print("\n"); | 98 | Print("\n"); |
83 | } | 99 | } |
@@ -89,10 +105,10 @@ static void PrintHex(UInt64 v, size_t align) | |||
89 | PrintAligned(s, align); | 105 | PrintAligned(s, align); |
90 | } | 106 | } |
91 | 107 | ||
92 | static void PrintDec(UInt64 v, size_t align) | 108 | static void PrintDec(int v, size_t align) |
93 | { | 109 | { |
94 | char s[32]; | 110 | char s[32]; |
95 | ConvertUInt64ToString(v, s); | 111 | ConvertUInt64ToString((unsigned)v, s); |
96 | PrintAligned(s, align); | 112 | PrintAligned(s, align); |
97 | } | 113 | } |
98 | 114 | ||
@@ -102,12 +118,19 @@ static void PrintAddr(void *p) | |||
102 | } | 118 | } |
103 | 119 | ||
104 | 120 | ||
105 | #define PRINT_ALLOC(name, cnt, size, ptr) \ | 121 | #define PRINT_REALLOC(name, cnt, size, ptr) { \ |
122 | Print(name " "); \ | ||
123 | if (!ptr) PrintDec(cnt++, 10); \ | ||
124 | PrintHex(size, 10); \ | ||
125 | PrintAddr(ptr); \ | ||
126 | PrintLn(); } | ||
127 | |||
128 | #define PRINT_ALLOC(name, cnt, size, ptr) { \ | ||
106 | Print(name " "); \ | 129 | Print(name " "); \ |
107 | PrintDec(cnt++, 10); \ | 130 | PrintDec(cnt++, 10); \ |
108 | PrintHex(size, 10); \ | 131 | PrintHex(size, 10); \ |
109 | PrintAddr(ptr); \ | 132 | PrintAddr(ptr); \ |
110 | PrintLn(); | 133 | PrintLn(); } |
111 | 134 | ||
112 | #define PRINT_FREE(name, cnt, ptr) if (ptr) { \ | 135 | #define PRINT_FREE(name, cnt, ptr) if (ptr) { \ |
113 | Print(name " "); \ | 136 | Print(name " "); \ |
@@ -117,7 +140,9 @@ static void PrintAddr(void *p) | |||
117 | 140 | ||
118 | #else | 141 | #else |
119 | 142 | ||
143 | #ifdef _WIN32 | ||
120 | #define PRINT_ALLOC(name, cnt, size, ptr) | 144 | #define PRINT_ALLOC(name, cnt, size, ptr) |
145 | #endif | ||
121 | #define PRINT_FREE(name, cnt, ptr) | 146 | #define PRINT_FREE(name, cnt, ptr) |
122 | #define Print(s) | 147 | #define Print(s) |
123 | #define PrintLn() | 148 | #define PrintLn() |
@@ -127,16 +152,31 @@ static void PrintAddr(void *p) | |||
127 | #endif | 152 | #endif |
128 | 153 | ||
129 | 154 | ||
155 | /* | ||
156 | by specification: | ||
157 | malloc(non_NULL, 0) : returns NULL or a unique pointer value that can later be successfully passed to free() | ||
158 | realloc(NULL, size) : the call is equivalent to malloc(size) | ||
159 | realloc(non_NULL, 0) : the call is equivalent to free(ptr) | ||
160 | |||
161 | in main compilers: | ||
162 | malloc(0) : returns non_NULL | ||
163 | realloc(NULL, 0) : returns non_NULL | ||
164 | realloc(non_NULL, 0) : returns NULL | ||
165 | */ | ||
166 | |||
130 | 167 | ||
131 | void *MyAlloc(size_t size) | 168 | void *MyAlloc(size_t size) |
132 | { | 169 | { |
133 | if (size == 0) | 170 | if (size == 0) |
134 | return NULL; | 171 | return NULL; |
135 | PRINT_ALLOC("Alloc ", g_allocCount, size, NULL); | 172 | // PRINT_ALLOC("Alloc ", g_allocCount, size, NULL) |
136 | #ifdef _SZ_ALLOC_DEBUG | 173 | #ifdef SZ_ALLOC_DEBUG |
137 | { | 174 | { |
138 | void *p = malloc(size); | 175 | void *p = malloc(size); |
139 | // PRINT_ALLOC("Alloc ", g_allocCount, size, p); | 176 | if (p) |
177 | { | ||
178 | PRINT_ALLOC("Alloc ", g_allocCount, size, p) | ||
179 | } | ||
140 | return p; | 180 | return p; |
141 | } | 181 | } |
142 | #else | 182 | #else |
@@ -146,33 +186,64 @@ void *MyAlloc(size_t size) | |||
146 | 186 | ||
147 | void MyFree(void *address) | 187 | void MyFree(void *address) |
148 | { | 188 | { |
149 | PRINT_FREE("Free ", g_allocCount, address); | 189 | PRINT_FREE("Free ", g_allocCount, address) |
150 | 190 | ||
151 | free(address); | 191 | free(address); |
152 | } | 192 | } |
153 | 193 | ||
194 | void *MyRealloc(void *address, size_t size) | ||
195 | { | ||
196 | if (size == 0) | ||
197 | { | ||
198 | MyFree(address); | ||
199 | return NULL; | ||
200 | } | ||
201 | // PRINT_REALLOC("Realloc ", g_allocCount, size, address) | ||
202 | #ifdef SZ_ALLOC_DEBUG | ||
203 | { | ||
204 | void *p = realloc(address, size); | ||
205 | if (p) | ||
206 | { | ||
207 | PRINT_REALLOC("Realloc ", g_allocCount, size, address) | ||
208 | } | ||
209 | return p; | ||
210 | } | ||
211 | #else | ||
212 | return realloc(address, size); | ||
213 | #endif | ||
214 | } | ||
215 | |||
216 | |||
154 | #ifdef _WIN32 | 217 | #ifdef _WIN32 |
155 | 218 | ||
156 | void *MidAlloc(size_t size) | 219 | void *MidAlloc(size_t size) |
157 | { | 220 | { |
158 | if (size == 0) | 221 | if (size == 0) |
159 | return NULL; | 222 | return NULL; |
160 | 223 | #ifdef SZ_ALLOC_DEBUG | |
161 | PRINT_ALLOC("Alloc-Mid", g_allocCountMid, size, NULL); | 224 | { |
162 | 225 | void *p = VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_READWRITE); | |
226 | if (p) | ||
227 | { | ||
228 | PRINT_ALLOC("Alloc-Mid", g_allocCountMid, size, p) | ||
229 | } | ||
230 | return p; | ||
231 | } | ||
232 | #else | ||
163 | return VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_READWRITE); | 233 | return VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_READWRITE); |
234 | #endif | ||
164 | } | 235 | } |
165 | 236 | ||
166 | void MidFree(void *address) | 237 | void MidFree(void *address) |
167 | { | 238 | { |
168 | PRINT_FREE("Free-Mid", g_allocCountMid, address); | 239 | PRINT_FREE("Free-Mid", g_allocCountMid, address) |
169 | 240 | ||
170 | if (!address) | 241 | if (!address) |
171 | return; | 242 | return; |
172 | VirtualFree(address, 0, MEM_RELEASE); | 243 | VirtualFree(address, 0, MEM_RELEASE); |
173 | } | 244 | } |
174 | 245 | ||
175 | #ifdef _7ZIP_LARGE_PAGES | 246 | #ifdef Z7_LARGE_PAGES |
176 | 247 | ||
177 | #ifdef MEM_LARGE_PAGES | 248 | #ifdef MEM_LARGE_PAGES |
178 | #define MY__MEM_LARGE_PAGES MEM_LARGE_PAGES | 249 | #define MY__MEM_LARGE_PAGES MEM_LARGE_PAGES |
@@ -183,34 +254,35 @@ void MidFree(void *address) | |||
183 | extern | 254 | extern |
184 | SIZE_T g_LargePageSize; | 255 | SIZE_T g_LargePageSize; |
185 | SIZE_T g_LargePageSize = 0; | 256 | SIZE_T g_LargePageSize = 0; |
186 | typedef SIZE_T (WINAPI *GetLargePageMinimumP)(VOID); | 257 | typedef SIZE_T (WINAPI *Func_GetLargePageMinimum)(VOID); |
187 | 258 | ||
188 | #endif // _7ZIP_LARGE_PAGES | 259 | void SetLargePageSize(void) |
189 | |||
190 | void SetLargePageSize() | ||
191 | { | 260 | { |
192 | #ifdef _7ZIP_LARGE_PAGES | 261 | #ifdef Z7_LARGE_PAGES |
193 | SIZE_T size; | 262 | SIZE_T size; |
194 | GetLargePageMinimumP largePageMinimum = (GetLargePageMinimumP) | 263 | const |
195 | GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "GetLargePageMinimum"); | 264 | Func_GetLargePageMinimum fn = |
196 | if (!largePageMinimum) | 265 | (Func_GetLargePageMinimum) MY_CAST_FUNC GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), |
266 | "GetLargePageMinimum"); | ||
267 | if (!fn) | ||
197 | return; | 268 | return; |
198 | size = largePageMinimum(); | 269 | size = fn(); |
199 | if (size == 0 || (size & (size - 1)) != 0) | 270 | if (size == 0 || (size & (size - 1)) != 0) |
200 | return; | 271 | return; |
201 | g_LargePageSize = size; | 272 | g_LargePageSize = size; |
202 | #endif | 273 | #endif |
203 | } | 274 | } |
204 | 275 | ||
276 | #endif // Z7_LARGE_PAGES | ||
205 | 277 | ||
206 | void *BigAlloc(size_t size) | 278 | void *BigAlloc(size_t size) |
207 | { | 279 | { |
208 | if (size == 0) | 280 | if (size == 0) |
209 | return NULL; | 281 | return NULL; |
210 | 282 | ||
211 | PRINT_ALLOC("Alloc-Big", g_allocCountBig, size, NULL); | 283 | PRINT_ALLOC("Alloc-Big", g_allocCountBig, size, NULL) |
212 | 284 | ||
213 | #ifdef _7ZIP_LARGE_PAGES | 285 | #ifdef Z7_LARGE_PAGES |
214 | { | 286 | { |
215 | SIZE_T ps = g_LargePageSize; | 287 | SIZE_T ps = g_LargePageSize; |
216 | if (ps != 0 && ps <= (1 << 30) && size > (ps / 2)) | 288 | if (ps != 0 && ps <= (1 << 30) && size > (ps / 2)) |
@@ -220,38 +292,38 @@ void *BigAlloc(size_t size) | |||
220 | size2 = (size + ps) & ~ps; | 292 | size2 = (size + ps) & ~ps; |
221 | if (size2 >= size) | 293 | if (size2 >= size) |
222 | { | 294 | { |
223 | void *res = VirtualAlloc(NULL, size2, MEM_COMMIT | MY__MEM_LARGE_PAGES, PAGE_READWRITE); | 295 | void *p = VirtualAlloc(NULL, size2, MEM_COMMIT | MY__MEM_LARGE_PAGES, PAGE_READWRITE); |
224 | if (res) | 296 | if (p) |
225 | return res; | 297 | { |
298 | PRINT_ALLOC("Alloc-BM ", g_allocCountMid, size2, p) | ||
299 | return p; | ||
300 | } | ||
226 | } | 301 | } |
227 | } | 302 | } |
228 | } | 303 | } |
229 | #endif | 304 | #endif |
230 | 305 | ||
231 | return VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_READWRITE); | 306 | return MidAlloc(size); |
232 | } | 307 | } |
233 | 308 | ||
234 | void BigFree(void *address) | 309 | void BigFree(void *address) |
235 | { | 310 | { |
236 | PRINT_FREE("Free-Big", g_allocCountBig, address); | 311 | PRINT_FREE("Free-Big", g_allocCountBig, address) |
237 | 312 | MidFree(address); | |
238 | if (!address) | ||
239 | return; | ||
240 | VirtualFree(address, 0, MEM_RELEASE); | ||
241 | } | 313 | } |
242 | 314 | ||
243 | #endif | 315 | #endif // _WIN32 |
244 | 316 | ||
245 | 317 | ||
246 | static void *SzAlloc(ISzAllocPtr p, size_t size) { UNUSED_VAR(p); return MyAlloc(size); } | 318 | static void *SzAlloc(ISzAllocPtr p, size_t size) { UNUSED_VAR(p) return MyAlloc(size); } |
247 | static void SzFree(ISzAllocPtr p, void *address) { UNUSED_VAR(p); MyFree(address); } | 319 | static void SzFree(ISzAllocPtr p, void *address) { UNUSED_VAR(p) MyFree(address); } |
248 | const ISzAlloc g_Alloc = { SzAlloc, SzFree }; | 320 | const ISzAlloc g_Alloc = { SzAlloc, SzFree }; |
249 | 321 | ||
250 | #ifdef _WIN32 | 322 | #ifdef _WIN32 |
251 | static void *SzMidAlloc(ISzAllocPtr p, size_t size) { UNUSED_VAR(p); return MidAlloc(size); } | 323 | static void *SzMidAlloc(ISzAllocPtr p, size_t size) { UNUSED_VAR(p) return MidAlloc(size); } |
252 | static void SzMidFree(ISzAllocPtr p, void *address) { UNUSED_VAR(p); MidFree(address); } | 324 | static void SzMidFree(ISzAllocPtr p, void *address) { UNUSED_VAR(p) MidFree(address); } |
253 | static void *SzBigAlloc(ISzAllocPtr p, size_t size) { UNUSED_VAR(p); return BigAlloc(size); } | 325 | static void *SzBigAlloc(ISzAllocPtr p, size_t size) { UNUSED_VAR(p) return BigAlloc(size); } |
254 | static void SzBigFree(ISzAllocPtr p, void *address) { UNUSED_VAR(p); BigFree(address); } | 326 | static void SzBigFree(ISzAllocPtr p, void *address) { UNUSED_VAR(p) BigFree(address); } |
255 | const ISzAlloc g_MidAlloc = { SzMidAlloc, SzMidFree }; | 327 | const ISzAlloc g_MidAlloc = { SzMidAlloc, SzMidFree }; |
256 | const ISzAlloc g_BigAlloc = { SzBigAlloc, SzBigFree }; | 328 | const ISzAlloc g_BigAlloc = { SzBigAlloc, SzBigFree }; |
257 | #endif | 329 | #endif |
@@ -334,7 +406,7 @@ static void *SzAlignedAlloc(ISzAllocPtr pp, size_t size) | |||
334 | void *p; | 406 | void *p; |
335 | void *pAligned; | 407 | void *pAligned; |
336 | size_t newSize; | 408 | size_t newSize; |
337 | UNUSED_VAR(pp); | 409 | UNUSED_VAR(pp) |
338 | 410 | ||
339 | /* also we can allocate additional dummy ALLOC_ALIGN_SIZE bytes after aligned | 411 | /* also we can allocate additional dummy ALLOC_ALIGN_SIZE bytes after aligned |
340 | block to prevent cache line sharing with another allocated blocks */ | 412 | block to prevent cache line sharing with another allocated blocks */ |
@@ -362,7 +434,7 @@ static void *SzAlignedAlloc(ISzAllocPtr pp, size_t size) | |||
362 | #else | 434 | #else |
363 | 435 | ||
364 | void *p; | 436 | void *p; |
365 | UNUSED_VAR(pp); | 437 | UNUSED_VAR(pp) |
366 | if (posix_memalign(&p, ALLOC_ALIGN_SIZE, size)) | 438 | if (posix_memalign(&p, ALLOC_ALIGN_SIZE, size)) |
367 | return NULL; | 439 | return NULL; |
368 | 440 | ||
@@ -377,7 +449,7 @@ static void *SzAlignedAlloc(ISzAllocPtr pp, size_t size) | |||
377 | 449 | ||
378 | static void SzAlignedFree(ISzAllocPtr pp, void *address) | 450 | static void SzAlignedFree(ISzAllocPtr pp, void *address) |
379 | { | 451 | { |
380 | UNUSED_VAR(pp); | 452 | UNUSED_VAR(pp) |
381 | #ifndef USE_posix_memalign | 453 | #ifndef USE_posix_memalign |
382 | if (address) | 454 | if (address) |
383 | MyFree(((void **)address)[-1]); | 455 | MyFree(((void **)address)[-1]); |
@@ -401,7 +473,7 @@ const ISzAlloc g_AlignedAlloc = { SzAlignedAlloc, SzAlignedFree }; | |||
401 | 473 | ||
402 | static void *AlignOffsetAlloc_Alloc(ISzAllocPtr pp, size_t size) | 474 | static void *AlignOffsetAlloc_Alloc(ISzAllocPtr pp, size_t size) |
403 | { | 475 | { |
404 | CAlignOffsetAlloc *p = CONTAINER_FROM_VTBL(pp, CAlignOffsetAlloc, vt); | 476 | const CAlignOffsetAlloc *p = Z7_CONTAINER_FROM_VTBL_CONST(pp, CAlignOffsetAlloc, vt); |
405 | void *adr; | 477 | void *adr; |
406 | void *pAligned; | 478 | void *pAligned; |
407 | size_t newSize; | 479 | size_t newSize; |
@@ -447,7 +519,7 @@ static void AlignOffsetAlloc_Free(ISzAllocPtr pp, void *address) | |||
447 | { | 519 | { |
448 | if (address) | 520 | if (address) |
449 | { | 521 | { |
450 | CAlignOffsetAlloc *p = CONTAINER_FROM_VTBL(pp, CAlignOffsetAlloc, vt); | 522 | const CAlignOffsetAlloc *p = Z7_CONTAINER_FROM_VTBL_CONST(pp, CAlignOffsetAlloc, vt); |
451 | PrintLn(); | 523 | PrintLn(); |
452 | Print("- Aligned Free: "); | 524 | Print("- Aligned Free: "); |
453 | PrintLn(); | 525 | PrintLn(); |