blob: aa2175c7f165c945da569b6aa2ee8250cdbd8c84 [file] [log] [blame]
/*
* Copyright 2015 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <folly/Malloc.h>
#include <cstdint>
namespace folly {
// How do we determine that we're using jemalloc?
// In the hackiest way possible. We allocate memory using malloc() and see if
// the per-thread counter of allocated memory increases. This makes me feel
// dirty inside. Also note that this requires jemalloc to have been compiled
// with --enable-stats.
bool usingJEMallocSlow() {
// Some platforms (*cough* OSX *cough*) require weak symbol checks to be
// in the form if (mallctl != nullptr). Not if (mallctl) or if (!mallctl)
// (!!). http://goo.gl/xpmctm
if (mallocx == nullptr || rallocx == nullptr || xallocx == nullptr
|| sallocx == nullptr || dallocx == nullptr || nallocx == nullptr
|| mallctl == nullptr || mallctlnametomib == nullptr
|| mallctlbymib == nullptr) {
return false;
}
// "volatile" because gcc optimizes out the reads from *counter, because
// it "knows" malloc doesn't modify global state...
/* nolint */ volatile uint64_t* counter;
size_t counterLen = sizeof(uint64_t*);
if (mallctl("thread.allocatedp", static_cast<void*>(&counter), &counterLen,
nullptr, 0) != 0) {
return false;
}
if (counterLen != sizeof(uint64_t*)) {
return false;
}
uint64_t origAllocated = *counter;
void* ptr = malloc(1);
if (!ptr) {
// wtf, failing to allocate 1 byte
return false;
}
free(ptr);
return (origAllocated != *counter);
}
} // namespaces