| #ifndef UTIL_MMAP_H |
| #define UTIL_MMAP_H |
| |
|
|
| #include <cstddef> |
| #include <limits> |
|
|
| #include <stdint.h> |
| #include <sys/types.h> |
|
|
| namespace util { |
|
|
| class scoped_fd; |
|
|
| std::size_t SizePage(); |
|
|
| |
| class scoped_mmap { |
| public: |
| scoped_mmap() : data_((void*)-1), size_(0) {} |
| scoped_mmap(void *data, std::size_t size) : data_(data), size_(size) {} |
| ~scoped_mmap(); |
|
|
| void *get() const { return data_; } |
|
|
| const uint8_t *begin() const { return reinterpret_cast<uint8_t*>(data_); } |
| const uint8_t *end() const { return reinterpret_cast<uint8_t*>(data_) + size_; } |
| std::size_t size() const { return size_; } |
|
|
| void reset(void *data, std::size_t size) { |
| scoped_mmap other(data_, size_); |
| data_ = data; |
| size_ = size; |
| } |
|
|
| void reset() { |
| reset((void*)-1, 0); |
| } |
|
|
| void *steal() { |
| void *ret = data_; |
| data_ = (void*)-1; |
| size_ = 0; |
| return ret; |
| } |
|
|
| private: |
| void *data_; |
| std::size_t size_; |
|
|
| scoped_mmap(const scoped_mmap &); |
| scoped_mmap &operator=(const scoped_mmap &); |
| }; |
|
|
| |
| |
| |
| |
| class scoped_memory { |
| public: |
| typedef enum { |
| MMAP_ROUND_UP_ALLOCATED, |
| MMAP_ALLOCATED, |
| MALLOC_ALLOCATED, |
| NONE_ALLOCATED |
| } Alloc; |
|
|
| scoped_memory(void *data, std::size_t size, Alloc source) |
| : data_(data), size_(size), source_(source) {} |
|
|
| scoped_memory() : data_(NULL), size_(0), source_(NONE_ALLOCATED) {} |
|
|
| |
| scoped_memory(std::size_t to, bool zero_new); |
|
|
| ~scoped_memory() { reset(); } |
|
|
| void *get() const { return data_; } |
| const char *begin() const { return reinterpret_cast<char*>(data_); } |
| const char *end() const { return reinterpret_cast<char*>(data_) + size_; } |
| std::size_t size() const { return size_; } |
|
|
| Alloc source() const { return source_; } |
|
|
| void reset() { reset(NULL, 0, NONE_ALLOCATED); } |
|
|
| void reset(void *data, std::size_t size, Alloc from); |
|
|
| void *steal() { |
| void *ret = data_; |
| data_ = NULL; |
| size_ = 0; |
| source_ = NONE_ALLOCATED; |
| return ret; |
| } |
|
|
| private: |
| void *data_; |
| std::size_t size_; |
|
|
| Alloc source_; |
|
|
| scoped_memory(const scoped_memory &); |
| scoped_memory &operator=(const scoped_memory &); |
| }; |
|
|
| extern const int kFileFlags; |
|
|
| |
| void *MapOrThrow(std::size_t size, bool for_write, int flags, bool prefault, int fd, uint64_t offset = 0); |
|
|
| |
| void SyncOrThrow(void *start, size_t length); |
|
|
| |
| void UnmapOrThrow(void *start, size_t length); |
|
|
| |
| |
| |
| void HugeMalloc(std::size_t size, bool zeroed, scoped_memory &to); |
|
|
| |
| |
| |
| |
| |
| |
| void HugeRealloc(std::size_t size, bool new_zeroed, scoped_memory &mem); |
|
|
| typedef enum { |
| |
| LAZY, |
| |
| POPULATE_OR_LAZY, |
| |
| POPULATE_OR_READ, |
| |
| READ, |
| |
| PARALLEL_READ, |
| } LoadMethod; |
|
|
| void MapRead(LoadMethod method, int fd, uint64_t offset, std::size_t size, scoped_memory &out); |
|
|
| |
| void *MapZeroedWrite(int fd, std::size_t size); |
| void *MapZeroedWrite(const char *name, std::size_t size, scoped_fd &file); |
|
|
| |
| class Rolling { |
| public: |
| Rolling() {} |
|
|
| explicit Rolling(void *data) { Init(data); } |
|
|
| Rolling(const Rolling ©_from, uint64_t increase = 0); |
| Rolling &operator=(const Rolling ©_from); |
|
|
| |
| explicit Rolling(int fd, bool for_write, std::size_t block, std::size_t read_bound, uint64_t offset, uint64_t amount); |
|
|
| |
| void Init(void *data) { |
| ptr_ = data; |
| current_end_ = std::numeric_limits<uint64_t>::max(); |
| current_begin_ = 0; |
| |
| fd_ = -1; |
| } |
|
|
| void IncreaseBase(uint64_t by) { |
| file_begin_ += by; |
| ptr_ = static_cast<uint8_t*>(ptr_) + by; |
| if (!IsPassthrough()) current_end_ = 0; |
| } |
|
|
| void DecreaseBase(uint64_t by) { |
| file_begin_ -= by; |
| ptr_ = static_cast<uint8_t*>(ptr_) - by; |
| if (!IsPassthrough()) current_end_ = 0; |
| } |
|
|
| void *ExtractNonRolling(scoped_memory &out, uint64_t index, std::size_t size); |
|
|
| |
| void *get() const { return ptr_; } |
|
|
| |
| void *CheckedBase(uint64_t index) { |
| if (index >= current_end_ || index < current_begin_) { |
| Roll(index); |
| } |
| return ptr_; |
| } |
|
|
| |
| void *CheckedIndex(uint64_t index) { |
| return static_cast<uint8_t*>(CheckedBase(index)) + index; |
| } |
|
|
| private: |
| void Roll(uint64_t index); |
|
|
| |
| bool IsPassthrough() const { return fd_ == -1; } |
|
|
| void *ptr_; |
| uint64_t current_begin_; |
| uint64_t current_end_; |
|
|
| scoped_memory mem_; |
|
|
| int fd_; |
| uint64_t file_begin_; |
| uint64_t file_end_; |
|
|
| bool for_write_; |
| std::size_t block_; |
| std::size_t read_bound_; |
| }; |
|
|
| } |
|
|
| #endif |
|
|