summaryrefslogtreecommitdiffstats
path: root/jemalloc
diff options
context:
space:
mode:
authorJason Evans <je@fb.com>2011-03-14 19:56:51 (GMT)
committerJason Evans <je@fb.com>2011-03-14 19:56:51 (GMT)
commita8118233ec0369e00629fe853a5655c0dabf83d2 (patch)
tree94b0192522f7d337174d6cc7b7c43bf8f2c8a048 /jemalloc
parenta7153a0d7d5f1c81edf4a8087353cc095819b78c (diff)
downloadjemalloc-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.c19
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)