Skip to content

Commit c508a38

Browse files
authored
Merge pull request #210 from AW-AlanWu/chore/arena
Add arena helper functions and improve block insertion
2 parents 7163605 + 4be720b commit c508a38

File tree

1 file changed

+148
-36
lines changed

1 file changed

+148
-36
lines changed

src/globals.c

Lines changed: 148 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,6 @@ int elf_data_start;
8989

9090
/**
9191
* arena_block_create() - Creates a new arena block with given capacity.
92-
* The created arena block is guaranteed to be zero-initialized.
9392
* @capacity: The capacity of the arena block. Must be positive.
9493
*
9594
* Return: The pointer of created arena block. NULL if failed to allocate.
@@ -99,16 +98,16 @@ arena_block_t *arena_block_create(int capacity)
9998
arena_block_t *block = malloc(sizeof(arena_block_t));
10099

101100
if (!block) {
102-
printf("Failed to allocate memory for arena block\n");
103-
exit(1);
101+
printf("Failed to allocate memory for arena block structure\n");
102+
abort();
104103
}
105104

106-
block->memory = calloc(capacity, sizeof(char));
105+
block->memory = malloc(capacity * sizeof(char));
107106

108107
if (!block->memory) {
109-
printf("Failed to allocate memory for arena block\n");
108+
printf("Failed to allocate memory for arena block buffer\n");
110109
free(block);
111-
exit(1);
110+
abort();
112111
}
113112

114113
block->capacity = capacity;
@@ -117,6 +116,16 @@ arena_block_t *arena_block_create(int capacity)
117116
return block;
118117
}
119118

119+
/**
120+
* arena_block_free() - Free a single arena block and its memory buffer.
121+
* @block: Pointer to the arena_block_t to free. Must not be NULL.
122+
*/
123+
void arena_block_free(arena_block_t *block)
124+
{
125+
free(block->memory);
126+
free(block);
127+
}
128+
120129
/**
121130
* arena_init() - Initializes the given arena with initial capacity.
122131
* @initial_capacity: The initial capacity of the arena. Must be positive.
@@ -126,6 +135,10 @@ arena_block_t *arena_block_create(int capacity)
126135
arena_t *arena_init(int initial_capacity)
127136
{
128137
arena_t *arena = malloc(sizeof(arena_t));
138+
if (!arena) {
139+
printf("Failed to allocate memory for arena structure\n");
140+
abort();
141+
}
129142
arena->head = arena_block_create(initial_capacity);
130143
return arena;
131144
}
@@ -141,47 +154,147 @@ arena_t *arena_init(int initial_capacity)
141154
*/
142155
void *arena_alloc(arena_t *arena, int size)
143156
{
144-
char *ptr;
145-
arena_block_t *block = arena->head;
157+
if (size <= 0) {
158+
printf("arena_alloc: size must be positive\n");
159+
abort();
160+
}
146161

147-
while (block) {
148-
if (block->offset + size <= block->capacity) {
149-
ptr = block->memory + block->offset;
150-
block->offset += size;
151-
return ptr;
152-
}
153-
if (!block->next)
154-
break;
155-
block = block->next;
162+
/* Align to PTR_SIZE bytes */
163+
size = (size + PTR_SIZE - 1) & ~(PTR_SIZE - 1);
164+
165+
if (!arena->head || arena->head->offset + size > arena->head->capacity) {
166+
/* Need a new block: choose capacity = max(DEFAULT_ARENA_SIZE, size) */
167+
int new_capacity =
168+
(size > DEFAULT_ARENA_SIZE ? size : DEFAULT_ARENA_SIZE);
169+
arena_block_t *new_block = arena_block_create(new_capacity);
170+
new_block->next = arena->head;
171+
arena->head = new_block;
156172
}
157173

158-
/* If no space is available, create a new block
159-
* Allocate at least 256 KiB or the requested size
160-
*/
161-
int new_capacity = size > DEFAULT_ARENA_SIZE ? size : DEFAULT_ARENA_SIZE;
162-
arena_block_t *new_block = arena_block_create(new_capacity);
174+
void *ptr = arena->head->memory + arena->head->offset;
175+
arena->head->offset += size;
176+
return ptr;
177+
}
163178

164-
if (!new_block)
165-
return NULL;
179+
/**
180+
* arena_calloc() - arena_alloc() plus explicit zero‑initialization.
181+
* @arena: The arena to allocate memory from. Must not be NULL.
182+
* @n: Number of elements.
183+
* @size: Size of each element in bytes.
184+
*
185+
* Internally calls arena_alloc(n * size) and then fills the entire region
186+
* with zero bytes.
187+
*
188+
* Return: Pointer to zero-initialized memory.
189+
*/
190+
void *arena_calloc(arena_t *arena, int n, int size)
191+
{
192+
if (n * size == 0) {
193+
printf("arena_calloc: cannot allocate 0 bytes\n");
194+
abort();
195+
}
196+
197+
int total = n * size;
198+
void *ptr = arena_alloc(arena, total);
199+
200+
int *w_ptr = ptr;
201+
int w_count = total >> 2;
202+
int b_index = w_count << 2;
203+
204+
for (int i = 0; i < w_count; ++i)
205+
w_ptr[i] = 0;
206+
207+
char *b_ptr = ptr;
208+
while (b_index < total)
209+
b_ptr[b_index++] = 0;
166210

167-
block->next = new_block;
168-
ptr = new_block->memory + new_block->offset;
169-
new_block->offset += size;
170211
return ptr;
171212
}
172213

173214
/**
174-
* arena_reset() - Resets the given arena by resetting all blocks' offset to 0.
175-
* @arena: The arena to reset. Must not be NULL.
215+
* arena_realloc() - Reallocate a previously allocated region within the arena
216+
* to a different size.
217+
*
218+
* Behaviors:
219+
* 1. If oldptr == NULL and oldsz == 0, act like malloc.
220+
* 2. If newsz <= oldsz, return oldptr immediately.
221+
* 3. Grow in place if oldptr is the last allocation in the current block.
222+
* 4. Otherwise, allocate a new region and copy old data.
223+
*
224+
* @arena: Pointer to the arena. Must not be NULL.
225+
* @oldptr: Pointer to the previously allocated memory in the arena.
226+
* @oldsz: Original size (in bytes) of that allocation.
227+
* @newsz: New desired size (in bytes).
228+
*
229+
* Return: Pointer to the reallocated (resized) memory region.
176230
*/
177-
void arena_reset(arena_t *arena)
231+
void *arena_realloc(arena_t *arena, char *oldptr, int oldsz, int newsz)
178232
{
179-
arena_block_t *block = arena->head;
233+
/* act like malloc */
234+
if (oldptr == NULL) {
235+
if (oldsz != 0) {
236+
printf("arena_realloc: oldptr == NULL requires oldsz == 0\n");
237+
abort();
238+
}
239+
return arena_alloc(arena, newsz);
240+
}
241+
if (oldsz == 0) {
242+
printf("arena_realloc: oldptr != NULL requires oldsz > 0\n");
243+
abort();
244+
}
180245

181-
while (block) {
182-
block->offset = 0;
183-
block = block->next;
246+
/* return oldptr immediately */
247+
if (newsz <= oldsz) {
248+
return oldptr;
184249
}
250+
251+
/* From here on, oldptr != NULL and newsz > oldsz and oldsz != 0 */
252+
int delta = newsz - oldsz;
253+
arena_block_t *blk = arena->head;
254+
char *block_end = blk->memory + blk->offset;
255+
256+
/* grow in place if oldptr is the last allocation in the current block */
257+
if (oldptr + oldsz == block_end && blk->offset + delta <= blk->capacity) {
258+
blk->offset += delta;
259+
return oldptr;
260+
}
261+
262+
/* allocate a new region and copy old data */
263+
void *newptr = arena_alloc(arena, newsz);
264+
memcpy(newptr, oldptr, oldsz);
265+
return newptr;
266+
}
267+
268+
/**
269+
* arena_strdup() - Duplicate a NULL-terminated string into the arena.
270+
*
271+
* @arena: a Pointer to the arena. Must not be NULL.
272+
* @str: NULL-terminated input string to duplicate. Must not be NULL.
273+
*
274+
* Return: Pointer to the duplicated string stored in the arena.
275+
*/
276+
char *arena_strdup(arena_t *arena, char *str)
277+
{
278+
int n = strlen(str);
279+
char *dup = arena_alloc(arena, n + 1);
280+
memcpy(dup, str, n);
281+
dup[n] = '\0';
282+
return dup;
283+
}
284+
285+
/**
286+
* arena_memdup() - Duplicate a block of memory into the arena.
287+
* Allocates size bytes within the arena and copies data from the input pointer.
288+
*
289+
* @arena: a Pointer to the arena. Must not be NULL.
290+
* @data: data Pointer to the source memory. Must not be NULL.
291+
* @size: size Number of bytes to copy. Must be non-negative.
292+
*
293+
* Return: The pointer to the duplicated memory stored in the arena.
294+
*/
295+
void *arena_memdup(arena_t *arena, void *data, int size)
296+
{
297+
return memcpy(arena_alloc(arena, size), data, size);
185298
}
186299

187300
/**
@@ -194,8 +307,7 @@ void arena_free(arena_t *arena)
194307

195308
while (block) {
196309
next = block->next;
197-
free(block->memory);
198-
free(block);
310+
arena_block_free(block);
199311
block = next;
200312
}
201313

0 commit comments

Comments
 (0)