Add a "dumpable" bit to the extent state.
Currently, this is unused (i.e. all extents are always marked dumpable). In the future, we'll begin using this functionality.
This commit is contained in:
parent
bbaa72422b
commit
d14bbf8d81
@ -93,6 +93,12 @@ extent_committed_get(const extent_t *extent) {
|
|||||||
EXTENT_BITS_COMMITTED_SHIFT);
|
EXTENT_BITS_COMMITTED_SHIFT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline bool
|
||||||
|
extent_dumpable_get(const extent_t *extent) {
|
||||||
|
return (bool)((extent->e_bits & EXTENT_BITS_DUMPABLE_MASK) >>
|
||||||
|
EXTENT_BITS_DUMPABLE_SHIFT);
|
||||||
|
}
|
||||||
|
|
||||||
static inline bool
|
static inline bool
|
||||||
extent_slab_get(const extent_t *extent) {
|
extent_slab_get(const extent_t *extent) {
|
||||||
return (bool)((extent->e_bits & EXTENT_BITS_SLAB_MASK) >>
|
return (bool)((extent->e_bits & EXTENT_BITS_SLAB_MASK) >>
|
||||||
@ -269,6 +275,12 @@ extent_committed_set(extent_t *extent, bool committed) {
|
|||||||
((uint64_t)committed << EXTENT_BITS_COMMITTED_SHIFT);
|
((uint64_t)committed << EXTENT_BITS_COMMITTED_SHIFT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
extent_dumpable_set(extent_t *extent, bool dumpable) {
|
||||||
|
extent->e_bits = (extent->e_bits & ~EXTENT_BITS_DUMPABLE_MASK) |
|
||||||
|
((uint64_t)dumpable << EXTENT_BITS_DUMPABLE_SHIFT);
|
||||||
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
extent_slab_set(extent_t *extent, bool slab) {
|
extent_slab_set(extent_t *extent, bool slab) {
|
||||||
extent->e_bits = (extent->e_bits & ~EXTENT_BITS_SLAB_MASK) |
|
extent->e_bits = (extent->e_bits & ~EXTENT_BITS_SLAB_MASK) |
|
||||||
@ -283,7 +295,7 @@ extent_prof_tctx_set(extent_t *extent, prof_tctx_t *tctx) {
|
|||||||
static inline void
|
static inline void
|
||||||
extent_init(extent_t *extent, arena_t *arena, void *addr, size_t size,
|
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 slab, szind_t szind, size_t sn, extent_state_t state, bool zeroed,
|
||||||
bool committed) {
|
bool committed, bool dumpable) {
|
||||||
assert(addr == PAGE_ADDR2BASE(addr) || !slab);
|
assert(addr == PAGE_ADDR2BASE(addr) || !slab);
|
||||||
|
|
||||||
extent_arena_set(extent, arena);
|
extent_arena_set(extent, arena);
|
||||||
@ -295,6 +307,7 @@ extent_init(extent_t *extent, arena_t *arena, void *addr, size_t size,
|
|||||||
extent_state_set(extent, state);
|
extent_state_set(extent, state);
|
||||||
extent_zeroed_set(extent, zeroed);
|
extent_zeroed_set(extent, zeroed);
|
||||||
extent_committed_set(extent, committed);
|
extent_committed_set(extent, committed);
|
||||||
|
extent_dumpable_set(extent, dumpable);
|
||||||
ql_elm_new(extent, ql_link);
|
ql_elm_new(extent, ql_link);
|
||||||
if (config_prof) {
|
if (config_prof) {
|
||||||
extent_prof_tctx_set(extent, NULL);
|
extent_prof_tctx_set(extent, NULL);
|
||||||
@ -312,6 +325,7 @@ extent_binit(extent_t *extent, void *addr, size_t bsize, size_t sn) {
|
|||||||
extent_state_set(extent, extent_state_active);
|
extent_state_set(extent, extent_state_active);
|
||||||
extent_zeroed_set(extent, true);
|
extent_zeroed_set(extent, true);
|
||||||
extent_committed_set(extent, true);
|
extent_committed_set(extent, true);
|
||||||
|
extent_dumpable_set(extent, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
|
@ -23,13 +23,14 @@ struct extent_s {
|
|||||||
* a: arena_ind
|
* a: arena_ind
|
||||||
* b: slab
|
* b: slab
|
||||||
* c: committed
|
* c: committed
|
||||||
|
* d: dumpable
|
||||||
* z: zeroed
|
* z: zeroed
|
||||||
* t: state
|
* t: state
|
||||||
* i: szind
|
* i: szind
|
||||||
* f: nfree
|
* f: nfree
|
||||||
* n: sn
|
* n: sn
|
||||||
*
|
*
|
||||||
* nnnnnnnn ... nnnnnfff fffffffi iiiiiiit tzcbaaaa aaaaaaaa
|
* nnnnnnnn ... nnnnffff ffffffii iiiiiitt zdcbaaaa aaaaaaaa
|
||||||
*
|
*
|
||||||
* arena_ind: Arena from which this extent came, or all 1 bits if
|
* arena_ind: Arena from which this extent came, or all 1 bits if
|
||||||
* unassociated.
|
* unassociated.
|
||||||
@ -44,6 +45,23 @@ struct extent_s {
|
|||||||
* as on a system that overcommits and satisfies physical
|
* as on a system that overcommits and satisfies physical
|
||||||
* memory needs on demand via soft page faults.
|
* memory needs on demand via soft page faults.
|
||||||
*
|
*
|
||||||
|
* dumpable: The dumpable flag indicates whether or not we've set the
|
||||||
|
* memory in question to be dumpable. Note that this
|
||||||
|
* interacts somewhat subtly with user-specified extent hooks,
|
||||||
|
* since we don't know if *they* are fiddling with
|
||||||
|
* dumpability (in which case, we don't want to undo whatever
|
||||||
|
* they're doing). To deal with this scenario, we:
|
||||||
|
* - Make dumpable false only for memory allocated with the
|
||||||
|
* default hooks.
|
||||||
|
* - Only allow memory to go from non-dumpable to dumpable,
|
||||||
|
* and only once.
|
||||||
|
* - Never make the OS call to allow dumping when the
|
||||||
|
* dumpable bit is already set.
|
||||||
|
* These three constraints mean that we will never
|
||||||
|
* accidentally dump user memory that the user meant to set
|
||||||
|
* nondumpable with their extent hooks.
|
||||||
|
*
|
||||||
|
*
|
||||||
* zeroed: The zeroed flag is used by extent recycling code to track
|
* zeroed: The zeroed flag is used by extent recycling code to track
|
||||||
* whether memory is zero-filled.
|
* whether memory is zero-filled.
|
||||||
*
|
*
|
||||||
@ -80,25 +98,29 @@ struct extent_s {
|
|||||||
#define EXTENT_BITS_COMMITTED_MASK \
|
#define EXTENT_BITS_COMMITTED_MASK \
|
||||||
((uint64_t)0x1U << EXTENT_BITS_COMMITTED_SHIFT)
|
((uint64_t)0x1U << EXTENT_BITS_COMMITTED_SHIFT)
|
||||||
|
|
||||||
#define EXTENT_BITS_ZEROED_SHIFT (MALLOCX_ARENA_BITS + 2)
|
#define EXTENT_BITS_DUMPABLE_SHIFT (MALLOCX_ARENA_BITS + 2)
|
||||||
|
#define EXTENT_BITS_DUMPABLE_MASK \
|
||||||
|
((uint64_t)0x1U << EXTENT_BITS_DUMPABLE_SHIFT)
|
||||||
|
|
||||||
|
#define EXTENT_BITS_ZEROED_SHIFT (MALLOCX_ARENA_BITS + 3)
|
||||||
#define EXTENT_BITS_ZEROED_MASK \
|
#define EXTENT_BITS_ZEROED_MASK \
|
||||||
((uint64_t)0x1U << EXTENT_BITS_ZEROED_SHIFT)
|
((uint64_t)0x1U << EXTENT_BITS_ZEROED_SHIFT)
|
||||||
|
|
||||||
#define EXTENT_BITS_STATE_SHIFT (MALLOCX_ARENA_BITS + 3)
|
#define EXTENT_BITS_STATE_SHIFT (MALLOCX_ARENA_BITS + 4)
|
||||||
#define EXTENT_BITS_STATE_MASK \
|
#define EXTENT_BITS_STATE_MASK \
|
||||||
((uint64_t)0x3U << EXTENT_BITS_STATE_SHIFT)
|
((uint64_t)0x3U << EXTENT_BITS_STATE_SHIFT)
|
||||||
|
|
||||||
#define EXTENT_BITS_SZIND_SHIFT (MALLOCX_ARENA_BITS + 5)
|
#define EXTENT_BITS_SZIND_SHIFT (MALLOCX_ARENA_BITS + 6)
|
||||||
#define EXTENT_BITS_SZIND_MASK \
|
#define EXTENT_BITS_SZIND_MASK \
|
||||||
(((uint64_t)(1U << LG_CEIL_NSIZES) - 1) << EXTENT_BITS_SZIND_SHIFT)
|
(((uint64_t)(1U << LG_CEIL_NSIZES) - 1) << EXTENT_BITS_SZIND_SHIFT)
|
||||||
|
|
||||||
#define EXTENT_BITS_NFREE_SHIFT \
|
#define EXTENT_BITS_NFREE_SHIFT \
|
||||||
(MALLOCX_ARENA_BITS + 5 + LG_CEIL_NSIZES)
|
(MALLOCX_ARENA_BITS + 6 + LG_CEIL_NSIZES)
|
||||||
#define EXTENT_BITS_NFREE_MASK \
|
#define EXTENT_BITS_NFREE_MASK \
|
||||||
((uint64_t)((1U << (LG_SLAB_MAXREGS + 1)) - 1) << EXTENT_BITS_NFREE_SHIFT)
|
((uint64_t)((1U << (LG_SLAB_MAXREGS + 1)) - 1) << EXTENT_BITS_NFREE_SHIFT)
|
||||||
|
|
||||||
#define EXTENT_BITS_SN_SHIFT \
|
#define EXTENT_BITS_SN_SHIFT \
|
||||||
(MALLOCX_ARENA_BITS + 5 + LG_CEIL_NSIZES + (LG_SLAB_MAXREGS + 1))
|
(MALLOCX_ARENA_BITS + 6 + LG_CEIL_NSIZES + (LG_SLAB_MAXREGS + 1))
|
||||||
#define EXTENT_BITS_SN_MASK (UINT64_MAX << EXTENT_BITS_SN_SHIFT)
|
#define EXTENT_BITS_SN_MASK (UINT64_MAX << EXTENT_BITS_SN_SHIFT)
|
||||||
|
|
||||||
/* Pointer to the extent that this structure is responsible for. */
|
/* Pointer to the extent that this structure is responsible for. */
|
||||||
@ -128,7 +150,7 @@ struct extent_s {
|
|||||||
*/
|
*/
|
||||||
ql_elm(extent_t) ql_link;
|
ql_elm(extent_t) ql_link;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Linkage for per size class sn/address-ordered heaps, and
|
* Linkage for per size class sn/address-ordered heaps, and
|
||||||
* for extent_avail
|
* for extent_avail
|
||||||
*/
|
*/
|
||||||
|
19
src/extent.c
19
src/extent.c
@ -449,8 +449,10 @@ extents_alloc(tsdn_t *tsdn, arena_t *arena, extent_hooks_t **r_extent_hooks,
|
|||||||
witness_assert_depth_to_rank(tsdn_witness_tsdp_get(tsdn),
|
witness_assert_depth_to_rank(tsdn_witness_tsdp_get(tsdn),
|
||||||
WITNESS_RANK_CORE, 0);
|
WITNESS_RANK_CORE, 0);
|
||||||
|
|
||||||
return extent_recycle(tsdn, arena, r_extent_hooks, extents, new_addr,
|
extent_t *extent = extent_recycle(tsdn, arena, r_extent_hooks, extents,
|
||||||
size, pad, alignment, slab, szind, zero, commit, false);
|
new_addr, size, pad, alignment, slab, szind, zero, commit, false);
|
||||||
|
assert(extent == NULL || extent_dumpable_get(extent));
|
||||||
|
return extent;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -458,6 +460,7 @@ extents_dalloc(tsdn_t *tsdn, arena_t *arena, extent_hooks_t **r_extent_hooks,
|
|||||||
extents_t *extents, extent_t *extent) {
|
extents_t *extents, extent_t *extent) {
|
||||||
assert(extent_base_get(extent) != NULL);
|
assert(extent_base_get(extent) != NULL);
|
||||||
assert(extent_size_get(extent) != 0);
|
assert(extent_size_get(extent) != 0);
|
||||||
|
assert(extent_dumpable_get(extent));
|
||||||
witness_assert_depth_to_rank(tsdn_witness_tsdp_get(tsdn),
|
witness_assert_depth_to_rank(tsdn_witness_tsdp_get(tsdn),
|
||||||
WITNESS_RANK_CORE, 0);
|
WITNESS_RANK_CORE, 0);
|
||||||
|
|
||||||
@ -1207,11 +1210,12 @@ extent_grow_retained(tsdn_t *tsdn, arena_t *arena,
|
|||||||
|
|
||||||
extent_init(extent, arena, ptr, alloc_size, false, NSIZES,
|
extent_init(extent, arena, ptr, alloc_size, false, NSIZES,
|
||||||
arena_extent_sn_next(arena), extent_state_active, zeroed,
|
arena_extent_sn_next(arena), extent_state_active, zeroed,
|
||||||
committed);
|
committed, true);
|
||||||
if (ptr == NULL) {
|
if (ptr == NULL) {
|
||||||
extent_dalloc(tsdn, arena, extent);
|
extent_dalloc(tsdn, arena, extent);
|
||||||
goto label_err;
|
goto label_err;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (extent_register_no_gdump_add(tsdn, extent)) {
|
if (extent_register_no_gdump_add(tsdn, extent)) {
|
||||||
extents_leak(tsdn, arena, r_extent_hooks,
|
extents_leak(tsdn, arena, r_extent_hooks,
|
||||||
&arena->extents_retained, extent, true);
|
&arena->extents_retained, extent, true);
|
||||||
@ -1374,7 +1378,8 @@ extent_alloc_wrapper_hard(tsdn_t *tsdn, arena_t *arena,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
extent_init(extent, arena, addr, esize, slab, szind,
|
extent_init(extent, arena, addr, esize, slab, szind,
|
||||||
arena_extent_sn_next(arena), extent_state_active, zero, commit);
|
arena_extent_sn_next(arena), extent_state_active, zero, commit,
|
||||||
|
true);
|
||||||
if (pad != 0) {
|
if (pad != 0) {
|
||||||
extent_addr_randomize(tsdn, extent, alignment);
|
extent_addr_randomize(tsdn, extent, alignment);
|
||||||
}
|
}
|
||||||
@ -1412,6 +1417,7 @@ extent_alloc_wrapper(tsdn_t *tsdn, arena_t *arena,
|
|||||||
new_addr, size, pad, alignment, slab, szind, zero, commit);
|
new_addr, size, pad, alignment, slab, szind, zero, commit);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
assert(extent == NULL || extent_dumpable_get(extent));
|
||||||
return extent;
|
return extent;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1636,6 +1642,7 @@ extent_dalloc_wrapper_try(tsdn_t *tsdn, arena_t *arena,
|
|||||||
void
|
void
|
||||||
extent_dalloc_wrapper(tsdn_t *tsdn, arena_t *arena,
|
extent_dalloc_wrapper(tsdn_t *tsdn, arena_t *arena,
|
||||||
extent_hooks_t **r_extent_hooks, extent_t *extent) {
|
extent_hooks_t **r_extent_hooks, extent_t *extent) {
|
||||||
|
assert(extent_dumpable_get(extent));
|
||||||
witness_assert_depth_to_rank(tsdn_witness_tsdp_get(tsdn),
|
witness_assert_depth_to_rank(tsdn_witness_tsdp_get(tsdn),
|
||||||
WITNESS_RANK_CORE, 0);
|
WITNESS_RANK_CORE, 0);
|
||||||
|
|
||||||
@ -1926,7 +1933,7 @@ extent_split_impl(tsdn_t *tsdn, arena_t *arena,
|
|||||||
extent_init(trail, arena, (void *)((uintptr_t)extent_base_get(extent) +
|
extent_init(trail, arena, (void *)((uintptr_t)extent_base_get(extent) +
|
||||||
size_a), size_b, slab_b, szind_b, extent_sn_get(extent),
|
size_a), size_b, slab_b, szind_b, extent_sn_get(extent),
|
||||||
extent_state_get(extent), extent_zeroed_get(extent),
|
extent_state_get(extent), extent_zeroed_get(extent),
|
||||||
extent_committed_get(extent));
|
extent_committed_get(extent), extent_dumpable_get(extent));
|
||||||
|
|
||||||
rtree_ctx_t rtree_ctx_fallback;
|
rtree_ctx_t rtree_ctx_fallback;
|
||||||
rtree_ctx_t *rtree_ctx = tsdn_rtree_ctx(tsdn, &rtree_ctx_fallback);
|
rtree_ctx_t *rtree_ctx = tsdn_rtree_ctx(tsdn, &rtree_ctx_fallback);
|
||||||
@ -1937,7 +1944,7 @@ extent_split_impl(tsdn_t *tsdn, arena_t *arena,
|
|||||||
extent_init(&lead, arena, extent_addr_get(extent), size_a,
|
extent_init(&lead, arena, extent_addr_get(extent), size_a,
|
||||||
slab_a, szind_a, extent_sn_get(extent),
|
slab_a, szind_a, extent_sn_get(extent),
|
||||||
extent_state_get(extent), extent_zeroed_get(extent),
|
extent_state_get(extent), extent_zeroed_get(extent),
|
||||||
extent_committed_get(extent));
|
extent_committed_get(extent), extent_dumpable_get(extent));
|
||||||
|
|
||||||
extent_rtree_leaf_elms_lookup(tsdn, rtree_ctx, &lead, false,
|
extent_rtree_leaf_elms_lookup(tsdn, rtree_ctx, &lead, false,
|
||||||
true, &lead_elm_a, &lead_elm_b);
|
true, &lead_elm_a, &lead_elm_b);
|
||||||
|
@ -156,7 +156,7 @@ extent_alloc_dss(tsdn_t *tsdn, arena_t *arena, void *new_addr, size_t size,
|
|||||||
extent_init(gap, arena, gap_addr_page,
|
extent_init(gap, arena, gap_addr_page,
|
||||||
gap_size_page, false, NSIZES,
|
gap_size_page, false, NSIZES,
|
||||||
arena_extent_sn_next(arena),
|
arena_extent_sn_next(arena),
|
||||||
extent_state_active, false, true);
|
extent_state_active, false, true, true);
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* Compute the address just past the end of the desired
|
* Compute the address just past the end of the desired
|
||||||
@ -199,7 +199,8 @@ extent_alloc_dss(tsdn_t *tsdn, arena_t *arena, void *new_addr, size_t size,
|
|||||||
|
|
||||||
extent_init(&extent, arena, ret, size,
|
extent_init(&extent, arena, ret, size,
|
||||||
size, false, NSIZES,
|
size, false, NSIZES,
|
||||||
extent_state_active, false, true);
|
extent_state_active, false, true,
|
||||||
|
true);
|
||||||
if (extent_purge_forced_wrapper(tsdn,
|
if (extent_purge_forced_wrapper(tsdn,
|
||||||
arena, &extent_hooks, &extent, 0,
|
arena, &extent_hooks, &extent, 0,
|
||||||
size)) {
|
size)) {
|
||||||
|
@ -87,9 +87,9 @@ TEST_BEGIN(test_rtree_extrema) {
|
|||||||
extent_t extent_a, extent_b;
|
extent_t extent_a, extent_b;
|
||||||
extent_init(&extent_a, NULL, NULL, LARGE_MINCLASS, false,
|
extent_init(&extent_a, NULL, NULL, LARGE_MINCLASS, false,
|
||||||
sz_size2index(LARGE_MINCLASS), 0, extent_state_active, false,
|
sz_size2index(LARGE_MINCLASS), 0, extent_state_active, false,
|
||||||
false);
|
false, true);
|
||||||
extent_init(&extent_b, NULL, NULL, 0, false, NSIZES, 0,
|
extent_init(&extent_b, NULL, NULL, 0, false, NSIZES, 0,
|
||||||
extent_state_active, false, false);
|
extent_state_active, false, false, true);
|
||||||
|
|
||||||
tsdn_t *tsdn = tsdn_fetch();
|
tsdn_t *tsdn = tsdn_fetch();
|
||||||
|
|
||||||
@ -126,7 +126,7 @@ TEST_BEGIN(test_rtree_bits) {
|
|||||||
|
|
||||||
extent_t extent;
|
extent_t extent;
|
||||||
extent_init(&extent, NULL, NULL, 0, false, NSIZES, 0,
|
extent_init(&extent, NULL, NULL, 0, false, NSIZES, 0,
|
||||||
extent_state_active, false, false);
|
extent_state_active, false, false, true);
|
||||||
|
|
||||||
rtree_t *rtree = &test_rtree;
|
rtree_t *rtree = &test_rtree;
|
||||||
rtree_ctx_t rtree_ctx;
|
rtree_ctx_t rtree_ctx;
|
||||||
@ -167,7 +167,7 @@ TEST_BEGIN(test_rtree_random) {
|
|||||||
|
|
||||||
extent_t extent;
|
extent_t extent;
|
||||||
extent_init(&extent, NULL, NULL, 0, false, NSIZES, 0,
|
extent_init(&extent, NULL, NULL, 0, false, NSIZES, 0,
|
||||||
extent_state_active, false, false);
|
extent_state_active, false, false, true);
|
||||||
|
|
||||||
assert_false(rtree_new(rtree, false), "Unexpected rtree_new() failure");
|
assert_false(rtree_new(rtree, false), "Unexpected rtree_new() failure");
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@ TEST_BEGIN(test_arena_slab_regind) {
|
|||||||
const arena_bin_info_t *bin_info = &arena_bin_info[binind];
|
const arena_bin_info_t *bin_info = &arena_bin_info[binind];
|
||||||
extent_init(&slab, NULL, mallocx(bin_info->slab_size,
|
extent_init(&slab, NULL, mallocx(bin_info->slab_size,
|
||||||
MALLOCX_LG_ALIGN(LG_PAGE)), bin_info->slab_size, true,
|
MALLOCX_LG_ALIGN(LG_PAGE)), bin_info->slab_size, true,
|
||||||
binind, 0, extent_state_active, false, true);
|
binind, 0, extent_state_active, false, true, true);
|
||||||
assert_ptr_not_null(extent_addr_get(&slab),
|
assert_ptr_not_null(extent_addr_get(&slab),
|
||||||
"Unexpected malloc() failure");
|
"Unexpected malloc() failure");
|
||||||
for (regind = 0; regind < bin_info->nregs; regind++) {
|
for (regind = 0; regind < bin_info->nregs; regind++) {
|
||||||
|
Loading…
Reference in New Issue
Block a user