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:
@@ -343,10 +343,30 @@ extent_prof_alloc_time_set(extent_t *extent, nstime_t t) {
|
||||
nstime_copy(&extent->e_alloc_time, &t);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
extent_is_head_get(extent_t *extent) {
|
||||
if (maps_coalesce) {
|
||||
not_reached();
|
||||
}
|
||||
|
||||
return (bool)((extent->e_bits & EXTENT_BITS_IS_HEAD_MASK) >>
|
||||
EXTENT_BITS_IS_HEAD_SHIFT);
|
||||
}
|
||||
|
||||
static inline void
|
||||
extent_is_head_set(extent_t *extent, bool is_head) {
|
||||
if (maps_coalesce) {
|
||||
not_reached();
|
||||
}
|
||||
|
||||
extent->e_bits = (extent->e_bits & ~EXTENT_BITS_IS_HEAD_MASK) |
|
||||
((uint64_t)is_head << EXTENT_BITS_IS_HEAD_SHIFT);
|
||||
}
|
||||
|
||||
static inline void
|
||||
extent_init(extent_t *extent, arena_t *arena, void *addr, size_t size,
|
||||
bool slab, szind_t szind, size_t sn, extent_state_t state, bool zeroed,
|
||||
bool committed, bool dumpable) {
|
||||
bool committed, bool dumpable, extent_head_state_t is_head) {
|
||||
assert(addr == PAGE_ADDR2BASE(addr) || !slab);
|
||||
|
||||
extent_arena_set(extent, arena);
|
||||
@@ -360,6 +380,10 @@ extent_init(extent_t *extent, arena_t *arena, void *addr, size_t size,
|
||||
extent_committed_set(extent, committed);
|
||||
extent_dumpable_set(extent, dumpable);
|
||||
ql_elm_new(extent, ql_link);
|
||||
if (!maps_coalesce) {
|
||||
extent_is_head_set(extent, (is_head == EXTENT_IS_HEAD) ? true :
|
||||
false);
|
||||
}
|
||||
if (config_prof) {
|
||||
extent_prof_tctx_set(extent, NULL);
|
||||
}
|
||||
|
@@ -128,7 +128,11 @@ struct extent_s {
|
||||
#define EXTENT_BITS_BINSHARD_SHIFT (EXTENT_BITS_NFREE_WIDTH + EXTENT_BITS_NFREE_SHIFT)
|
||||
#define EXTENT_BITS_BINSHARD_MASK MASK(EXTENT_BITS_BINSHARD_WIDTH, EXTENT_BITS_BINSHARD_SHIFT)
|
||||
|
||||
#define EXTENT_BITS_SN_SHIFT (EXTENT_BITS_BINSHARD_WIDTH + EXTENT_BITS_BINSHARD_SHIFT)
|
||||
#define EXTENT_BITS_IS_HEAD_WIDTH 1
|
||||
#define EXTENT_BITS_IS_HEAD_SHIFT (EXTENT_BITS_BINSHARD_WIDTH + EXTENT_BITS_BINSHARD_SHIFT)
|
||||
#define EXTENT_BITS_IS_HEAD_MASK MASK(EXTENT_BITS_IS_HEAD_WIDTH, EXTENT_BITS_IS_HEAD_SHIFT)
|
||||
|
||||
#define EXTENT_BITS_SN_SHIFT (EXTENT_BITS_IS_HEAD_WIDTH + EXTENT_BITS_IS_HEAD_SHIFT)
|
||||
#define EXTENT_BITS_SN_MASK (UINT64_MAX << EXTENT_BITS_SN_SHIFT)
|
||||
|
||||
/* Pointer to the extent that this structure is responsible for. */
|
||||
|
@@ -15,4 +15,9 @@ typedef struct extent_util_stats_verbose_s extent_util_stats_verbose_t;
|
||||
*/
|
||||
#define LG_EXTENT_MAX_ACTIVE_FIT_DEFAULT 6
|
||||
|
||||
typedef enum {
|
||||
EXTENT_NOT_HEAD,
|
||||
EXTENT_IS_HEAD /* Only relevant for Windows && opt.retain. */
|
||||
} extent_head_state_t;
|
||||
|
||||
#endif /* JEMALLOC_INTERNAL_EXTENT_TYPES_H */
|
||||
|
Reference in New Issue
Block a user