X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=folly%2FMemoryMapping.h;h=280a261fd6407c14d596dd419f57310e5951f694;hb=6896ff9de7e7e8d8db569b594e9b493d3e4f8122;hp=85f804dadd006d5cbf746ccd2f773949fa0d6712;hpb=82275df6fc89e0c86556c73d49858b40a5691b78;p=folly.git diff --git a/folly/MemoryMapping.h b/folly/MemoryMapping.h index 85f804da..280a261f 100644 --- a/folly/MemoryMapping.h +++ b/folly/MemoryMapping.h @@ -1,5 +1,5 @@ /* - * 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. @@ -17,9 +17,9 @@ #ifndef FOLLY_MEMORYMAPPING_H_ #define FOLLY_MEMORYMAPPING_H_ -#include "folly/FBString.h" -#include "folly/File.h" -#include "folly/Range.h" +#include +#include +#include #include #include @@ -52,19 +52,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); + off_t length=-1, + Options options=Options()); explicit MemoryMapping(int fd, off_t offset=0, - off_t length=-1); + 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 @@ -76,7 +145,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. @@ -88,6 +157,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 @@ -104,12 +174,34 @@ 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. */ StringPiece data() const { return asRange(); @@ -121,50 +213,41 @@ class MemoryMapping : boost::noncopyable { int fd() const { return file_.fd(); } - protected: + 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). + * + * Assumes src and dest are aligned to alignof(unsigned long). * - * @author Tom Jackson (tjackson@fb.com) + * 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 { - 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