diff options
author | Igor Pavlov <87184205+ip7z@users.noreply.github.com> | 2024-05-14 00:00:00 +0000 |
---|---|---|
committer | Igor Pavlov <87184205+ip7z@users.noreply.github.com> | 2024-05-15 23:55:04 +0500 |
commit | fc662341e6f85da78ada0e443f6116b978f79f22 (patch) | |
tree | 1be1cc402a7a9cbc18d4eeea6b141354c2d559e3 /C/Alloc.c | |
parent | 5b39dc76f1bc82f941d5c800ab9f34407a06b53a (diff) | |
download | 7zip-fc662341e6f85da78ada0e443f6116b978f79f22.tar.gz 7zip-fc662341e6f85da78ada0e443f6116b978f79f22.tar.bz2 7zip-fc662341e6f85da78ada0e443f6116b978f79f22.zip |
24.0524.05
Diffstat (limited to 'C/Alloc.c')
-rw-r--r-- | C/Alloc.c | 174 |
1 files changed, 122 insertions, 52 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* Alloc.c -- Memory allocation functions | 1 | /* Alloc.c -- Memory allocation functions |
2 | 2023-04-02 : Igor Pavlov : Public domain */ | 2 | 2024-02-18 : Igor Pavlov : Public domain */ |
3 | 3 | ||
4 | #include "Precomp.h" | 4 | #include "Precomp.h" |
5 | 5 | ||
@@ -10,19 +10,18 @@ | |||
10 | 10 | ||
11 | #include "Alloc.h" | 11 | #include "Alloc.h" |
12 | 12 | ||
13 | #ifdef _WIN32 | 13 | #if defined(Z7_LARGE_PAGES) && defined(_WIN32) && \ |
14 | #ifdef Z7_LARGE_PAGES | 14 | (!defined(Z7_WIN32_WINNT_MIN) || Z7_WIN32_WINNT_MIN < 0x0502) // < Win2003 (xp-64) |
15 | #if defined(__clang__) || defined(__GNUC__) | 15 | #define Z7_USE_DYN_GetLargePageMinimum |
16 | typedef void (*Z7_voidFunction)(void); | 16 | #endif |
17 | #define MY_CAST_FUNC (Z7_voidFunction) | 17 | |
18 | #elif defined(_MSC_VER) && _MSC_VER > 1920 | 18 | // for debug: |
19 | #define MY_CAST_FUNC (void *) | 19 | #if 0 |
20 | // #pragma warning(disable : 4191) // 'type cast': unsafe conversion from 'FARPROC' to 'void (__cdecl *)()' | 20 | #if defined(__CHERI__) && defined(__SIZEOF_POINTER__) && (__SIZEOF_POINTER__ == 16) |
21 | #else | 21 | // #pragma message("=== Z7_ALLOC_NO_OFFSET_ALLOCATOR === ") |
22 | #define MY_CAST_FUNC | 22 | #define Z7_ALLOC_NO_OFFSET_ALLOCATOR |
23 | #endif | ||
23 | #endif | 24 | #endif |
24 | #endif // Z7_LARGE_PAGES | ||
25 | #endif // _WIN32 | ||
26 | 25 | ||
27 | // #define SZ_ALLOC_DEBUG | 26 | // #define SZ_ALLOC_DEBUG |
28 | /* #define SZ_ALLOC_DEBUG */ | 27 | /* #define SZ_ALLOC_DEBUG */ |
@@ -146,7 +145,9 @@ static void PrintAddr(void *p) | |||
146 | #define PRINT_FREE(name, cnt, ptr) | 145 | #define PRINT_FREE(name, cnt, ptr) |
147 | #define Print(s) | 146 | #define Print(s) |
148 | #define PrintLn() | 147 | #define PrintLn() |
148 | #ifndef Z7_ALLOC_NO_OFFSET_ALLOCATOR | ||
149 | #define PrintHex(v, align) | 149 | #define PrintHex(v, align) |
150 | #endif | ||
150 | #define PrintAddr(p) | 151 | #define PrintAddr(p) |
151 | 152 | ||
152 | #endif | 153 | #endif |
@@ -246,9 +247,9 @@ void MidFree(void *address) | |||
246 | #ifdef Z7_LARGE_PAGES | 247 | #ifdef Z7_LARGE_PAGES |
247 | 248 | ||
248 | #ifdef MEM_LARGE_PAGES | 249 | #ifdef MEM_LARGE_PAGES |
249 | #define MY__MEM_LARGE_PAGES MEM_LARGE_PAGES | 250 | #define MY_MEM_LARGE_PAGES MEM_LARGE_PAGES |
250 | #else | 251 | #else |
251 | #define MY__MEM_LARGE_PAGES 0x20000000 | 252 | #define MY_MEM_LARGE_PAGES 0x20000000 |
252 | #endif | 253 | #endif |
253 | 254 | ||
254 | extern | 255 | extern |
@@ -258,19 +259,23 @@ typedef SIZE_T (WINAPI *Func_GetLargePageMinimum)(VOID); | |||
258 | 259 | ||
259 | void SetLargePageSize(void) | 260 | void SetLargePageSize(void) |
260 | { | 261 | { |
261 | #ifdef Z7_LARGE_PAGES | ||
262 | SIZE_T size; | 262 | SIZE_T size; |
263 | #ifdef Z7_USE_DYN_GetLargePageMinimum | ||
264 | Z7_DIAGNOSTIC_IGNORE_CAST_FUNCTION | ||
265 | |||
263 | const | 266 | const |
264 | Func_GetLargePageMinimum fn = | 267 | Func_GetLargePageMinimum fn = |
265 | (Func_GetLargePageMinimum) MY_CAST_FUNC GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), | 268 | (Func_GetLargePageMinimum) Z7_CAST_FUNC_C GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), |
266 | "GetLargePageMinimum"); | 269 | "GetLargePageMinimum"); |
267 | if (!fn) | 270 | if (!fn) |
268 | return; | 271 | return; |
269 | size = fn(); | 272 | size = fn(); |
273 | #else | ||
274 | size = GetLargePageMinimum(); | ||
275 | #endif | ||
270 | if (size == 0 || (size & (size - 1)) != 0) | 276 | if (size == 0 || (size & (size - 1)) != 0) |
271 | return; | 277 | return; |
272 | g_LargePageSize = size; | 278 | g_LargePageSize = size; |
273 | #endif | ||
274 | } | 279 | } |
275 | 280 | ||
276 | #endif // Z7_LARGE_PAGES | 281 | #endif // Z7_LARGE_PAGES |
@@ -292,7 +297,7 @@ void *BigAlloc(size_t size) | |||
292 | size2 = (size + ps) & ~ps; | 297 | size2 = (size + ps) & ~ps; |
293 | if (size2 >= size) | 298 | if (size2 >= size) |
294 | { | 299 | { |
295 | void *p = VirtualAlloc(NULL, size2, MEM_COMMIT | MY__MEM_LARGE_PAGES, PAGE_READWRITE); | 300 | void *p = VirtualAlloc(NULL, size2, MEM_COMMIT | MY_MEM_LARGE_PAGES, PAGE_READWRITE); |
296 | if (p) | 301 | if (p) |
297 | { | 302 | { |
298 | PRINT_ALLOC("Alloc-BM ", g_allocCountMid, size2, p) | 303 | PRINT_ALLOC("Alloc-BM ", g_allocCountMid, size2, p) |
@@ -328,20 +333,7 @@ const ISzAlloc g_MidAlloc = { SzMidAlloc, SzMidFree }; | |||
328 | const ISzAlloc g_BigAlloc = { SzBigAlloc, SzBigFree }; | 333 | const ISzAlloc g_BigAlloc = { SzBigAlloc, SzBigFree }; |
329 | #endif | 334 | #endif |
330 | 335 | ||
331 | /* | 336 | #ifndef Z7_ALLOC_NO_OFFSET_ALLOCATOR |
332 | uintptr_t : <stdint.h> C99 (optional) | ||
333 | : unsupported in VS6 | ||
334 | */ | ||
335 | |||
336 | #ifdef _WIN32 | ||
337 | typedef UINT_PTR UIntPtr; | ||
338 | #else | ||
339 | /* | ||
340 | typedef uintptr_t UIntPtr; | ||
341 | */ | ||
342 | typedef ptrdiff_t UIntPtr; | ||
343 | #endif | ||
344 | |||
345 | 337 | ||
346 | #define ADJUST_ALLOC_SIZE 0 | 338 | #define ADJUST_ALLOC_SIZE 0 |
347 | /* | 339 | /* |
@@ -352,14 +344,36 @@ const ISzAlloc g_BigAlloc = { SzBigAlloc, SzBigFree }; | |||
352 | MyAlloc() can return address that is NOT multiple of sizeof(void *). | 344 | MyAlloc() can return address that is NOT multiple of sizeof(void *). |
353 | */ | 345 | */ |
354 | 346 | ||
355 | |||
356 | /* | 347 | /* |
357 | #define MY_ALIGN_PTR_DOWN(p, align) ((void *)((char *)(p) - ((size_t)(UIntPtr)(p) & ((align) - 1)))) | 348 | uintptr_t : <stdint.h> C99 (optional) |
349 | : unsupported in VS6 | ||
358 | */ | 350 | */ |
359 | #define MY_ALIGN_PTR_DOWN(p, align) ((void *)((((UIntPtr)(p)) & ~((UIntPtr)(align) - 1)))) | 351 | typedef |
352 | #ifdef _WIN32 | ||
353 | UINT_PTR | ||
354 | #elif 1 | ||
355 | uintptr_t | ||
356 | #else | ||
357 | ptrdiff_t | ||
358 | #endif | ||
359 | MY_uintptr_t; | ||
360 | |||
361 | #if 0 \ | ||
362 | || (defined(__CHERI__) \ | ||
363 | || defined(__SIZEOF_POINTER__) && (__SIZEOF_POINTER__ > 8)) | ||
364 | // for 128-bit pointers (cheri): | ||
365 | #define MY_ALIGN_PTR_DOWN(p, align) \ | ||
366 | ((void *)((char *)(p) - ((size_t)(MY_uintptr_t)(p) & ((align) - 1)))) | ||
367 | #else | ||
368 | #define MY_ALIGN_PTR_DOWN(p, align) \ | ||
369 | ((void *)((((MY_uintptr_t)(p)) & ~((MY_uintptr_t)(align) - 1)))) | ||
370 | #endif | ||
360 | 371 | ||
372 | #endif | ||
361 | 373 | ||
362 | #if !defined(_WIN32) && defined(_POSIX_C_SOURCE) && (_POSIX_C_SOURCE >= 200112L) | 374 | #if !defined(_WIN32) \ |
375 | && (defined(Z7_ALLOC_NO_OFFSET_ALLOCATOR) \ | ||
376 | || defined(_POSIX_C_SOURCE) && (_POSIX_C_SOURCE >= 200112L)) | ||
363 | #define USE_posix_memalign | 377 | #define USE_posix_memalign |
364 | #endif | 378 | #endif |
365 | 379 | ||
@@ -399,14 +413,13 @@ static int posix_memalign(void **ptr, size_t align, size_t size) | |||
399 | 413 | ||
400 | #define ALLOC_ALIGN_SIZE ((size_t)1 << 7) | 414 | #define ALLOC_ALIGN_SIZE ((size_t)1 << 7) |
401 | 415 | ||
402 | static void *SzAlignedAlloc(ISzAllocPtr pp, size_t size) | 416 | void *z7_AlignedAlloc(size_t size) |
403 | { | 417 | { |
404 | #ifndef USE_posix_memalign | 418 | #ifndef USE_posix_memalign |
405 | 419 | ||
406 | void *p; | 420 | void *p; |
407 | void *pAligned; | 421 | void *pAligned; |
408 | size_t newSize; | 422 | size_t newSize; |
409 | UNUSED_VAR(pp) | ||
410 | 423 | ||
411 | /* also we can allocate additional dummy ALLOC_ALIGN_SIZE bytes after aligned | 424 | /* also we can allocate additional dummy ALLOC_ALIGN_SIZE bytes after aligned |
412 | block to prevent cache line sharing with another allocated blocks */ | 425 | block to prevent cache line sharing with another allocated blocks */ |
@@ -431,10 +444,9 @@ static void *SzAlignedAlloc(ISzAllocPtr pp, size_t size) | |||
431 | 444 | ||
432 | return pAligned; | 445 | return pAligned; |
433 | 446 | ||
434 | #else | 447 | #else |
435 | 448 | ||
436 | void *p; | 449 | void *p; |
437 | UNUSED_VAR(pp) | ||
438 | if (posix_memalign(&p, ALLOC_ALIGN_SIZE, size)) | 450 | if (posix_memalign(&p, ALLOC_ALIGN_SIZE, size)) |
439 | return NULL; | 451 | return NULL; |
440 | 452 | ||
@@ -443,19 +455,37 @@ static void *SzAlignedAlloc(ISzAllocPtr pp, size_t size) | |||
443 | 455 | ||
444 | return p; | 456 | return p; |
445 | 457 | ||
446 | #endif | 458 | #endif |
459 | } | ||
460 | |||
461 | |||
462 | void z7_AlignedFree(void *address) | ||
463 | { | ||
464 | #ifndef USE_posix_memalign | ||
465 | if (address) | ||
466 | MyFree(((void **)address)[-1]); | ||
467 | #else | ||
468 | free(address); | ||
469 | #endif | ||
470 | } | ||
471 | |||
472 | |||
473 | static void *SzAlignedAlloc(ISzAllocPtr pp, size_t size) | ||
474 | { | ||
475 | UNUSED_VAR(pp) | ||
476 | return z7_AlignedAlloc(size); | ||
447 | } | 477 | } |
448 | 478 | ||
449 | 479 | ||
450 | static void SzAlignedFree(ISzAllocPtr pp, void *address) | 480 | static void SzAlignedFree(ISzAllocPtr pp, void *address) |
451 | { | 481 | { |
452 | UNUSED_VAR(pp) | 482 | UNUSED_VAR(pp) |
453 | #ifndef USE_posix_memalign | 483 | #ifndef USE_posix_memalign |
454 | if (address) | 484 | if (address) |
455 | MyFree(((void **)address)[-1]); | 485 | MyFree(((void **)address)[-1]); |
456 | #else | 486 | #else |
457 | free(address); | 487 | free(address); |
458 | #endif | 488 | #endif |
459 | } | 489 | } |
460 | 490 | ||
461 | 491 | ||
@@ -463,16 +493,44 @@ const ISzAlloc g_AlignedAlloc = { SzAlignedAlloc, SzAlignedFree }; | |||
463 | 493 | ||
464 | 494 | ||
465 | 495 | ||
466 | #define MY_ALIGN_PTR_DOWN_1(p) MY_ALIGN_PTR_DOWN(p, sizeof(void *)) | ||
467 | |||
468 | /* we align ptr to support cases where CAlignOffsetAlloc::offset is not multiply of sizeof(void *) */ | 496 | /* we align ptr to support cases where CAlignOffsetAlloc::offset is not multiply of sizeof(void *) */ |
469 | #define REAL_BLOCK_PTR_VAR(p) ((void **)MY_ALIGN_PTR_DOWN_1(p))[-1] | 497 | #ifndef Z7_ALLOC_NO_OFFSET_ALLOCATOR |
470 | /* | 498 | #if 1 |
471 | #define REAL_BLOCK_PTR_VAR(p) ((void **)(p))[-1] | 499 | #define MY_ALIGN_PTR_DOWN_1(p) MY_ALIGN_PTR_DOWN(p, sizeof(void *)) |
472 | */ | 500 | #define REAL_BLOCK_PTR_VAR(p) ((void **)MY_ALIGN_PTR_DOWN_1(p))[-1] |
501 | #else | ||
502 | // we can use this simplified code, | ||
503 | // if (CAlignOffsetAlloc::offset == (k * sizeof(void *)) | ||
504 | #define REAL_BLOCK_PTR_VAR(p) (((void **)(p))[-1]) | ||
505 | #endif | ||
506 | #endif | ||
507 | |||
508 | |||
509 | #if 0 | ||
510 | #ifndef Z7_ALLOC_NO_OFFSET_ALLOCATOR | ||
511 | #include <stdio.h> | ||
512 | static void PrintPtr(const char *s, const void *p) | ||
513 | { | ||
514 | const Byte *p2 = (const Byte *)&p; | ||
515 | unsigned i; | ||
516 | printf("%s %p ", s, p); | ||
517 | for (i = sizeof(p); i != 0;) | ||
518 | { | ||
519 | i--; | ||
520 | printf("%02x", p2[i]); | ||
521 | } | ||
522 | printf("\n"); | ||
523 | } | ||
524 | #endif | ||
525 | #endif | ||
526 | |||
473 | 527 | ||
474 | static void *AlignOffsetAlloc_Alloc(ISzAllocPtr pp, size_t size) | 528 | static void *AlignOffsetAlloc_Alloc(ISzAllocPtr pp, size_t size) |
475 | { | 529 | { |
530 | #if defined(Z7_ALLOC_NO_OFFSET_ALLOCATOR) | ||
531 | UNUSED_VAR(pp) | ||
532 | return z7_AlignedAlloc(size); | ||
533 | #else | ||
476 | const CAlignOffsetAlloc *p = Z7_CONTAINER_FROM_VTBL_CONST(pp, CAlignOffsetAlloc, vt); | 534 | const CAlignOffsetAlloc *p = Z7_CONTAINER_FROM_VTBL_CONST(pp, CAlignOffsetAlloc, vt); |
477 | void *adr; | 535 | void *adr; |
478 | void *pAligned; | 536 | void *pAligned; |
@@ -501,6 +559,12 @@ static void *AlignOffsetAlloc_Alloc(ISzAllocPtr pp, size_t size) | |||
501 | pAligned = (char *)MY_ALIGN_PTR_DOWN((char *)adr + | 559 | pAligned = (char *)MY_ALIGN_PTR_DOWN((char *)adr + |
502 | alignSize - p->offset + extra + ADJUST_ALLOC_SIZE, alignSize) + p->offset; | 560 | alignSize - p->offset + extra + ADJUST_ALLOC_SIZE, alignSize) + p->offset; |
503 | 561 | ||
562 | #if 0 | ||
563 | printf("\nalignSize = %6x, offset=%6x, size=%8x \n", (unsigned)alignSize, (unsigned)p->offset, (unsigned)size); | ||
564 | PrintPtr("base", adr); | ||
565 | PrintPtr("alig", pAligned); | ||
566 | #endif | ||
567 | |||
504 | PrintLn(); | 568 | PrintLn(); |
505 | Print("- Aligned: "); | 569 | Print("- Aligned: "); |
506 | Print(" size="); PrintHex(size, 8); | 570 | Print(" size="); PrintHex(size, 8); |
@@ -512,11 +576,16 @@ static void *AlignOffsetAlloc_Alloc(ISzAllocPtr pp, size_t size) | |||
512 | REAL_BLOCK_PTR_VAR(pAligned) = adr; | 576 | REAL_BLOCK_PTR_VAR(pAligned) = adr; |
513 | 577 | ||
514 | return pAligned; | 578 | return pAligned; |
579 | #endif | ||
515 | } | 580 | } |
516 | 581 | ||
517 | 582 | ||
518 | static void AlignOffsetAlloc_Free(ISzAllocPtr pp, void *address) | 583 | static void AlignOffsetAlloc_Free(ISzAllocPtr pp, void *address) |
519 | { | 584 | { |
585 | #if defined(Z7_ALLOC_NO_OFFSET_ALLOCATOR) | ||
586 | UNUSED_VAR(pp) | ||
587 | z7_AlignedFree(address); | ||
588 | #else | ||
520 | if (address) | 589 | if (address) |
521 | { | 590 | { |
522 | const CAlignOffsetAlloc *p = Z7_CONTAINER_FROM_VTBL_CONST(pp, CAlignOffsetAlloc, vt); | 591 | const CAlignOffsetAlloc *p = Z7_CONTAINER_FROM_VTBL_CONST(pp, CAlignOffsetAlloc, vt); |
@@ -525,6 +594,7 @@ static void AlignOffsetAlloc_Free(ISzAllocPtr pp, void *address) | |||
525 | PrintLn(); | 594 | PrintLn(); |
526 | ISzAlloc_Free(p->baseAlloc, REAL_BLOCK_PTR_VAR(address)); | 595 | ISzAlloc_Free(p->baseAlloc, REAL_BLOCK_PTR_VAR(address)); |
527 | } | 596 | } |
597 | #endif | ||
528 | } | 598 | } |
529 | 599 | ||
530 | 600 | ||