Skip to content

Commit 1cf6384

Browse files
github-actions[bot]ericstjjkotas
authored
[release/9.0-staging] Revert "Remove custom allocator." (#118279)
* Revert "Remove custom allocator." This reverts commit c62bc5b. * Remove zlib custom allocator for linux. * Remove cookie check from windows custom zlib allocator * Remove zeroing of memory in zlib-allocator * Don't use custom allocator on x86 * Refine allocator condition * Update src/native/libs/System.IO.Compression.Native/CMakeLists.txt --------- Co-authored-by: Eric StJohn <[email protected]> Co-authored-by: Jan Kotas <[email protected]>
1 parent dda010a commit 1cf6384

File tree

4 files changed

+101
-0
lines changed

4 files changed

+101
-0
lines changed

src/native/libs/System.IO.Compression.Native/CMakeLists.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@ set(NATIVECOMPRESSION_SOURCES
1414
pal_zlib.c
1515
)
1616

17+
if (CLR_CMAKE_TARGET_WIN32 AND NOT CLR_CMAKE_TARGET_ARCH_I386)
18+
list(APPEND NATIVECOMPRESSION_SOURCES "zlib_allocator_win.c")
19+
endif()
20+
1721
if (NOT CLR_CMAKE_TARGET_BROWSER AND NOT CLR_CMAKE_TARGET_WASI)
1822

1923
if (CLR_CMAKE_USE_SYSTEM_BROTLI)

src/native/libs/System.IO.Compression.Native/pal_zlib.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@
88
#ifdef _WIN32
99
#define c_static_assert(e) static_assert((e),"")
1010
#include "../Common/pal_utilities.h"
11+
#if _WIN64
12+
#include <zlib_allocator.h>
13+
#endif
1114
#else
1215
#include "pal_utilities.h"
1316
#endif
@@ -39,6 +42,11 @@ static int32_t Init(PAL_ZStream* stream)
3942
{
4043
z_stream* zStream = (z_stream*)calloc(1, sizeof(z_stream));
4144

45+
#ifdef _WIN64
46+
zStream->zalloc = z_custom_calloc;
47+
zStream->zfree = z_custom_cfree;
48+
#endif
49+
4250
stream->internalState = zStream;
4351

4452
if (zStream != NULL)
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
#include <zconf.h> // voidpf
5+
6+
voidpf z_custom_calloc(voidpf opaque, unsigned items, unsigned size);
7+
8+
void z_custom_cfree(voidpf opaque, voidpf ptr);
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
#include <Windows.h>
5+
#include <heapapi.h>
6+
#include <intsafe.h>
7+
#include <crtdbg.h> /* _ASSERTE */
8+
9+
#include <zlib_allocator.h>
10+
11+
/* A custom allocator for zlib that uses a dedicated heap.
12+
This provides better performance and avoids fragmentation
13+
that can occur on Windows when using the default process heap.
14+
*/
15+
16+
// Gets the special heap we'll allocate from.
17+
HANDLE GetZlibHeap()
18+
{
19+
static HANDLE s_hPublishedHeap = NULL;
20+
21+
// If already initialized, return immediately.
22+
// We don't need a volatile read here since the publish is performed with release semantics.
23+
if (s_hPublishedHeap != NULL) { return s_hPublishedHeap; }
24+
25+
// Attempt to create a new heap. The heap will be dynamically sized.
26+
HANDLE hNewHeap = HeapCreate(0, 0, 0);
27+
28+
if (hNewHeap != NULL)
29+
{
30+
// We created a new heap. Attempt to publish it.
31+
if (InterlockedCompareExchangePointer(&s_hPublishedHeap, hNewHeap, NULL) != NULL)
32+
{
33+
HeapDestroy(hNewHeap); // Somebody published before us. Destroy our heap.
34+
hNewHeap = NULL; // Guard against accidental use later in the method.
35+
}
36+
}
37+
else
38+
{
39+
// If we can't create a new heap, fall back to the process default heap.
40+
InterlockedCompareExchangePointer(&s_hPublishedHeap, GetProcessHeap(), NULL);
41+
}
42+
43+
// Some thread - perhaps us, perhaps somebody else - published the heap. Return it.
44+
// We don't need a volatile read here since the publish is performed with release semantics.
45+
_ASSERTE(s_hPublishedHeap != NULL);
46+
return s_hPublishedHeap;
47+
}
48+
49+
voidpf z_custom_calloc(opaque, items, size)
50+
voidpf opaque;
51+
unsigned items;
52+
unsigned size;
53+
{
54+
55+
SIZE_T cbRequested;
56+
if (sizeof(items) + sizeof(size) <= sizeof(cbRequested))
57+
{
58+
// multiplication can't overflow; no need for safeint
59+
cbRequested = (SIZE_T)items * (SIZE_T)size;
60+
}
61+
else
62+
{
63+
// multiplication can overflow; go through safeint
64+
if (FAILED(SIZETMult(items, size, &cbRequested))) { return NULL; }
65+
}
66+
67+
return HeapAlloc(GetZlibHeap(), 0, cbRequested);
68+
}
69+
70+
void z_custom_cfree(opaque, ptr)
71+
voidpf opaque;
72+
voidpf ptr;
73+
{
74+
if (ptr == NULL) { return; } // ok to free nullptr
75+
76+
if (!HeapFree(GetZlibHeap(), 0, ptr)) { goto Fail; }
77+
return;
78+
79+
Fail:
80+
__fastfail(FAST_FAIL_HEAP_METADATA_CORRUPTION);
81+
}

0 commit comments

Comments
 (0)