Fix MemoryIdler::flushLocalMallocCaches() regression.
authorJason Evans <je@fb.com>
Fri, 4 Sep 2015 16:12:18 +0000 (09:12 -0700)
committerfacebook-github-bot-4 <folly-bot@fb.com>
Fri, 4 Sep 2015 16:20:16 +0000 (09:20 -0700)
Summary: Fix MemoryIdler::flushLocalMallocCaches() to use the correct type when querying
jemalloc's "opt.narenas" mallctl.

Reviewed By: @jobenber

Differential Revision: D2414309

folly/detail/MemoryIdler.cpp

index fcba197e5e01f21ceab7eaf3def1fb3feee4e82a..07ec2fbb9b1a218a2a61e0e7db72d15e40ff81f4 100644 (file)
@@ -34,14 +34,14 @@ AtomicStruct<std::chrono::steady_clock::duration>
 MemoryIdler::defaultIdleTimeout(std::chrono::seconds(5));
 
 
-/// Calls mallctl, optionally reading and/or writing an unsigned value
-/// if in and/or out is non-null.  Logs on error
-static unsigned mallctlWrapper(const char* cmd, const unsigned* in,
-                               unsigned* out) {
-  size_t outLen = sizeof(unsigned);
+// Calls mallctl, optionally reading a value of type <T> if out is
+// non-null.  Logs on error.
+template <typename T>
+static int mallctlRead(const char* cmd, T* out) {
+  size_t outLen = sizeof(T);
   int err = mallctl(cmd,
                     out, out ? &outLen : nullptr,
-                    const_cast<unsigned*>(in), in ? sizeof(unsigned) : 0);
+                    nullptr, 0);
   if (err != 0) {
     FB_LOG_EVERY_MS(WARNING, 10000)
       << "mallctl " << cmd << ": " << strerror(err) << " (" << err << ")";
@@ -49,6 +49,11 @@ static unsigned mallctlWrapper(const char* cmd, const unsigned* in,
   return err;
 }
 
+static int mallctlCall(const char* cmd) {
+  // Use <unsigned> rather than <void> to avoid sizeof(void).
+  return mallctlRead<unsigned>(cmd, nullptr);
+}
+
 void MemoryIdler::flushLocalMallocCaches() {
   if (usingJEMalloc()) {
     if (!mallctl || !mallctlnametomib || !mallctlbymib) {
@@ -57,7 +62,7 @@ void MemoryIdler::flushLocalMallocCaches() {
     }
 
     // "tcache.flush" was renamed to "thread.tcache.flush" in jemalloc 3
-    (void)mallctlWrapper("thread.tcache.flush", nullptr, nullptr);
+    mallctlCall("thread.tcache.flush");
 
     // By default jemalloc has 4 arenas per cpu, and then assigns each
     // thread to one of those arenas.  This means that in any service
@@ -69,12 +74,13 @@ void MemoryIdler::flushLocalMallocCaches() {
     // purging the arenas is counter-productive.  We use the heuristic
     // that if narenas <= 2 * num_cpus then we shouldn't do anything here,
     // which detects when the narenas has been reduced from the default
-    unsigned narenas, arenaForCurrent;
+    size_t narenas;
+    unsigned arenaForCurrent;
     size_t mib[3];
     size_t miblen = 3;
-    if (mallctlWrapper("opt.narenas", nullptr, &narenas) == 0 &&
+    if (mallctlRead<size_t>("opt.narenas", &narenas) == 0 &&
         narenas > 2 * CacheLocality::system().numCpus &&
-        mallctlWrapper("thread.arena", nullptr, &arenaForCurrent) == 0 &&
+        mallctlRead<unsigned>("thread.arena", &arenaForCurrent) == 0 &&
         mallctlnametomib("arena.0.purge", mib, &miblen) == 0) {
       mib[1] = size_t(arenaForCurrent);
       mallctlbymib(mib, miblen, nullptr, nullptr, nullptr, 0);