Summary:
For proper rounding, and also so memOpInChunks doesn't try to mlock / munlock /
madvise / munmap in chunks smaller than the page size.
Test Plan: memory_mapping_test
Reviewed By: lucian@fb.com
FB internal diff:
D1232153
MemoryMapping::MemoryMapping()
: mapStart_(nullptr)
, mapLength_(0)
MemoryMapping::MemoryMapping()
: mapStart_(nullptr)
, mapLength_(0)
-MemoryMapping::MemoryMapping(File file, off_t offset, off_t length)
+MemoryMapping::MemoryMapping(File file, off_t offset, off_t length,
+ off_t pageSize)
: mapStart_(nullptr)
, mapLength_(0)
: mapStart_(nullptr)
, mapLength_(0)
- init(std::move(file), offset, length, PROT_READ, false);
+ init(std::move(file), offset, length, pageSize, PROT_READ, false);
-MemoryMapping::MemoryMapping(const char* name, off_t offset, off_t length)
- : MemoryMapping(File(name), offset, length) { }
+MemoryMapping::MemoryMapping(const char* name, off_t offset, off_t length,
+ off_t pageSize)
+ : MemoryMapping(File(name), offset, length, pageSize) { }
-MemoryMapping::MemoryMapping(int fd, off_t offset, off_t length)
- : MemoryMapping(File(fd), offset, length) { }
+MemoryMapping::MemoryMapping(int fd, off_t offset, off_t length,
+ off_t pageSize)
+ : MemoryMapping(File(fd), offset, length, pageSize) { }
void MemoryMapping::init(File file,
off_t offset, off_t length,
void MemoryMapping::init(File file,
off_t offset, off_t length,
- off_t pageSize = sysconf(_SC_PAGESIZE);
+ if (pageSize == 0) {
+ pageSize = sysconf(_SC_PAGESIZE);
+ }
+ CHECK_GT(pageSize, 0);
+ CHECK_EQ(pageSize & (pageSize - 1), 0); // power of two
// Round down the start of the mapped region
size_t skipStart = offset % pageSize;
// Round down the start of the mapped region
size_t skipStart = offset % pageSize;
-off_t memOpChunkSize(off_t length) {
+off_t memOpChunkSize(off_t length, off_t pageSize) {
off_t chunkSize = length;
if (FLAGS_mlock_chunk_size <= 0) {
return chunkSize;
}
chunkSize = FLAGS_mlock_chunk_size;
off_t chunkSize = length;
if (FLAGS_mlock_chunk_size <= 0) {
return chunkSize;
}
chunkSize = FLAGS_mlock_chunk_size;
- off_t pageSize = sysconf(_SC_PAGESIZE);
off_t r = chunkSize % pageSize;
if (r) {
chunkSize += (pageSize - r);
off_t r = chunkSize % pageSize;
if (r) {
chunkSize += (pageSize - r);
* - failure: false + amountSucceeded == nr bytes on which op succeeded.
*/
bool memOpInChunks(std::function<int(void*, size_t)> op,
* - failure: false + amountSucceeded == nr bytes on which op succeeded.
*/
bool memOpInChunks(std::function<int(void*, size_t)> op,
- void* mem, size_t bufSize,
+ void* mem, size_t bufSize, off_t pageSize,
size_t& amountSucceeded) {
// unmap/mlock/munlock take a kernel semaphore and block other threads from
// doing other memory operations. If the size of the buffer is big the
size_t& amountSucceeded) {
// unmap/mlock/munlock take a kernel semaphore and block other threads from
// doing other memory operations. If the size of the buffer is big the
// chunks breaks the locking into intervals and lets other threads do memory
// operations of their own.
// chunks breaks the locking into intervals and lets other threads do memory
// operations of their own.
- size_t chunkSize = memOpChunkSize(bufSize);
+ size_t chunkSize = memOpChunkSize(bufSize, pageSize);
char* addr = static_cast<char*>(mem);
amountSucceeded = 0;
char* addr = static_cast<char*>(mem);
amountSucceeded = 0;
bool MemoryMapping::mlock(LockMode lock) {
size_t amountSucceeded = 0;
bool MemoryMapping::mlock(LockMode lock) {
size_t amountSucceeded = 0;
- locked_ = memOpInChunks(::mlock, mapStart_, mapLength_, amountSucceeded);
+ locked_ = memOpInChunks(::mlock, mapStart_, mapLength_, pageSize_,
+ amountSucceeded);
if (locked_) {
return true;
}
if (locked_) {
return true;
}
}
// only part of the buffer was mlocked, unlock it back
}
// only part of the buffer was mlocked, unlock it back
- if (!memOpInChunks(::munlock, mapStart_, amountSucceeded, amountSucceeded)) {
+ if (!memOpInChunks(::munlock, mapStart_, amountSucceeded, pageSize_,
+ amountSucceeded)) {
PLOG(WARNING) << "munlock()";
}
PLOG(WARNING) << "munlock()";
}
if (!locked_) return;
size_t amountSucceeded = 0;
if (!locked_) return;
size_t amountSucceeded = 0;
- if (!memOpInChunks(::munlock, mapStart_, mapLength_, amountSucceeded)) {
+ if (!memOpInChunks(::munlock, mapStart_, mapLength_, pageSize_,
+ amountSucceeded)) {
PLOG(WARNING) << "munlock()";
}
if (mapLength_ && dontneed &&
PLOG(WARNING) << "munlock()";
}
if (mapLength_ && dontneed &&
MemoryMapping::~MemoryMapping() {
if (mapLength_) {
size_t amountSucceeded = 0;
MemoryMapping::~MemoryMapping() {
if (mapLength_) {
size_t amountSucceeded = 0;
- if (!memOpInChunks(::munmap, mapStart_, mapLength_, amountSucceeded)) {
+ if (!memOpInChunks(::munmap, mapStart_, mapLength_, pageSize_,
+ amountSucceeded)) {
PLOG(FATAL) << folly::format(
"munmap({}) failed at {}",
mapLength_, amountSucceeded).str();
PLOG(FATAL) << folly::format(
"munmap({}) failed at {}",
mapLength_, amountSucceeded).str();
-WritableMemoryMapping::WritableMemoryMapping(File file, off_t offset, off_t length) {
- init(std::move(file), offset, length, PROT_READ | PROT_WRITE, true);
+WritableMemoryMapping::WritableMemoryMapping(
+ File file, off_t offset, off_t length, off_t pageSize) {
+ init(std::move(file), offset, length, pageSize, PROT_READ | PROT_WRITE, true);
*/
explicit MemoryMapping(File file,
off_t offset=0,
*/
explicit MemoryMapping(File file,
off_t offset=0,
+ off_t length=-1,
+ off_t pageSize=0);
explicit MemoryMapping(const char* name,
off_t offset=0,
explicit MemoryMapping(const char* name,
off_t offset=0,
+ off_t length=-1,
+ off_t pageSize=0);
explicit MemoryMapping(int fd,
off_t offset=0,
explicit MemoryMapping(int fd,
off_t offset=0,
+ off_t length=-1,
+ off_t pageSize=0);
virtual ~MemoryMapping();
virtual ~MemoryMapping();
void init(File file,
off_t offset, off_t length,
void init(File file,
off_t offset, off_t length,
int prot,
bool grow);
File file_;
void* mapStart_;
off_t mapLength_;
int prot,
bool grow);
File file_;
void* mapStart_;
off_t mapLength_;
bool locked_;
Range<uint8_t*> data_;
};
bool locked_;
Range<uint8_t*> data_;
};
public:
explicit WritableMemoryMapping(File file,
off_t offset = 0,
public:
explicit WritableMemoryMapping(File file,
off_t offset = 0,
+ off_t length = -1,
+ off_t pageSize = 0);
/**
* A bitwise cast of the mapped bytes as range of mutable values. Only
* intended for use with POD or in-place usable types.
/**
* A bitwise cast of the mapped bytes as range of mutable values. Only
* intended for use with POD or in-place usable types.