Disallow merge across mmap regions to preserve SN / first-fit.
Check the is_head state before merging two extents. Disallow the merge if it's crossing two separate mmap regions. This enforces first-fit (by not losing the SN) at a very small cost.
This commit is contained in:
parent
7014f81e17
commit
ca1f082251
32
src/ehooks.c
32
src/ehooks.c
@ -201,17 +201,6 @@ ehooks_same_sn(tsdn_t *tsdn, void *addr_a, void *addr_b) {
|
|||||||
static bool
|
static bool
|
||||||
ehooks_no_merge_heads(tsdn_t *tsdn, void *addr_a, bool head_a, void *addr_b,
|
ehooks_no_merge_heads(tsdn_t *tsdn, void *addr_a, bool head_a, void *addr_b,
|
||||||
bool head_b) {
|
bool head_b) {
|
||||||
/*
|
|
||||||
* When coalesce is not always allowed (Windows), only merge extents
|
|
||||||
* from the same VirtualAlloc region under opt.retain (in which case
|
|
||||||
* MEM_DECOMMIT is utilized for purging).
|
|
||||||
*/
|
|
||||||
if (maps_coalesce) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!opt_retain) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
/* If b is a head extent, disallow the cross-region merge. */
|
/* If b is a head extent, disallow the cross-region merge. */
|
||||||
if (head_b) {
|
if (head_b) {
|
||||||
/*
|
/*
|
||||||
@ -230,10 +219,27 @@ ehooks_no_merge_heads(tsdn_t *tsdn, void *addr_a, bool head_a, void *addr_b,
|
|||||||
bool
|
bool
|
||||||
ehooks_default_merge_impl(tsdn_t *tsdn, void *addr_a, bool head_a, void *addr_b,
|
ehooks_default_merge_impl(tsdn_t *tsdn, void *addr_a, bool head_a, void *addr_b,
|
||||||
bool head_b) {
|
bool head_b) {
|
||||||
if (ehooks_no_merge_heads(tsdn, addr_a, head_a, addr_b, head_b)) {
|
assert(addr_a < addr_b);
|
||||||
|
/*
|
||||||
|
* For non-DSS cases (first 2 branches) --
|
||||||
|
* a) W/o maps_coalesce, merge is not always allowed (Windows):
|
||||||
|
* 1) w/o retain, never merge (first branch below).
|
||||||
|
* 2) with retain, only merge extents from the same VirtualAlloc
|
||||||
|
* region (in which case MEM_DECOMMIT is utilized for purging).
|
||||||
|
*
|
||||||
|
* b) With maps_coalesce, it's always possible to merge.
|
||||||
|
* 1) w/o retain, always allow merge (only about dirty / muzzy).
|
||||||
|
* 2) with retain, to preserve the SN / first-fit, merge is still
|
||||||
|
* disallowed if b is a head extent, i.e. no merging across
|
||||||
|
* different mmap regions.
|
||||||
|
*
|
||||||
|
* a2) and b2) share the implementation (the no_merge_heads branch).
|
||||||
|
*/
|
||||||
|
if (!maps_coalesce && !opt_retain) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (!maps_coalesce && !opt_retain) {
|
if (opt_retain && ehooks_no_merge_heads(tsdn, addr_a, head_a, addr_b,
|
||||||
|
head_b)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (have_dss && !extent_dss_mergeable(addr_a, addr_b)) {
|
if (have_dss && !extent_dss_mergeable(addr_a, addr_b)) {
|
||||||
|
Loading…
Reference in New Issue
Block a user