Fix a thread cache stats merging bug.

When a thread cache flushes objects to their arenas due to an abundance
of cached objects, it merges the allocation request count for the
associated size class, and increments a flush counter.  If none of the
flushed objects came from the thread's assigned arena, then the merging
wouldn't happen (though the counter would typically eventually be
merged), nor would the flush counter be incremented (a hard bug).  Fix
this via extra conditional code just after the flush loop.
This commit is contained in:
Jason Evans 2011-03-14 12:56:51 -07:00
parent a7153a0d7d
commit a8118233ec

View File

@ -58,6 +58,9 @@ tcache_bin_flush_small(tcache_bin_t *tbin, size_t binind, unsigned rem
void *flush, *deferred, *ptr; void *flush, *deferred, *ptr;
unsigned i, nflush, ndeferred; unsigned i, nflush, ndeferred;
bool first_pass; bool first_pass;
#ifdef JEMALLOC_STATS
bool merged_stats = false;
#endif
assert(binind < nbins); assert(binind < nbins);
assert(rem <= tbin->ncached); assert(rem <= tbin->ncached);
@ -82,6 +85,8 @@ tcache_bin_flush_small(tcache_bin_t *tbin, size_t binind, unsigned rem
malloc_mutex_lock(&bin->lock); malloc_mutex_lock(&bin->lock);
#ifdef JEMALLOC_STATS #ifdef JEMALLOC_STATS
if (arena == tcache->arena) { if (arena == tcache->arena) {
assert(merged_stats == false);
merged_stats = true;
bin->stats.nflushes++; bin->stats.nflushes++;
bin->stats.nrequests += tbin->tstats.nrequests; bin->stats.nrequests += tbin->tstats.nrequests;
tbin->tstats.nrequests = 0; tbin->tstats.nrequests = 0;
@ -119,6 +124,20 @@ tcache_bin_flush_small(tcache_bin_t *tbin, size_t binind, unsigned rem
first_pass = false; first_pass = false;
} }
} }
#ifdef JEMALLOC_STATS
if (merged_stats == false) {
/*
* The flush loop didn't happen to flush to this thread's
* arena, so the stats didn't get merged. Manually do so now.
*/
arena_bin_t *bin = &tcache->arena->bins[binind];
malloc_mutex_lock(&bin->lock);
bin->stats.nflushes++;
bin->stats.nrequests += tbin->tstats.nrequests;
tbin->tstats.nrequests = 0;
malloc_mutex_unlock(&bin->lock);
}
#endif
tbin->ncached = rem; tbin->ncached = rem;
if (tbin->ncached < tbin->low_water) if (tbin->ncached < tbin->low_water)