34 fd_ = memfd_create(
"rewire_allocator", MFD_CLOEXEC);
36 auto name = std::to_string(getpid());
37 fd_ = shm_open(name.c_str(), O_RDWR | O_TRUNC | O_CREAT, S_IRUSR | S_IWUSR);
38 shm_unlink(name.c_str());
39 ftruncate(
fd_, 1UL << 44);
42 throw std::runtime_error(strerror(errno));
52 return Memory(*
this, addr, size, offset);
64 addr_ = mmap(
nullptr, aligned_size, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
65 if (
addr_ == MAP_FAILED)
66 throw std::runtime_error(strerror(errno));
87 M_insist(size <= this->
size(),
"size exceeds memory size");
88 M_insist(offset_src < this->
size(),
"source offset out of bounds");
90 M_insist(offset_src + size <= this->
size(),
"source range out of bounds");
93 M_insist(offset_dst < vm.
size(),
"destination offset out of bounds");
97 void *dst_addr = vm.
as<uint8_t*>() + offset_dst;
98 void *
addr = mmap(dst_addr,
size, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_FIXED,
allocator().fd(),
99 this->
offset() + offset_src);
100 if (
addr == MAP_FAILED)
101 throw std::runtime_error(strerror(errno));
102 if (
addr != dst_addr)
103 throw std::runtime_error(
"MAP_FIXED failed");
109 out <<
"Memory at virtual address " <<
addr() <<
" of size " <<
size() <<
" bytes mapped to offset " <<
offset()
110 <<
" of file descriptor " <<
allocator().
fd() << std::endl;
122 if (size == 0)
return Memory();
125 M_insist(aligned_size >= size,
"size must be ceiled");
128 if (ftruncate(
fd(),
offset_ + aligned_size))
129 throw std::runtime_error(strerror(errno));
135 void *addr = mmap(
nullptr, aligned_size, PROT_READ|PROT_WRITE, MAP_SHARED,
fd(),
offset_);
136 if (addr == MAP_FAILED)
137 throw std::runtime_error(strerror(errno));
148constexpr std::size_t MSB = std::size_t(1UL) << (
sizeof(MSB) * CHAR_BIT - 1U);
152std::size_t mark_for_deallocation(std::size_t offset) {
return offset | MSB; }
155bool is_marked_for_deallocation(uintptr_t offset) {
return offset & MSB; }
158std::size_t unmarked(std::size_t offset) {
return offset & ~MSB; }
164 if (&mem.allocator() !=
this)
165 throw std::invalid_argument(
"memory has not been allocated by this allocator");
170 throw std::invalid_argument(
"memory has not been allocated by this allocator or has already been deallocated");
173 munmap(mem.addr(), mem.size());
176 *it = mark_for_deallocation(mem.offset());
181 std::size_t new_size_of_file;
183 new_size_of_file = unmarked(*it);
185 }
while (it !=
allocations_.rend()
and is_marked_for_deallocation(*it));
189 if (ftruncate(
fd(), new_size_of_file))
190 throw std::runtime_error(strerror(errno));
std::size_t Is_Page_Aligned(std::size_t n)
Returns true iff n is a integral multiple of the page size (in bytes).
std::size_t Ceil_To_Next_Page(std::size_t n)
Returns the smallest integral multiple of the page size (in bytes) greater than or equals to n.
This class represents a reserved address space in virtual memory.
void * addr_
pointer to the beginning of the virtual address space
std::size_t size_
size in bytes of the address space
T as() const
Get a pointer to the beginning of the virtual address space, converted to type T.
std::size_t size() const
Returns the size in bytes of the virtual address space.
This is the common interface for all memory allocators that support rewiring.
int fd_
file descriptor of the underlying memory file
Memory create_memory(void *addr, std::size_t size, std::size_t offset)
Helper method to inherit the friend ability to construct a Memory object.
int fd() const
Return the file descriptor of the underlying memory file.
std::size_t offset_
the offset from the start of the memory file of the next allocation
std::vector< std::size_t > allocations_
stack of allocations; allocations can be marked deallocated for later reclaiming
void deallocate(Memory &&mem) override
Deallocates a memory object.
Memory allocate(std::size_t size) override
Creates a new memory object with size bytes of freshly allocated memory.
Represents a mapping created by a memory::Allocator.
void * addr() const
Returns a pointer to the beginning of the virtual address space where this allocation is mapped to.
std::size_t offset() const
Returns the offset in bytes of this allocation within its allocator.
Allocator & allocator() const
Returns a reference to the allocator that created this allocation.
std::size_t size() const
Returns the size in bytes of this allocation.
void map(std::size_t size, std::size_t offset_src, const AddressSpace &vm, std::size_t offset_dst) const
Map size bytes starting at offset_src into the address space of vm at offset offset_dst.