Do not advance decay epoch when time goes backwards.

Instead, move the epoch backward in time.  Additionally, add
nstime_monotonic() and use it in debug builds to assert that time only
goes backward if nstime_update() is using a non-monotonic time source.
This commit is contained in:
Jason Evans
2016-10-10 22:15:10 -07:00
parent ee0c74b77a
commit 5f11fb7d43
6 changed files with 63 additions and 6 deletions

View File

@@ -693,10 +693,23 @@ arena_maybe_purge_decay(tsdn_t *tsdn, arena_t *arena)
return;
}
nstime_copy(&time, &arena->decay.epoch);
if (unlikely(nstime_update(&time))) {
/* Time went backwards. Force an epoch advance. */
nstime_copy(&time, &arena->decay.deadline);
nstime_init(&time, 0);
nstime_update(&time);
if (unlikely(!nstime_monotonic() && nstime_compare(&arena->decay.epoch,
&time) > 0)) {
/*
* Time went backwards. Move the epoch back in time, with the
* expectation that time typically flows forward for long enough
* periods of time that epochs complete. Unfortunately,
* this strategy is susceptible to clock jitter triggering
* premature epoch advances, but clock jitter estimation and
* compensation isn't feasible here because calls into this code
* are event-driven.
*/
nstime_copy(&arena->decay.epoch, &time);
} else {
/* Verify that time does not go backwards. */
assert(nstime_compare(&arena->decay.epoch, &time) <= 0);
}
if (arena_decay_deadline_reached(arena, &time))

View File

@@ -98,6 +98,7 @@ nstime_divide(const nstime_t *time, const nstime_t *divisor)
}
#ifdef _WIN32
# define NSTIME_MONOTONIC true
static void
nstime_get(nstime_t *time)
{
@@ -110,6 +111,7 @@ nstime_get(nstime_t *time)
nstime_init(time, ticks_100ns * 100);
}
#elif JEMALLOC_HAVE_CLOCK_MONOTONIC_RAW
# define NSTIME_MONOTONIC true
static void
nstime_get(nstime_t *time)
{
@@ -119,6 +121,7 @@ nstime_get(nstime_t *time)
nstime_init2(time, ts.tv_sec, ts.tv_nsec);
}
#elif JEMALLOC_HAVE_CLOCK_MONOTONIC
# define NSTIME_MONOTONIC true
static void
nstime_get(nstime_t *time)
{
@@ -128,6 +131,7 @@ nstime_get(nstime_t *time)
nstime_init2(time, ts.tv_sec, ts.tv_nsec);
}
#elif JEMALLOC_HAVE_MACH_ABSOLUTE_TIME
# define NSTIME_MONOTONIC true
static void
nstime_get(nstime_t *time)
{
@@ -135,6 +139,7 @@ nstime_get(nstime_t *time)
nstime_init(time, mach_absolute_time());
}
#else
# define NSTIME_MONOTONIC false
static void
nstime_get(nstime_t *time)
{
@@ -145,6 +150,23 @@ nstime_get(nstime_t *time)
}
#endif
#ifdef JEMALLOC_JET
#undef nstime_monotonic
#define nstime_monotonic JEMALLOC_N(n_nstime_monotonic)
#endif
bool
nstime_monotonic(void)
{
return (NSTIME_MONOTONIC);
#undef NSTIME_MONOTONIC
}
#ifdef JEMALLOC_JET
#undef nstime_monotonic
#define nstime_monotonic JEMALLOC_N(nstime_monotonic)
nstime_monotonic_t *nstime_monotonic = JEMALLOC_N(n_nstime_monotonic);
#endif
#ifdef JEMALLOC_JET
#undef nstime_update
#define nstime_update JEMALLOC_N(n_nstime_update)