Commit 51026ab6 authored by Lucian Grijincu's avatar Lucian Grijincu Committed by Viswanath Sivakumar

folly: MemoryMapping: add offset/size params to advise

Test Plan: ran it

Reviewed By: philipp@fb.com

Subscribers: folly-diffs@, yfeldblum, chalfant

FB internal diff: D1974936

Signature: t1:1974936:1428453023:1a83ed8336f75b745bffc633b8471231423b0fb0
parent d2eda017
...@@ -15,8 +15,12 @@ ...@@ -15,8 +15,12 @@
*/ */
#include <folly/MemoryMapping.h> #include <folly/MemoryMapping.h>
#include <algorithm>
#include <functional>
#include <utility>
#include <folly/Format.h> #include <folly/Format.h>
#include <folly/Portability.h>
#ifdef __linux__ #ifdef __linux__
#include <folly/experimental/io/HugePages.h> #include <folly/experimental/io/HugePages.h>
...@@ -240,9 +244,8 @@ bool MemoryMapping::mlock(LockMode lock) { ...@@ -240,9 +244,8 @@ bool MemoryMapping::mlock(LockMode lock) {
return true; return true;
} }
auto msg(folly::format( auto msg =
"mlock({}) failed at {}", folly::sformat("mlock({}) failed at {}", mapLength_, amountSucceeded);
mapLength_, amountSucceeded).str());
if (lock == LockMode::TRY_LOCK && (errno == EPERM || errno == ENOMEM)) { if (lock == LockMode::TRY_LOCK && (errno == EPERM || errno == ENOMEM)) {
PLOG(WARNING) << msg; PLOG(WARNING) << msg;
...@@ -283,17 +286,35 @@ MemoryMapping::~MemoryMapping() { ...@@ -283,17 +286,35 @@ MemoryMapping::~MemoryMapping() {
size_t amountSucceeded = 0; size_t amountSucceeded = 0;
if (!memOpInChunks(::munmap, mapStart_, mapLength_, options_.pageSize, if (!memOpInChunks(::munmap, mapStart_, mapLength_, options_.pageSize,
amountSucceeded)) { amountSucceeded)) {
PLOG(FATAL) << folly::format( PLOG(FATAL) << folly::format("munmap({}) failed at {}",
"munmap({}) failed at {}", mapLength_, amountSucceeded);
mapLength_, amountSucceeded).str();
} }
} }
} }
void MemoryMapping::advise(int advice) const { void MemoryMapping::advise(int advice) const { advise(advice, 0, mapLength_); }
if (mapLength_ && ::madvise(mapStart_, mapLength_, advice)) {
PLOG(WARNING) << "madvise()"; void MemoryMapping::advise(int advice, size_t offset, size_t length) const {
CHECK_LE(offset + length, mapLength_)
<< " offset: " << offset
<< " length: " << length
<< " mapLength_: " << mapLength_;
if (length == 0) {
return;
}
auto offMisalign = offset % options_.pageSize;
if (offMisalign != 0) {
offset -= offMisalign;
length += offMisalign;
} }
length = (length + options_.pageSize - 1) & ~(options_.pageSize - 1);
length = std::min(length, mapLength_ - offset);
char* mapStart = static_cast<char*>(mapStart_) + offset;
PLOG_IF(WARNING, ::madvise(mapStart, length, advice)) << "madvise";
} }
MemoryMapping& MemoryMapping::operator=(MemoryMapping other) { MemoryMapping& MemoryMapping::operator=(MemoryMapping other) {
......
...@@ -157,6 +157,7 @@ class MemoryMapping : boost::noncopyable { ...@@ -157,6 +157,7 @@ class MemoryMapping : boost::noncopyable {
* Advise the kernel about memory access. * Advise the kernel about memory access.
*/ */
void advise(int advice) const; void advise(int advice) const;
void advise(int advice, size_t offset, size_t length) const;
/** /**
* A bitwise cast of the mapped bytes as range of values. Only intended for * A bitwise cast of the mapped bytes as range of values. Only intended for
......
...@@ -14,9 +14,11 @@ ...@@ -14,9 +14,11 @@
* limitations under the License. * limitations under the License.
*/ */
#include <sys/mman.h>
#include <cstdlib> #include <cstdlib>
#include <gtest/gtest.h> #include <folly/FileUtil.h>
#include <folly/MemoryMapping.h> #include <folly/MemoryMapping.h>
#include <gtest/gtest.h>
namespace folly { namespace folly {
...@@ -145,4 +147,29 @@ TEST(MemoryMapping, ZeroLength) { ...@@ -145,4 +147,29 @@ TEST(MemoryMapping, ZeroLength) {
EXPECT_EQ(0, m.data().size()); EXPECT_EQ(0, m.data().size());
} }
TEST(MemoryMapping, Advise) {
File f = File::temporary();
size_t kPageSize = 4096;
size_t size = kPageSize + 10; // unaligned file size
PCHECK(ftruncateNoInt(f.fd(), size) == 0) << size;
MemoryMapping m(File(f.fd()));
// NOTE: advise crashes on bad input.
m.advise(MADV_NORMAL, 0, kPageSize);
m.advise(MADV_NORMAL, 1, kPageSize);
m.advise(MADV_NORMAL, 0, 2);
m.advise(MADV_NORMAL, 1, 2);
m.advise(MADV_NORMAL, kPageSize, 0);
m.advise(MADV_NORMAL, kPageSize, 1);
m.advise(MADV_NORMAL, kPageSize, size - kPageSize);
auto off = kPageSize + 1;
m.advise(MADV_NORMAL, off, size - off);
EXPECT_DEATH(m.advise(MADV_NORMAL, off, size - off + 1), "");
}
} // namespace folly } // namespace folly
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