77fa735f4c39281cf3589bd08e06c340497d41af
[folly.git] / folly / detail / AtomicUnorderedMapUtils.h
1 #pragma once
2
3 #include <atomic>
4 #include <stdint.h>
5
6 #include <folly/portability/SysMman.h>
7 #include <folly/portability/Unistd.h>
8
9 namespace folly { namespace detail {
10
11 class MMapAlloc {
12  private:
13   size_t computeSize(size_t size) {
14     long pagesize = sysconf(_SC_PAGESIZE);
15     size_t mmapLength = ((size - 1) & ~(pagesize - 1)) + pagesize;
16     assert(size <= mmapLength && mmapLength < size + pagesize);
17     assert((mmapLength % pagesize) == 0);
18     return mmapLength;
19   }
20
21  public:
22   void* allocate(size_t size) {
23     auto len = computeSize(size);
24
25     // MAP_HUGETLB is a perf win, but requires cooperation from the
26     // deployment environment (and a change to computeSize()).
27     void* mem = static_cast<void*>(mmap(
28         nullptr,
29         len,
30         PROT_READ | PROT_WRITE,
31         MAP_PRIVATE | MAP_ANONYMOUS
32 #ifdef MAP_POPULATE
33             |
34             MAP_POPULATE
35 #endif
36         ,
37         -1,
38         0));
39     if (mem == reinterpret_cast<void*>(-1)) {
40       throw std::system_error(errno, std::system_category());
41     }
42 #if !defined(MAP_POPULATE) && defined(MADV_WILLNEED)
43     madvise(mem, size, MADV_WILLNEED);
44 #endif
45
46     return mem;
47   }
48
49   void deallocate(void* p, size_t size) {
50     auto len = computeSize(size);
51     munmap(p, len);
52   }
53 };
54
55 template<typename Allocator>
56 struct GivesZeroFilledMemory : public std::false_type {};
57
58 template<>
59 struct GivesZeroFilledMemory<MMapAlloc> : public std::true_type{};
60
61 }}