2019-05-22 20:15:35 +00:00
|
|
|
/*
|
2020-07-20 16:35:17 +00:00
|
|
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
2019-05-22 20:15:35 +00:00
|
|
|
*
|
|
|
|
* 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
|
|
|
|
*
|
2020-07-20 16:35:17 +00:00
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
2019-05-22 20:15:35 +00:00
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include <atomic>
|
|
|
|
#include <cassert>
|
|
|
|
#include <cstdint>
|
|
|
|
#include <system_error>
|
|
|
|
|
|
|
|
#include <folly/portability/SysMman.h>
|
|
|
|
#include <folly/portability/Unistd.h>
|
|
|
|
|
|
|
|
namespace folly {
|
|
|
|
namespace detail {
|
|
|
|
|
|
|
|
class MMapAlloc {
|
|
|
|
private:
|
|
|
|
size_t computeSize(size_t size) {
|
|
|
|
long pagesize = sysconf(_SC_PAGESIZE);
|
|
|
|
size_t mmapLength = ((size - 1) & ~(pagesize - 1)) + pagesize;
|
|
|
|
assert(size <= mmapLength && mmapLength < size + pagesize);
|
|
|
|
assert((mmapLength % pagesize) == 0);
|
|
|
|
return mmapLength;
|
|
|
|
}
|
|
|
|
|
|
|
|
public:
|
|
|
|
void* allocate(size_t size) {
|
|
|
|
auto len = computeSize(size);
|
|
|
|
|
|
|
|
int extraflags = 0;
|
|
|
|
#if defined(MAP_POPULATE)
|
|
|
|
extraflags |= MAP_POPULATE;
|
|
|
|
#endif
|
|
|
|
// MAP_HUGETLB is a perf win, but requires cooperation from the
|
|
|
|
// deployment environment (and a change to computeSize()).
|
|
|
|
void* mem = static_cast<void*>(mmap(
|
|
|
|
nullptr,
|
|
|
|
len,
|
|
|
|
PROT_READ | PROT_WRITE,
|
|
|
|
MAP_PRIVATE | MAP_ANONYMOUS | extraflags,
|
|
|
|
-1,
|
|
|
|
0));
|
|
|
|
if (mem == reinterpret_cast<void*>(-1)) {
|
|
|
|
throw std::system_error(errno, std::system_category());
|
|
|
|
}
|
|
|
|
#if !defined(MAP_POPULATE) && defined(MADV_WILLNEED)
|
|
|
|
madvise(mem, size, MADV_WILLNEED);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return mem;
|
|
|
|
}
|
|
|
|
|
|
|
|
void deallocate(void* p, size_t size) {
|
|
|
|
auto len = computeSize(size);
|
|
|
|
munmap(p, len);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
template <typename Allocator>
|
|
|
|
struct GivesZeroFilledMemory : public std::false_type {};
|
|
|
|
|
|
|
|
template <>
|
|
|
|
struct GivesZeroFilledMemory<MMapAlloc> : public std::true_type {};
|
|
|
|
|
|
|
|
} // namespace detail
|
|
|
|
} // namespace folly
|