Commit 922f80e0 authored by Tudor Bosman's avatar Tudor Bosman Committed by Dave Watson

Optionally specify page size in MemoryMapping ctor

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
parent d4738210
...@@ -33,29 +33,40 @@ namespace folly { ...@@ -33,29 +33,40 @@ namespace folly {
MemoryMapping::MemoryMapping() MemoryMapping::MemoryMapping()
: mapStart_(nullptr) : mapStart_(nullptr)
, mapLength_(0) , mapLength_(0)
, pageSize_(0)
, locked_(false) { , locked_(false) {
} }
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) : mapStart_(nullptr)
, mapLength_(0) , mapLength_(0)
, pageSize_(0)
, locked_(false) { , locked_(false) {
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::MemoryMapping(const char* name, off_t offset, off_t length,
: MemoryMapping(File(name), offset, length) { } off_t pageSize)
: MemoryMapping(File(name), offset, length, pageSize) { }
MemoryMapping::MemoryMapping(int fd, off_t offset, off_t length) MemoryMapping::MemoryMapping(int fd, off_t offset, off_t length,
: MemoryMapping(File(fd), offset, length) { } off_t pageSize)
: MemoryMapping(File(fd), offset, length, pageSize) { }
void MemoryMapping::init(File file, void MemoryMapping::init(File file,
off_t offset, off_t length, off_t offset, off_t length,
off_t pageSize,
int prot, int prot,
bool grow) { bool grow) {
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
CHECK_GE(offset, 0); CHECK_GE(offset, 0);
pageSize_ = pageSize;
// Round down the start of the mapped region // Round down the start of the mapped region
size_t skipStart = offset % pageSize; size_t skipStart = offset % pageSize;
...@@ -105,14 +116,13 @@ void MemoryMapping::init(File file, ...@@ -105,14 +116,13 @@ void MemoryMapping::init(File file,
namespace { namespace {
off_t memOpChunkSize(off_t length) { off_t memOpChunkSize(off_t length, off_t pageSize) {
off_t chunkSize = length; off_t chunkSize = length;
if (FLAGS_mlock_chunk_size <= 0) { if (FLAGS_mlock_chunk_size <= 0) {
return chunkSize; return chunkSize;
} }
chunkSize = FLAGS_mlock_chunk_size; chunkSize = FLAGS_mlock_chunk_size;
off_t pageSize = sysconf(_SC_PAGESIZE);
off_t r = chunkSize % pageSize; off_t r = chunkSize % pageSize;
if (r) { if (r) {
chunkSize += (pageSize - r); chunkSize += (pageSize - r);
...@@ -128,7 +138,7 @@ off_t memOpChunkSize(off_t length) { ...@@ -128,7 +138,7 @@ off_t memOpChunkSize(off_t length) {
* - failure: false + amountSucceeded == nr bytes on which op succeeded. * - failure: false + amountSucceeded == nr bytes on which op succeeded.
*/ */
bool memOpInChunks(std::function<int(void*, size_t)> op, 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) { size_t& amountSucceeded) {
// unmap/mlock/munlock take a kernel semaphore and block other threads from // 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 // doing other memory operations. If the size of the buffer is big the
...@@ -137,7 +147,7 @@ bool memOpInChunks(std::function<int(void*, size_t)> op, ...@@ -137,7 +147,7 @@ bool memOpInChunks(std::function<int(void*, size_t)> op,
// chunks breaks the locking into intervals and lets other threads do memory // chunks breaks the locking into intervals and lets other threads do memory
// operations of their own. // operations of their own.
size_t chunkSize = memOpChunkSize(bufSize); size_t chunkSize = memOpChunkSize(bufSize, pageSize);
char* addr = static_cast<char*>(mem); char* addr = static_cast<char*>(mem);
amountSucceeded = 0; amountSucceeded = 0;
...@@ -157,7 +167,8 @@ bool memOpInChunks(std::function<int(void*, size_t)> op, ...@@ -157,7 +167,8 @@ bool memOpInChunks(std::function<int(void*, size_t)> op,
bool MemoryMapping::mlock(LockMode lock) { bool MemoryMapping::mlock(LockMode lock) {
size_t amountSucceeded = 0; size_t amountSucceeded = 0;
locked_ = memOpInChunks(::mlock, mapStart_, mapLength_, amountSucceeded); locked_ = memOpInChunks(::mlock, mapStart_, mapLength_, pageSize_,
amountSucceeded);
if (locked_) { if (locked_) {
return true; return true;
} }
...@@ -173,7 +184,8 @@ bool MemoryMapping::mlock(LockMode lock) { ...@@ -173,7 +184,8 @@ bool MemoryMapping::mlock(LockMode lock) {
} }
// 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()";
} }
...@@ -184,7 +196,8 @@ void MemoryMapping::munlock(bool dontneed) { ...@@ -184,7 +196,8 @@ void MemoryMapping::munlock(bool dontneed) {
if (!locked_) return; if (!locked_) return;
size_t amountSucceeded = 0; size_t amountSucceeded = 0;
if (!memOpInChunks(::munlock, mapStart_, mapLength_, amountSucceeded)) { if (!memOpInChunks(::munlock, mapStart_, mapLength_, pageSize_,
amountSucceeded)) {
PLOG(WARNING) << "munlock()"; PLOG(WARNING) << "munlock()";
} }
if (mapLength_ && dontneed && if (mapLength_ && dontneed &&
...@@ -201,7 +214,8 @@ void MemoryMapping::hintLinearScan() { ...@@ -201,7 +214,8 @@ void MemoryMapping::hintLinearScan() {
MemoryMapping::~MemoryMapping() { MemoryMapping::~MemoryMapping() {
if (mapLength_) { if (mapLength_) {
size_t amountSucceeded = 0; size_t amountSucceeded = 0;
if (!memOpInChunks(::munmap, mapStart_, mapLength_, amountSucceeded)) { if (!memOpInChunks(::munmap, mapStart_, mapLength_, pageSize_,
amountSucceeded)) {
PLOG(FATAL) << folly::format( PLOG(FATAL) << folly::format(
"munmap({}) failed at {}", "munmap({}) failed at {}",
mapLength_, amountSucceeded).str(); mapLength_, amountSucceeded).str();
...@@ -215,8 +229,9 @@ void MemoryMapping::advise(int advice) const { ...@@ -215,8 +229,9 @@ void MemoryMapping::advise(int advice) const {
} }
} }
WritableMemoryMapping::WritableMemoryMapping(File file, off_t offset, off_t length) { WritableMemoryMapping::WritableMemoryMapping(
init(std::move(file), offset, length, PROT_READ | PROT_WRITE, true); File file, off_t offset, off_t length, off_t pageSize) {
init(std::move(file), offset, length, pageSize, PROT_READ | PROT_WRITE, true);
} }
} // namespace folly } // namespace folly
...@@ -54,15 +54,18 @@ class MemoryMapping : boost::noncopyable { ...@@ -54,15 +54,18 @@ class MemoryMapping : boost::noncopyable {
*/ */
explicit MemoryMapping(File file, explicit MemoryMapping(File file,
off_t offset=0, off_t offset=0,
off_t length=-1); off_t length=-1,
off_t pageSize=0);
explicit MemoryMapping(const char* name, explicit MemoryMapping(const char* name,
off_t offset=0, off_t offset=0,
off_t length=-1); off_t length=-1,
off_t pageSize=0);
explicit MemoryMapping(int fd, explicit MemoryMapping(int fd,
off_t offset=0, off_t offset=0,
off_t length=-1); off_t length=-1,
off_t pageSize=0);
virtual ~MemoryMapping(); virtual ~MemoryMapping();
...@@ -126,12 +129,14 @@ class MemoryMapping : boost::noncopyable { ...@@ -126,12 +129,14 @@ class MemoryMapping : boost::noncopyable {
void init(File file, void init(File file,
off_t offset, off_t length, off_t offset, off_t length,
off_t pageSize,
int prot, int prot,
bool grow); bool grow);
File file_; File file_;
void* mapStart_; void* mapStart_;
off_t mapLength_; off_t mapLength_;
off_t pageSize_;
bool locked_; bool locked_;
Range<uint8_t*> data_; Range<uint8_t*> data_;
}; };
...@@ -145,7 +150,8 @@ class WritableMemoryMapping : public MemoryMapping { ...@@ -145,7 +150,8 @@ class WritableMemoryMapping : public MemoryMapping {
public: public:
explicit WritableMemoryMapping(File file, explicit WritableMemoryMapping(File file,
off_t offset = 0, off_t offset = 0,
off_t length = -1); off_t length = -1,
off_t pageSize = 0);
/** /**
* A bitwise cast of the mapped bytes as range of mutable values. Only * A bitwise cast of the mapped bytes as range of mutable values. Only
* intended for use with POD or in-place usable types. * intended for use with POD or in-place usable types.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment