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:
Qi Wang 2019-12-30 17:14:44 -08:00 committed by Qi Wang
parent 7014f81e17
commit ca1f082251

View File

@ -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)) {