in folly/system/MemoryMapping.cpp [113:213]
void MemoryMapping::init(off_t offset, off_t length) {
const bool grow = options_.grow;
const bool anon = !file_;
CHECK(!(grow && anon));
off_t& pageSize = options_.pageSize;
struct stat st;
// On Linux, hugetlbfs file systems don't require ftruncate() to grow the
// file, and (on kernels before 2.6.24) don't even allow it. Also, the file
// size is always a multiple of the page size.
bool autoExtend = false;
if (!anon) {
// Stat the file
CHECK_ERR(fstat(file_.fd(), &st));
if (pageSize == 0) {
getDeviceOptions(st.st_dev, pageSize, autoExtend);
}
} else {
DCHECK(!file_);
DCHECK_EQ(offset, 0);
CHECK_EQ(pageSize, 0);
CHECK_GE(length, 0);
}
if (pageSize == 0) {
pageSize = off_t(sysconf(_SC_PAGESIZE));
}
CHECK_GT(pageSize, 0);
CHECK_EQ(pageSize & (pageSize - 1), 0); // power of two
CHECK_GE(offset, 0);
// Round down the start of the mapped region
off_t skipStart = offset % pageSize;
offset -= skipStart;
mapLength_ = length;
if (mapLength_ != -1) {
mapLength_ += skipStart;
// Round up the end of the mapped region
mapLength_ = (mapLength_ + pageSize - 1) / pageSize * pageSize;
}
off_t remaining = anon ? length : st.st_size - offset;
if (mapLength_ == -1) {
length = mapLength_ = remaining;
} else {
if (length > remaining) {
if (grow) {
if (!autoExtend) {
PCHECK(0 == ftruncate(file_.fd(), offset + length))
<< "ftruncate() failed, couldn't grow file to "
<< offset + length;
remaining = length;
} else {
// Extend mapping to multiple of page size, don't use ftruncate
remaining = mapLength_;
}
} else {
length = remaining;
}
}
if (mapLength_ > remaining) {
mapLength_ = remaining;
}
}
if (length == 0) {
mapLength_ = 0;
mapStart_ = nullptr;
} else {
int flags = options_.shared ? MAP_SHARED : MAP_PRIVATE;
if (anon) {
flags |= MAP_ANONYMOUS;
}
if (options_.prefault) {
flags |= mmap_flags::populate;
}
// The standard doesn't actually require PROT_NONE to be zero...
int prot = PROT_NONE;
if (options_.readable || options_.writable) {
prot =
((options_.readable ? PROT_READ : 0) |
(options_.writable ? PROT_WRITE : 0));
}
auto start = static_cast<unsigned char*>(mmap(
options_.address, size_t(mapLength_), prot, flags, file_.fd(), offset));
PCHECK(start != MAP_FAILED)
<< " offset=" << offset << " length=" << mapLength_;
mapStart_ = start;
data_.reset(start + skipStart, size_t(length));
}
}