Add MSVC support for FOLLY_FINAL and FOLLY_OVERRIDE
[folly.git] / folly / Malloc.cpp
1 /*
2  * Copyright 2015 Facebook, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *   http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <folly/Malloc.h>
18
19 #include <cstdint>
20
21 namespace folly {
22
23 // How do we determine that we're using jemalloc?
24 // In the hackiest way possible. We allocate memory using malloc() and see if
25 // the per-thread counter of allocated memory increases. This makes me feel
26 // dirty inside. Also note that this requires jemalloc to have been compiled
27 // with --enable-stats.
28 bool usingJEMallocSlow() {
29   // Some platforms (*cough* OSX *cough*) require weak symbol checks to be
30   // in the form if (mallctl != nullptr). Not if (mallctl) or if (!mallctl)
31   // (!!). http://goo.gl/xpmctm
32   if (mallocx == nullptr || rallocx == nullptr || xallocx == nullptr
33       || sallocx == nullptr || dallocx == nullptr || nallocx == nullptr
34       || mallctl == nullptr) {
35     return false;
36   }
37
38   // "volatile" because gcc optimizes out the reads from *counter, because
39   // it "knows" malloc doesn't modify global state...
40   /* nolint */ volatile uint64_t* counter;
41   size_t counterLen = sizeof(uint64_t*);
42
43   if (mallctl("thread.allocatedp", static_cast<void*>(&counter), &counterLen,
44               nullptr, 0) != 0) {
45     return false;
46   }
47
48   if (counterLen != sizeof(uint64_t*)) {
49     return false;
50   }
51
52   uint64_t origAllocated = *counter;
53
54   void* ptr = malloc(1);
55   if (!ptr) {
56     // wtf, failing to allocate 1 byte
57     return false;
58   }
59   free(ptr);
60
61   return (origAllocated != *counter);
62 }
63
64 }  // namespaces