|
#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 char *begin() const { return reinterpret_cast<char*>(data_); } |
|
char *begin() { return reinterpret_cast<char*>(data_); } |
|
const char *end() const { return reinterpret_cast<char*>(data_) + size_; } |
|
char *end() { return reinterpret_cast<char*>(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_1G_ALLOCATED, |
|
MMAP_ROUND_2M_ALLOCATED, |
|
MMAP_ROUND_PAGE_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); |
|
|
|
#if __cplusplus >= 201103L |
|
scoped_memory(scoped_memory &&from) noexcept |
|
: data_(from.data_), size_(from.size_), source_(from.source_) { |
|
from.steal(); |
|
} |
|
#endif |
|
|
|
~scoped_memory() { reset(); } |
|
|
|
void *get() const { return data_; } |
|
|
|
const char *begin() const { return reinterpret_cast<char*>(data_); } |
|
char *begin() { return reinterpret_cast<char*>(data_); } |
|
const char *end() const { return reinterpret_cast<char*>(data_) + size_; } |
|
char *end() { 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); |
|
|
|
enum LoadMethod { |
|
|
|
LAZY, |
|
|
|
POPULATE_OR_LAZY, |
|
|
|
POPULATE_OR_READ, |
|
|
|
READ, |
|
|
|
PARALLEL_READ, |
|
}; |
|
|
|
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 |
|
|