diff options
author | Jason Evans <je@fb.com> | 2011-03-14 19:56:51 (GMT) |
---|---|---|
committer | Jason Evans <je@fb.com> | 2011-03-14 19:56:51 (GMT) |
commit | a8118233ec0369e00629fe853a5655c0dabf83d2 (patch) | |
tree | 94b0192522f7d337174d6cc7b7c43bf8f2c8a048 /jemalloc | |
parent | a7153a0d7d5f1c81edf4a8087353cc095819b78c (diff) | |
download | jemalloc-a8118233ec0369e00629fe853a5655c0dabf83d2.zip jemalloc-a8118233ec0369e00629fe853a5655c0dabf83d2.tar.gz jemalloc-a8118233ec0369e00629fe853a5655c0dabf83d2.tar.bz2 |
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.
Diffstat (limited to 'jemalloc')
-rw-r--r-- | jemalloc/src/tcache.c | 19 |
1 files changed, 19 insertions, 0 deletions
diff --git a/jemalloc/src/tcache.c b/jemalloc/src/tcache.c index cbbe7a1..e9b067d 100644 --- a/jemalloc/src/tcache.c +++ b/jemalloc/src/tcache.c @@ -58,6 +58,9 @@ tcache_bin_flush_small(tcache_bin_t *tbin, size_t binind, unsigned rem void *flush, *deferred, *ptr; unsigned i, nflush, ndeferred; bool first_pass; +#ifdef JEMALLOC_STATS + bool merged_stats = false; +#endif assert(binind < nbins); 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); #ifdef JEMALLOC_STATS if (arena == tcache->arena) { + assert(merged_stats == false); + merged_stats = true; bin->stats.nflushes++; bin->stats.nrequests += tbin->tstats.nrequests; tbin->tstats.nrequests = 0; @@ -119,6 +124,20 @@ tcache_bin_flush_small(tcache_bin_t *tbin, size_t binind, unsigned rem 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; if (tbin->ncached < tbin->low_water) |