Skip to content

Commit 2f9acd0

Browse files
committed
Replace some C-style casts, comments, improve free_segment check
1 parent d6df61a commit 2f9acd0

File tree

1 file changed

+32
-21
lines changed

1 file changed

+32
-21
lines changed

src/erikmtalloc.cpp

Lines changed: 32 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,15 @@
1111

1212
#define DEFAULT_CHUNK_SIZE 1024*256 // 256KB chunks
1313

14+
// Structure for segments allocated inside of an MMAPed "chunk"
1415
struct segment_s {
1516
segment_s* next;
1617
size_t size;
1718
bool is_allocated;
1819
bool is_footer;
1920
};
2021

22+
// mmap()'ed parent "chunks", on which variable size "segments" are allocated
2123
struct chunk_s {
2224
chunk_s* next;
2325
size_t allocated_size;
@@ -37,10 +39,10 @@ chunk_s* root;
3739
chunk_s* cur;
3840
size_t pagesize = sysconf(_SC_PAGE_SIZE);
3941

42+
// Add a header and footer identifying metadata for new chunk,
43+
// then add the chunk to the chunk map list.
44+
// Add footer to end of allocation
4045
void tag_chunk(char *chunk, size_t aligned_size) {
41-
// Add a header and footer identifying metadata for new chunk,
42-
// then add the chunk to the chunk map list.
43-
// Add footer to end of allocation
4446
struct chunk_s* footer = reinterpret_cast<chunk_s*>(static_cast<char*>(chunk) + (aligned_size - sizeof(chunk_s)));
4547
debug(std::cout, "writing CHUNK footer at", footer);
4648

@@ -77,31 +79,32 @@ void tag_chunk(char *chunk, size_t aligned_size) {
7779
}
7880
}
7981

82+
// Align to OS page size
8083
size_t align_to_pagesize(size_t size) {
8184
return (size_t) (size + (pagesize - (size % pagesize)));
8285
}
8386

87+
// Align size to next nearest 4 byte boundary
8488
size_t align_4(size_t size) {
85-
// Align size to next nearest 4 byte boundary
8689
return (size_t) (size + (4 - (size % 4)));
8790
}
8891

92+
// Get a pointer to the first byte of the payload section
93+
// from a segment_s header
8994
void* get_payload(uintptr_t addr) {
90-
// Get a pointer to the first byte of the payload section
91-
// from a segment_s header
9295
return reinterpret_cast<void *>(align_4(addr + sizeof(segment_s)));
9396
}
9497

98+
// Get a pointer to the header struct of payload
9599
void* get_header(void* ptr) {
96-
// Get a pointer to the header struct of payload
97-
return reinterpret_cast<void *>((uintptr_t) ptr - (sizeof(segment_s)));
100+
return reinterpret_cast<void *>(reinterpret_cast<uintptr_t>(ptr) - (sizeof(segment_s)));
98101
}
99102

103+
// Add a chunk capable of containing at least the size passed. By default, create
104+
// a large chunk (specified by DEFAULT_CHUNK_SIZE), unless new() requires more memory
105+
// than the chunk size, in which case, create a chunk aligned up to the nearest page
106+
// beyond the requested size.
100107
size_t add_chunk(size_t size) {
101-
// Add a chunk capable of containing at least the size passed. By default, create
102-
// a large chunk (specified by DEFAULT_CHUNK_SIZE), unless new() requires more memory
103-
// than the chunk size, in which case, create a chunk aligned up to the nearest page
104-
// beyond the requested size.
105108
size_t aligned_size;
106109

107110
// Pad to ensure there's enough room for desired allocation + headers/footers structs
@@ -117,8 +120,8 @@ size_t add_chunk(size_t size) {
117120
return aligned_size;
118121
}
119122

123+
// Find free space in parent chunk, and reserve it
120124
void* create_segment_in_chunk(chunk_s* chunk, size_t size) {
121-
// Find free space in parent chunk, and reserve it
122125
debug(std::cout, "SIZE REMAINING:", chunk->remaining_size);
123126
segment_s* segment_iter = chunk->next_segment;
124127

@@ -132,13 +135,13 @@ void* create_segment_in_chunk(chunk_s* chunk, size_t size) {
132135
uintptr_t free_space_ptr;
133136
if (segment_iter == nullptr) {
134137
// No segments currently exist in this chunk, initialize with offset from chunk_s header
135-
free_space_ptr = (uintptr_t) chunk + sizeof(chunk_s) + 1;
138+
free_space_ptr = reinterpret_cast<uintptr_t>(chunk) + sizeof(chunk_s) + 1;
136139
} else {
137140
// Iterate to end of currently allocated space
138141
while (segment_iter->next) {
139142
segment_iter = segment_iter->next;
140143
}
141-
free_space_ptr = (uintptr_t) segment_iter + sizeof(segment_s) + 1;
144+
free_space_ptr = reinterpret_cast<uintptr_t>(segment_iter) + sizeof(segment_s) + 1;
142145
}
143146

144147
// Now write a header and footer for the new segment
@@ -177,8 +180,9 @@ void* create_segment_in_chunk(chunk_s* chunk, size_t size) {
177180
return get_payload(free_space_ptr);
178181
}
179182

183+
// Find free space in parent chunk (if it exists), reserve it,
184+
// and return a void* pointer to it.
180185
void* reserve_segment(chunk_s* parent_chunk, segment_s* segment, size_t size) {
181-
// Find free space in parent chunk, and reserve it
182186
debug(std::cout, "Reusing segment:", segment, "in parent chunk:", parent_chunk,
183187
"with size:", segment->size, "for new segment of size:", size);
184188

@@ -195,8 +199,14 @@ void* reserve_segment(chunk_s* parent_chunk, segment_s* segment, size_t size) {
195199
return reinterpret_cast<void *>((uintptr_t) segment + sizeof(segment_s));
196200
}
197201

202+
// Find and return a void* pointer to a new memory segment to new()
203+
// The second call to find_segment() is guaranteed to return a segment if
204+
// add_chunk succeeds (as this is happening in a mutex that prevents anyone)
205+
// else from claiming it. There's a little unnecessary overhead since we
206+
// walk the linked list from root to get there, so it makes sense to refactor
207+
// this later to have add_chunk also create the first segment and return the
208+
// pointer to it directly.
198209
void *get_segment(size_t size) {
199-
// Find and return a void* pointer to a new memory segment to new()
200210
void *seg = find_segment(size);
201211

202212
if (seg == nullptr) {
@@ -209,6 +219,7 @@ void *get_segment(size_t size) {
209219
return find_segment(size);
210220
}
211221

222+
// Locate (or create) and return a viable segment, and return a void* to it.
212223
void *find_segment(size_t minimum_size) {
213224
#ifdef DEBUG
214225
print_memory_stack();
@@ -219,7 +230,7 @@ void *find_segment(size_t minimum_size) {
219230
chunk_s* r = root;
220231
chunk_s* parent_chunk;
221232

222-
while (r != NULL) {
233+
while (r) {
223234
debug(std::cout, "Checking CHUNK", r, "with size", r->allocated_size, "and remaining space", r->remaining_size);
224235
parent_chunk = r;
225236
segment_s* segment_iter = r->next_segment;
@@ -248,7 +259,7 @@ void *find_segment(size_t minimum_size) {
248259

249260
debug(std::cout, "No suitable segments available, need to allocate one.");
250261

251-
return NULL;
262+
return nullptr;
252263
}
253264

254265
void unlink_node(chunk_s* root_node, chunk_s* node_to_remove) {
@@ -294,7 +305,7 @@ void free_segment(void* ptr) {
294305
chunk_s* r = root;
295306
chunk_s* current_parent_node;
296307

297-
while (r && r->next != NULL) {
308+
while (r) {
298309
// Check that pointer address that we're freeing is in the range of allocated
299310
// space for this chunk. If it's not, don't bother descending into this chunks
300311
// segments, move to next chunk.
@@ -336,7 +347,7 @@ void print_memory_stack() {
336347

337348
if (r) std::cout << r << std::endl;
338349

339-
while (r != NULL) {
350+
while (r) {
340351
std::cout << std::boolalpha
341352
<< "SEGMENT: " << r
342353
<< " ALLOCATED SIZE: " << r->allocated_size

0 commit comments

Comments
 (0)