11#include < cstdint>
22#include < ios>
33#include < ostream>
4+ #include < stdexcept>
45#include < sys/mman.h>
56#include < unistd.h>
67#include < thread>
@@ -81,17 +82,23 @@ void tag_chunk(char *chunk, size_t aligned_size) {
8182
8283// Align to OS page size
8384size_t align_to_pagesize (size_t size) {
84- return ( size_t ) (size + (pagesize - (size % pagesize)));
85+ return static_cast < size_t > (size + (pagesize - (size % pagesize)));
8586}
8687
8788// Align size to next nearest 4 byte boundary
8889size_t align_4 (size_t size) {
89- return (size_t ) (size + (4 - (size % 4 )));
90+ return static_cast <size_t >(size + (4 - (size % 4 )));
91+ }
92+
93+ // Return size required (rounded up to nearest 4-byte boundary) including
94+ // additional segment header/footer that will be allocated
95+ size_t get_padded_size (size_t size) {
96+ return static_cast <size_t >(align_4 (size + sizeof (segment_s)*2 ));
9097}
9198
9299// Get a pointer to the first byte of the payload section
93100// from a segment_s header
94- void * get_payload (uintptr_t addr) {
101+ void * get_payload (uintptr_t & addr) {
95102 return reinterpret_cast <void *>(align_4 (addr + sizeof (segment_s)));
96103}
97104
@@ -105,11 +112,12 @@ void* get_header(void* ptr) {
105112// than the chunk size, in which case, create a chunk aligned up to the nearest page
106113// beyond the requested size.
107114size_t add_chunk (size_t size) {
108- size_t aligned_size;
109-
110115 // Pad to ensure there's enough room for desired allocation + headers/footers structs
111- size_t padded_size = (sizeof (chunk_s)*4 ) + ((size > DEFAULT_CHUNK_SIZE) ? size : DEFAULT_CHUNK_SIZE);
112- aligned_size = align_to_pagesize (padded_size);
116+ size_t required_size = align_to_pagesize (sizeof (chunk_s)*2 ) + align_to_pagesize (get_padded_size (size));
117+
118+ // If resulting size is larger than the default chunk size, increase the size of the mmap request to
119+ // the nearest pagesize boundary past the requested size
120+ size_t aligned_size = (required_size > DEFAULT_CHUNK_SIZE) ? required_size : align_to_pagesize (DEFAULT_CHUNK_SIZE);
113121
114122 debug (std::cout, " Created chunk with size:" , aligned_size, " bytes" );
115123
@@ -127,7 +135,7 @@ void* create_segment_in_chunk(chunk_s* chunk, size_t size) {
127135
128136 // Update total remaining contiguous space removing allocation size + header/footer padding
129137 // TODO: Align this?
130- chunk->remaining_size = chunk->remaining_size - (size + ( sizeof (segment_s)* 2 ) );
138+ chunk->remaining_size = chunk->remaining_size - get_padded_size (size);
131139 chunk->total_allocations += 1 ;
132140
133141 // Skip to free space pool
@@ -147,13 +155,15 @@ void* create_segment_in_chunk(chunk_s* chunk, size_t size) {
147155 // Now write a header and footer for the new segment
148156 // Add footer to end of allocation
149157 struct segment_s * footer = reinterpret_cast <segment_s*>(align_4 (free_space_ptr + sizeof (segment_s) + size));
158+ debug (std::cout, " Writing segment footer at address" , footer);
150159
151160 footer->next = nullptr ;
152161 footer->size = size;
153162 footer->is_allocated = true ;
154163 footer->is_footer = true ;
155164
156165 struct segment_s * header = reinterpret_cast <segment_s*>(align_4 (free_space_ptr));
166+ debug (std::cout, " Writing segment header at address" , header);
157167
158168 header->next = footer;
159169 header->size = size;
@@ -231,22 +241,28 @@ void *find_segment(size_t minimum_size) {
231241 chunk_s* parent_chunk;
232242
233243 while (r) {
234- debug (std::cout, " Checking CHUNK" , r, " with size" , r->allocated_size , " and remaining space" , r->remaining_size );
244+ if (r->is_footer ) {
245+ r = r->next ;
246+ continue ;
247+ }
248+
249+ debug (std::cout, " Checking CHUNK" , r, " with size" , r->allocated_size , " and remaining space" , r->remaining_size ,
250+ " for minimum required size of" , minimum_size);
235251 parent_chunk = r;
236252 segment_s* segment_iter = r->next_segment ;
237253
238254 while (segment_iter) {
239255 // Look for a free segment to reclaim while searching for free chunk space
240256 // If we find it, re-use instead of allocating new segments
241- if (segment_iter->size >= ( minimum_size) && segment_iter->is_allocated == false && segment_iter->is_footer == false ) {
257+ if (segment_iter->size >= minimum_size && segment_iter->is_allocated == false && segment_iter->is_footer == false ) {
242258 // Located an existing segment large enough for allocation and marked unallocated
243259 debug (std::cout, " Found a reusable segment in chunk (need" , minimum_size, " bytes, have" , segment_iter->size , " bytes available." );
244260 return reserve_segment (parent_chunk, segment_iter, minimum_size);
245261 }
246262 segment_iter = segment_iter->next ;
247263 }
248264
249- if (r->remaining_size >= ( minimum_size+pagesize) && r->is_footer == false ) {
265+ if (r->remaining_size >= minimum_size && r->is_footer == false ) {
250266 // Unable to find an unallocated segment, allocate a new segment in chunk
251267 debug (std::cout, " Found a free MMAP chunk (need" , minimum_size, " bytes, have" , r->remaining_size , " bytes available." );
252268 return create_segment_in_chunk (r, minimum_size);
0 commit comments