X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=folly%2FMemoryMapping.h;h=14ce382da7938c510f09073afdfb12a6c255eae2;hb=60b2478a8e299bbae257a5fe69837696c0950ee5;hp=244727b4a6db12ff46249ea7a78c0c632eeaee01;hpb=2b8ea38174dea68f56f0e809f05c9d1867a93621;p=folly.git diff --git a/folly/MemoryMapping.h b/folly/MemoryMapping.h index 244727b4..14ce382d 100644 --- a/folly/MemoryMapping.h +++ b/folly/MemoryMapping.h @@ -1,5 +1,5 @@ /* - * Copyright 2013 Facebook, Inc. + * Copyright 2017 Facebook, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,12 +14,10 @@ * limitations under the License. */ -#ifndef FOLLY_MEMORYMAPPING_H_ -#define FOLLY_MEMORYMAPPING_H_ +#pragma once -#include "folly/FBString.h" -#include "folly/File.h" -#include "folly/Range.h" +#include +#include #include #include @@ -52,11 +50,88 @@ class MemoryMapping : boost::noncopyable { * The mapping will be destroyed (and the memory pointed-to by data() will * likely become inaccessible) when the MemoryMapping object is destroyed. */ + struct Options { + Options() {} + + // Convenience methods; return *this for chaining. + Options& setPageSize(off_t v) { pageSize = v; return *this; } + Options& setShared(bool v) { shared = v; return *this; } + Options& setPrefault(bool v) { prefault = v; return *this; } + Options& setReadable(bool v) { readable = v; return *this; } + Options& setWritable(bool v) { writable = v; return *this; } + Options& setGrow(bool v) { grow = v; return *this; } + + // Page size. 0 = use appropriate page size. + // (On Linux, we use a huge page size if the file is on a hugetlbfs + // file system, and the default page size otherwise) + off_t pageSize = 0; + + // If shared (default), the memory mapping is shared with other processes + // mapping the same file (or children); if not shared (private), each + // process has its own mapping. Changes in writable, private mappings are + // not reflected to the underlying file. See the discussion of + // MAP_PRIVATE vs MAP_SHARED in the mmap(2) manual page. + bool shared = true; + + // Populate page tables; subsequent accesses should not be blocked + // by page faults. This is a hint, as it may not be supported. + bool prefault = false; + + // Map the pages readable. Note that mapping pages without read permissions + // is not universally supported (not supported on hugetlbfs on Linux, for + // example) + bool readable = true; + + // Map the pages writable. + bool writable = false; + + // When mapping a file in writable mode, grow the file to the requested + // length (using ftruncate()) before mapping; if false, truncate the + // mapping to the actual file size instead. + bool grow = false; + + // Fix map at this address, if not nullptr. Must be aligned to a multiple + // of the appropriate page size. + void* address = nullptr; + }; + + // Options to emulate the old WritableMemoryMapping: readable and writable, + // allow growing the file if mapping past EOF. + static Options writable() { + return Options().setWritable(true).setGrow(true); + } + + enum AnonymousType { + kAnonymous + }; + + /** + * Create an anonymous mapping. + */ + MemoryMapping(AnonymousType, off_t length, Options options=Options()); + explicit MemoryMapping(File file, off_t offset=0, - off_t length=-1); + off_t length=-1, + Options options=Options()); + + explicit MemoryMapping(const char* name, + off_t offset=0, + off_t length=-1, + Options options=Options()); + + explicit MemoryMapping(int fd, + off_t offset=0, + off_t length=-1, + Options options=Options()); + + MemoryMapping(MemoryMapping&&) noexcept; + + ~MemoryMapping(); - virtual ~MemoryMapping(); + MemoryMapping& operator=(MemoryMapping); + + void swap(MemoryMapping& other) noexcept; /** * Lock the pages in memory @@ -68,7 +143,7 @@ class MemoryMapping : boost::noncopyable { * If dontneed is true, the kernel is instructed to release these pages * (per madvise(MADV_DONTNEED)). */ - void munlock(bool dontneed=false); + void munlock(bool dontneed = false); /** * Hint that these pages will be scanned linearly. @@ -80,6 +155,7 @@ class MemoryMapping : boost::noncopyable { * Advise the kernel about memory access. */ 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 @@ -87,7 +163,6 @@ class MemoryMapping : boost::noncopyable { */ template Range asRange() const { - CHECK(mapStart_); size_t count = data_.size() / sizeof(T); return Range(static_cast( static_cast(data_.data())), @@ -97,67 +172,79 @@ class MemoryMapping : boost::noncopyable { /** * A range of bytes mapped by this mapping. */ - Range range() const { - return {data_.begin(), data_.end()}; + ByteRange range() const { + return data_; + } + + /** + * A bitwise cast of the mapped bytes as range of mutable values. Only + * intended for use with POD or in-place usable types. + */ + template + Range asWritableRange() const { + DCHECK(options_.writable); // you'll segfault anyway... + size_t count = data_.size() / sizeof(T); + return Range(static_cast( + static_cast(data_.data())), + count); + } + + /** + * A range of mutable bytes mapped by this mapping. + */ + MutableByteRange writableRange() const { + DCHECK(options_.writable); // you'll segfault anyway... + return data_; } /** * Return the memory area where the file was mapped. + * Deprecated; use range() instead. */ - ByteRange data() const { - return range(); + StringPiece data() const { + return asRange(); } bool mlocked() const { return locked_; } - protected: + int fd() const { return file_.fd(); } + + private: MemoryMapping(); - void init(File file, - off_t offset, off_t length, - int prot, - bool grow); + enum InitFlags { + kGrow = 1 << 0, + kAnon = 1 << 1, + }; + void init(off_t offset, off_t length); File file_; - void* mapStart_; - off_t mapLength_; - bool locked_; - Range data_; + void* mapStart_ = nullptr; + off_t mapLength_ = 0; + Options options_; + bool locked_ = false; + MutableByteRange data_; }; +void swap(MemoryMapping&, MemoryMapping&) noexcept; + /** - * Maps files in memory for writing. + * A special case of memcpy() that always copies memory forwards. + * (libc's memcpy() is allowed to copy memory backwards, and will do so + * when using SSSE3 instructions). * - * @author Tom Jackson (tjackson@fb.com) + * Assumes src and dest are aligned to alignof(unsigned long). + * + * Useful when copying from/to memory mappings after hintLinearScan(); + * copying backwards renders any prefetching useless (even harmful). */ -class WritableMemoryMapping : public MemoryMapping { - public: - explicit WritableMemoryMapping(File file, - off_t offset = 0, - off_t length = -1); - /** - * A bitwise cast of the mapped bytes as range of mutable values. Only - * intended for use with POD or in-place usable types. - */ - template - Range asWritableRange() const { - CHECK(mapStart_); - size_t count = data_.size() / sizeof(T); - return Range(static_cast( - static_cast(data_.data())), - count); - } +void alignedForwardMemcpy(void* dest, const void* src, size_t size); - /** - * A range of mutable bytes mapped by this mapping. - */ - Range writableRange() const { - return data_; - } -}; +/** + * Copy a file using mmap(). Overwrites dest. + */ +void mmapFileCopy(const char* src, const char* dest, mode_t mode = 0666); } // namespace folly - -#endif /* FOLLY_MEMORYMAPPING_H_ */