X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=folly%2FMemoryMapping.h;h=14ce382da7938c510f09073afdfb12a6c255eae2;hb=60b2478a8e299bbae257a5fe69837696c0950ee5;hp=7b09dc980abba09f0cc992d8dafc913ce184f55f;hpb=2c73945cae93e33935f0c9730117ba78387cd987;p=folly.git diff --git a/folly/MemoryMapping.h b/folly/MemoryMapping.h index 7b09dc98..14ce382d 100644 --- a/folly/MemoryMapping.h +++ b/folly/MemoryMapping.h @@ -1,5 +1,5 @@ /* - * Copyright 2014 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,28 +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 pageSize=0); + Options options=Options()); explicit MemoryMapping(const char* name, off_t offset=0, off_t length=-1, - off_t pageSize=0); + Options options=Options()); explicit MemoryMapping(int fd, off_t offset=0, off_t length=-1, - off_t pageSize=0); + Options options=Options()); - MemoryMapping(MemoryMapping&&); + MemoryMapping(MemoryMapping&&) noexcept; - virtual ~MemoryMapping(); + ~MemoryMapping(); MemoryMapping& operator=(MemoryMapping); - void swap(MemoryMapping& other); + void swap(MemoryMapping& other) noexcept; /** * Lock the pages in memory @@ -97,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 @@ -113,12 +172,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(); @@ -130,56 +211,40 @@ class MemoryMapping : boost::noncopyable { int fd() const { return file_.fd(); } - protected: + private: MemoryMapping(); - void init(File file, - off_t offset, off_t length, - off_t pageSize, - 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_; - off_t pageSize_; - 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, - off_t pageSize = 0); - /** - * 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_; - } -}; - -void swap(MemoryMapping&, MemoryMapping&); +/** + * 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_ */