/*
- * Copyright 2014 Facebook, Inc.
+ * Copyright 2015 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
*/
#include <folly/MemoryMapping.h>
+
+#include <algorithm>
+#include <functional>
+#include <utility>
+
#include <folly/Format.h>
-#include <folly/Portability.h>
#ifdef __linux__
#include <folly/experimental/io/HugePages.h>
MemoryMapping::MemoryMapping(const char* name, off_t offset, off_t length,
Options options)
- : MemoryMapping(File(name), offset, length, options) { }
+ : MemoryMapping(File(name, options.writable ? O_RDWR : O_RDONLY),
+ offset,
+ length,
+ options) { }
MemoryMapping::MemoryMapping(int fd, off_t offset, off_t length,
Options options)
return true;
}
- auto msg(folly::format(
- "mlock({}) failed at {}",
- mapLength_, amountSucceeded).str());
+ auto msg =
+ folly::sformat("mlock({}) failed at {}", mapLength_, amountSucceeded);
if (lock == LockMode::TRY_LOCK && (errno == EPERM || errno == ENOMEM)) {
PLOG(WARNING) << msg;
size_t amountSucceeded = 0;
if (!memOpInChunks(::munmap, mapStart_, mapLength_, options_.pageSize,
amountSucceeded)) {
- PLOG(FATAL) << folly::format(
- "munmap({}) failed at {}",
- mapLength_, amountSucceeded).str();
+ PLOG(FATAL) << folly::format("munmap({}) failed at {}",
+ mapLength_, amountSucceeded);
}
}
}
-void MemoryMapping::advise(int advice) const {
- if (mapLength_ && ::madvise(mapStart_, mapLength_, advice)) {
- PLOG(WARNING) << "madvise()";
+void MemoryMapping::advise(int advice) const { advise(advice, 0, mapLength_); }
+
+void MemoryMapping::advise(int advice, size_t offset, size_t length) const {
+ CHECK_LE(offset + length, mapLength_)
+ << " offset: " << offset
+ << " length: " << length
+ << " mapLength_: " << mapLength_;
+
+ // Include the entire start page: round down to page boundary.
+ const auto offMisalign = offset % options_.pageSize;
+ offset -= offMisalign;
+ length += offMisalign;
+
+ // Round the last page down to page boundary.
+ if (offset + length != size_t(mapLength_)) {
+ length -= length % options_.pageSize;
}
+
+ if (length == 0) {
+ return;
+ }
+
+ char* mapStart = static_cast<char*>(mapStart_) + offset;
+ PLOG_IF(WARNING, ::madvise(mapStart, length, advice)) << "madvise";
}
MemoryMapping& MemoryMapping::operator=(MemoryMapping other) {