1 /*
2  * Copyright 2015-present 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 #pragma once
18 
19 #include <atomic>
20 #include <cassert>
21 #include <cstdint>
22 #include <system_error>
23 
24 #include <folly/portability/SysMman.h>
25 #include <folly/portability/Unistd.h>
26 
27 namespace folly {
28 namespace detail {
29 
30 class MMapAlloc {
31  private:
computeSize(size_t size)32   size_t computeSize(size_t size) {
33     long pagesize = sysconf(_SC_PAGESIZE);
34     size_t mmapLength = ((size - 1) & ~(pagesize - 1)) + pagesize;
35     assert(size <= mmapLength && mmapLength < size + pagesize);
36     assert((mmapLength % pagesize) == 0);
37     return mmapLength;
38   }
39 
40  public:
allocate(size_t size)41   void* allocate(size_t size) {
42     auto len = computeSize(size);
43 
44     int extraflags = 0;
45 #if defined(MAP_POPULATE)
46     extraflags |= MAP_POPULATE;
47 #endif
48     // MAP_HUGETLB is a perf win, but requires cooperation from the
49     // deployment environment (and a change to computeSize()).
50     void* mem = static_cast<void*>(mmap(
51         nullptr,
52         len,
53         PROT_READ | PROT_WRITE,
54         MAP_PRIVATE | MAP_ANONYMOUS | extraflags,
55         -1,
56         0));
57     if (mem == reinterpret_cast<void*>(-1)) {
58       throw std::system_error(errno, std::system_category());
59     }
60 #if !defined(MAP_POPULATE) && defined(MADV_WILLNEED)
61     madvise(mem, size, MADV_WILLNEED);
62 #endif
63 
64     return mem;
65   }
66 
deallocate(void * p,size_t size)67   void deallocate(void* p, size_t size) {
68     auto len = computeSize(size);
69     munmap(p, len);
70   }
71 };
72 
73 template <typename Allocator>
74 struct GivesZeroFilledMemory : public std::false_type {};
75 
76 template <>
77 struct GivesZeroFilledMemory<MMapAlloc> : public std::true_type {};
78 
79 } // namespace detail
80 } // namespace folly
81