Fix npages during arena_decay_epoch_advance().

We do not lock extents while advancing epoch.  This change makes sure that we
only read npages from extents once in order to avoid any inconsistency.
This commit is contained in:
Qi Wang 2017-05-29 22:47:16 -07:00 committed by Qi Wang
parent 4f0963b883
commit bf6673a070

View File

@ -637,15 +637,14 @@ arena_decay_backlog_npages_limit(const arena_decay_t *decay) {
} }
static void static void
arena_decay_backlog_update_last(arena_decay_t *decay, extents_t *extents) { arena_decay_backlog_update_last(arena_decay_t *decay, size_t current_npages) {
size_t ndirty = extents_npages_get(extents); size_t npages_delta = (current_npages > decay->nunpurged) ?
size_t ndirty_delta = (ndirty > decay->nunpurged) ? ndirty - current_npages - decay->nunpurged : 0;
decay->nunpurged : 0; decay->backlog[SMOOTHSTEP_NSTEPS-1] = npages_delta;
decay->backlog[SMOOTHSTEP_NSTEPS-1] = ndirty_delta;
if (config_debug) { if (config_debug) {
if (ndirty > decay->ceil_npages) { if (current_npages > decay->ceil_npages) {
decay->ceil_npages = ndirty; decay->ceil_npages = current_npages;
} }
size_t npages_limit = arena_decay_backlog_npages_limit(decay); size_t npages_limit = arena_decay_backlog_npages_limit(decay);
assert(decay->ceil_npages >= npages_limit); assert(decay->ceil_npages >= npages_limit);
@ -656,8 +655,8 @@ arena_decay_backlog_update_last(arena_decay_t *decay, extents_t *extents) {
} }
static void static void
arena_decay_backlog_update(arena_decay_t *decay, extents_t *extents, arena_decay_backlog_update(arena_decay_t *decay, uint64_t nadvance_u64,
uint64_t nadvance_u64) { size_t current_npages) {
if (nadvance_u64 >= SMOOTHSTEP_NSTEPS) { if (nadvance_u64 >= SMOOTHSTEP_NSTEPS) {
memset(decay->backlog, 0, (SMOOTHSTEP_NSTEPS-1) * memset(decay->backlog, 0, (SMOOTHSTEP_NSTEPS-1) *
sizeof(size_t)); sizeof(size_t));
@ -674,7 +673,7 @@ arena_decay_backlog_update(arena_decay_t *decay, extents_t *extents,
} }
} }
arena_decay_backlog_update_last(decay, extents); arena_decay_backlog_update_last(decay, current_npages);
} }
static void static void
@ -687,8 +686,8 @@ arena_decay_try_purge(tsdn_t *tsdn, arena_t *arena, arena_decay_t *decay,
} }
static void static void
arena_decay_epoch_advance_helper(arena_decay_t *decay, extents_t *extents, arena_decay_epoch_advance_helper(arena_decay_t *decay, const nstime_t *time,
const nstime_t *time) { size_t current_npages) {
assert(arena_decay_deadline_reached(decay, time)); assert(arena_decay_deadline_reached(decay, time));
nstime_t delta; nstime_t delta;
@ -707,25 +706,20 @@ arena_decay_epoch_advance_helper(arena_decay_t *decay, extents_t *extents,
arena_decay_deadline_init(decay); arena_decay_deadline_init(decay);
/* Update the backlog. */ /* Update the backlog. */
arena_decay_backlog_update(decay, extents, nadvance_u64); arena_decay_backlog_update(decay, nadvance_u64, current_npages);
} }
static void static void
arena_decay_epoch_advance(tsdn_t *tsdn, arena_t *arena, arena_decay_t *decay, arena_decay_epoch_advance(tsdn_t *tsdn, arena_t *arena, arena_decay_t *decay,
extents_t *extents, const nstime_t *time, bool purge) { extents_t *extents, const nstime_t *time, bool purge) {
arena_decay_epoch_advance_helper(decay, extents, time);
size_t current_npages = extents_npages_get(extents); size_t current_npages = extents_npages_get(extents);
arena_decay_epoch_advance_helper(decay, time, current_npages);
size_t npages_limit = arena_decay_backlog_npages_limit(decay); size_t npages_limit = arena_decay_backlog_npages_limit(decay);
if (purge) { if (purge) {
arena_decay_try_purge(tsdn, arena, decay, extents, arena_decay_try_purge(tsdn, arena, decay, extents,
current_npages, npages_limit); current_npages, npages_limit);
} }
/*
* There may be concurrent ndirty fluctuation between the purge above
* and the nunpurged update below, but this is inconsequential to decay
* machinery correctness.
*/
decay->nunpurged = (npages_limit > current_npages) ? npages_limit : decay->nunpurged = (npages_limit > current_npages) ? npages_limit :
current_npages; current_npages;
} }