Implement retain on Windows.
The VirtualAlloc and VirtualFree APIs are different because MEM_DECOMMIT cannot be used across multiple VirtualAlloc regions. To properly support decommit, only allow merge / split within the same region -- this is done by tracking the "is_head" state of extents and not merging cross-region. Add a new state is_head (only relevant for retain && !maps_coalesce), which is true for the first extent in each VirtualAlloc region. Determine if two extents can be merged based on the head state, and use serial numbers for sanity checks.
This commit is contained in:
@@ -279,8 +279,11 @@ extent_dalloc_unmap(extent_hooks_t *extent_hooks, void *addr, size_t size,
|
||||
if (!try_dalloc) {
|
||||
return true;
|
||||
}
|
||||
pages_unmap(addr, size);
|
||||
did_dalloc = true;
|
||||
if (!maps_coalesce && opt_retain) {
|
||||
return true;
|
||||
}
|
||||
pages_unmap(addr, size);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -304,7 +307,9 @@ TEST_BEGIN(test_arena_destroy_hooks_unmap) {
|
||||
unsigned nptrs;
|
||||
|
||||
extent_hooks_prep();
|
||||
try_decommit = false;
|
||||
if (maps_coalesce) {
|
||||
try_decommit = false;
|
||||
}
|
||||
memcpy(&hooks_orig, &hooks, sizeof(extent_hooks_t));
|
||||
memcpy(&hooks, &hooks_unmap, sizeof(extent_hooks_t));
|
||||
|
||||
|
@@ -87,9 +87,9 @@ TEST_BEGIN(test_rtree_extrema) {
|
||||
extent_t extent_a, extent_b;
|
||||
extent_init(&extent_a, NULL, NULL, SC_LARGE_MINCLASS, false,
|
||||
sz_size2index(SC_LARGE_MINCLASS), 0,
|
||||
extent_state_active, false, false, true);
|
||||
extent_state_active, false, false, true, EXTENT_NOT_HEAD);
|
||||
extent_init(&extent_b, NULL, NULL, 0, false, SC_NSIZES, 0,
|
||||
extent_state_active, false, false, true);
|
||||
extent_state_active, false, false, true, EXTENT_NOT_HEAD);
|
||||
|
||||
tsdn_t *tsdn = tsdn_fetch();
|
||||
|
||||
@@ -126,7 +126,7 @@ TEST_BEGIN(test_rtree_bits) {
|
||||
|
||||
extent_t extent;
|
||||
extent_init(&extent, NULL, NULL, 0, false, SC_NSIZES, 0,
|
||||
extent_state_active, false, false, true);
|
||||
extent_state_active, false, false, true, EXTENT_NOT_HEAD);
|
||||
|
||||
rtree_t *rtree = &test_rtree;
|
||||
rtree_ctx_t rtree_ctx;
|
||||
@@ -167,7 +167,7 @@ TEST_BEGIN(test_rtree_random) {
|
||||
|
||||
extent_t extent;
|
||||
extent_init(&extent, NULL, NULL, 0, false, SC_NSIZES, 0,
|
||||
extent_state_active, false, false, true);
|
||||
extent_state_active, false, false, true, EXTENT_NOT_HEAD);
|
||||
|
||||
assert_false(rtree_new(rtree, false), "Unexpected rtree_new() failure");
|
||||
|
||||
|
@@ -9,7 +9,8 @@ TEST_BEGIN(test_arena_slab_regind) {
|
||||
const bin_info_t *bin_info = &bin_infos[binind];
|
||||
extent_init(&slab, NULL, mallocx(bin_info->slab_size,
|
||||
MALLOCX_LG_ALIGN(LG_PAGE)), bin_info->slab_size, true,
|
||||
binind, 0, extent_state_active, false, true, true);
|
||||
binind, 0, extent_state_active, false, true, true,
|
||||
EXTENT_NOT_HEAD);
|
||||
assert_ptr_not_null(extent_addr_get(&slab),
|
||||
"Unexpected malloc() failure");
|
||||
for (regind = 0; regind < bin_info->nregs; regind++) {
|
||||
|
Reference in New Issue
Block a user