+++ /dev/null
-/*
- * 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
#define MALLOCX_ZERO (static_cast<int>(0x40))
#endif
-// If using fbstring from libstdc++, then just define stub code
-// here to typedef the fbstring type into the folly namespace.
+// If using fbstring from libstdc++ (see comment in FBString.h), then
+// just define stub code here to typedef the fbstring type into the
+// folly namespace.
// This provides backwards compatibility for code that explicitly
// includes and uses fbstring.
#if defined(_GLIBCXX_USE_FB) && !defined(_LIBSTDCXX_FBSTRING)
#define FOLLY_HAVE_MALLOC_H 1
#else
#include <folly/detail/Malloc.h> /* nolint */
-#include <folly/Portability.h>
#endif
// for malloc_usable_size
#include <cassert>
#include <cstddef>
+#include <cstdint>
#include <cstdlib>
#include <cstring>
namespace folly {
#endif
-bool usingJEMallocSlow();
+// Cannot depend on Portability.h when _LIBSTDCXX_FBSTRING.
+#ifdef __GNUC__
+#define FOLLY_MALLOC_NOINLINE __attribute__((__noinline__))
+#else
+#define FOLLY_MALLOC_NOINLINE
+#endif
/**
* Determine if we are using jemalloc or not.
*/
-inline bool usingJEMalloc() {
+inline bool usingJEMalloc() noexcept {
// Checking for rallocx != NULL is not sufficient; we may be in a dlopen()ed
// module that depends on libjemalloc, so rallocx is resolved, but the main
- // program might be using a different memory allocator. Look at the
- // implementation of usingJEMallocSlow() for the (hacky) details.
- static const bool result = usingJEMallocSlow();
+ // program might be using a different memory allocator.
+ // 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.
+ static const bool result = [] () FOLLY_MALLOC_NOINLINE noexcept {
+ // 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);
+ }();
+
return result;
}