aboutsummaryrefslogtreecommitdiff
path: root/C/Alloc.c
diff options
context:
space:
mode:
authorIgor Pavlov <87184205+ip7z@users.noreply.github.com>2023-06-21 00:00:00 +0000
committerIgor Pavlov <87184205+ip7z@users.noreply.github.com>2023-12-17 14:59:19 +0500
commit5b39dc76f1bc82f941d5c800ab9f34407a06b53a (patch)
treefe5e17420300b715021a76328444088d32047963 /C/Alloc.c
parent93be7d4abfd4233228f58ee1fbbcd76d91be66a4 (diff)
download7zip-5b39dc76f1bc82f941d5c800ab9f34407a06b53a.tar.gz
7zip-5b39dc76f1bc82f941d5c800ab9f34407a06b53a.tar.bz2
7zip-5b39dc76f1bc82f941d5c800ab9f34407a06b53a.zip
23.0123.01
Diffstat (limited to 'C/Alloc.c')
-rw-r--r--C/Alloc.c192
1 files changed, 132 insertions, 60 deletions
diff --git a/C/Alloc.c b/C/Alloc.c
index d1af76c..d841bf2 100644
--- a/C/Alloc.c
+++ b/C/Alloc.c
@@ -1,38 +1,54 @@
1/* Alloc.c -- Memory allocation functions 1/* Alloc.c -- Memory allocation functions
22021-07-13 : Igor Pavlov : Public domain */ 22023-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__)
16typedef 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>
21int g_allocCount = 0; 35static int g_allocCount = 0;
22int g_allocCountMid = 0; 36#ifdef _WIN32
23int g_allocCountBig = 0; 37static int g_allocCountMid = 0;
38static 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
33static void ConvertUInt64ToString(UInt64 val, char *s) 49static 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
80static void PrintLn() 96static 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
92static void PrintDec(UInt64 v, size_t align) 108static 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/*
156by 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
161in 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
131void *MyAlloc(size_t size) 168void *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
147void MyFree(void *address) 187void 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
194void *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
156void *MidAlloc(size_t size) 219void *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
166void MidFree(void *address) 237void 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)
183extern 254extern
184SIZE_T g_LargePageSize; 255SIZE_T g_LargePageSize;
185SIZE_T g_LargePageSize = 0; 256SIZE_T g_LargePageSize = 0;
186typedef SIZE_T (WINAPI *GetLargePageMinimumP)(VOID); 257typedef SIZE_T (WINAPI *Func_GetLargePageMinimum)(VOID);
187 258
188#endif // _7ZIP_LARGE_PAGES 259void SetLargePageSize(void)
189
190void 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
206void *BigAlloc(size_t size) 278void *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
234void BigFree(void *address) 309void 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
246static void *SzAlloc(ISzAllocPtr p, size_t size) { UNUSED_VAR(p); return MyAlloc(size); } 318static void *SzAlloc(ISzAllocPtr p, size_t size) { UNUSED_VAR(p) return MyAlloc(size); }
247static void SzFree(ISzAllocPtr p, void *address) { UNUSED_VAR(p); MyFree(address); } 319static void SzFree(ISzAllocPtr p, void *address) { UNUSED_VAR(p) MyFree(address); }
248const ISzAlloc g_Alloc = { SzAlloc, SzFree }; 320const ISzAlloc g_Alloc = { SzAlloc, SzFree };
249 321
250#ifdef _WIN32 322#ifdef _WIN32
251static void *SzMidAlloc(ISzAllocPtr p, size_t size) { UNUSED_VAR(p); return MidAlloc(size); } 323static void *SzMidAlloc(ISzAllocPtr p, size_t size) { UNUSED_VAR(p) return MidAlloc(size); }
252static void SzMidFree(ISzAllocPtr p, void *address) { UNUSED_VAR(p); MidFree(address); } 324static void SzMidFree(ISzAllocPtr p, void *address) { UNUSED_VAR(p) MidFree(address); }
253static void *SzBigAlloc(ISzAllocPtr p, size_t size) { UNUSED_VAR(p); return BigAlloc(size); } 325static void *SzBigAlloc(ISzAllocPtr p, size_t size) { UNUSED_VAR(p) return BigAlloc(size); }
254static void SzBigFree(ISzAllocPtr p, void *address) { UNUSED_VAR(p); BigFree(address); } 326static void SzBigFree(ISzAllocPtr p, void *address) { UNUSED_VAR(p) BigFree(address); }
255const ISzAlloc g_MidAlloc = { SzMidAlloc, SzMidFree }; 327const ISzAlloc g_MidAlloc = { SzMidAlloc, SzMidFree };
256const ISzAlloc g_BigAlloc = { SzBigAlloc, SzBigFree }; 328const 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
378static void SzAlignedFree(ISzAllocPtr pp, void *address) 450static 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
402static void *AlignOffsetAlloc_Alloc(ISzAllocPtr pp, size_t size) 474static 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();