aboutsummaryrefslogtreecommitdiff
path: root/C/Alloc.c
diff options
context:
space:
mode:
Diffstat (limited to 'C/Alloc.c')
-rw-r--r--C/Alloc.c174
1 files changed, 122 insertions, 52 deletions
diff --git a/C/Alloc.c b/C/Alloc.c
index d841bf2..63e1a12 100644
--- a/C/Alloc.c
+++ b/C/Alloc.c
@@ -1,5 +1,5 @@
1/* Alloc.c -- Memory allocation functions 1/* Alloc.c -- Memory allocation functions
22023-04-02 : Igor Pavlov : Public domain */ 22024-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
16typedef 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
254extern 255extern
@@ -258,19 +259,23 @@ typedef SIZE_T (WINAPI *Func_GetLargePageMinimum)(VOID);
258 259
259void SetLargePageSize(void) 260void SetLargePageSize(void)
260{ 261{
261 #ifdef Z7_LARGE_PAGES
262 SIZE_T size; 262 SIZE_T size;
263#ifdef Z7_USE_DYN_GetLargePageMinimum
264Z7_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 };
328const ISzAlloc g_BigAlloc = { SzBigAlloc, SzBigFree }; 333const 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)))) 351typedef
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
402static void *SzAlignedAlloc(ISzAllocPtr pp, size_t size) 416void *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
462void 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
473static void *SzAlignedAlloc(ISzAllocPtr pp, size_t size)
474{
475 UNUSED_VAR(pp)
476 return z7_AlignedAlloc(size);
447} 477}
448 478
449 479
450static void SzAlignedFree(ISzAllocPtr pp, void *address) 480static 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>
512static 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
474static void *AlignOffsetAlloc_Alloc(ISzAllocPtr pp, size_t size) 528static 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
518static void AlignOffsetAlloc_Free(ISzAllocPtr pp, void *address) 583static 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