Skip to content

Commit 8fb7d12

Browse files
named constants for buddy init
1 parent a373436 commit 8fb7d12

12 files changed

Lines changed: 154 additions & 47 deletions

File tree

include/basic/tokenizer.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -268,7 +268,7 @@ void tokenizer_next(struct basic_ctx* ctx);
268268
* @param ctx context
269269
* @return int token
270270
*/
271-
enum token_t tokenizer_token(struct basic_ctx* ctx);
271+
#define tokenizer_token(ctx) ((enum token_t)ctx->current_token)
272272

273273
/**
274274
* @brief Get integer number as next token
@@ -307,7 +307,7 @@ const char* tokenizer_variable_name(struct basic_ctx* ctx, size_t* count);
307307
* @param ctx context
308308
* @return int true if the program has finished
309309
*/
310-
bool tokenizer_finished(struct basic_ctx* ctx);
310+
#define tokenizer_finished(ctx) (*ctx->ptr == 0 || ctx->current_token == ENDOFINPUT)
311311

312312
/**
313313
* @brief display an error to the terminal and end the program

include/buddy_allocator.h

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,36 @@
3131
#include <stddef.h>
3232
#include <stdint.h>
3333

34+
typedef enum buddy_order {
35+
buddy_32b = 5,
36+
buddy_64b = 6,
37+
buddy_128b = 7,
38+
buddy_256b = 8,
39+
buddy_512b = 9,
40+
buddy_1kb = 10,
41+
buddy_2kb = 11,
42+
buddy_4kb = 12,
43+
buddy_8kb = 13,
44+
buddy_16kb = 14,
45+
buddy_32kb = 15,
46+
buddy_64kb = 16,
47+
buddy_128kb = 17,
48+
buddy_256kb = 18,
49+
buddy_512kb = 19,
50+
buddy_1mb = 20,
51+
buddy_2mb = 21,
52+
buddy_4mb = 22,
53+
buddy_8mb = 23,
54+
buddy_16mb = 24,
55+
buddy_32mb = 25,
56+
buddy_64mb = 26,
57+
buddy_128mb = 27,
58+
buddy_256mb = 28,
59+
buddy_512mb = 29
60+
} buddy_order_t;
61+
62+
#define BUDDY_MAX_ORDER buddy_512mb
63+
#define BUDDY_MIN_ORDER buddy_32b
3464

3565
/**
3666
* @brief Block header used for both free list nodes and allocated blocks.
@@ -127,6 +157,45 @@ void* buddy_malloc(buddy_allocator_t* alloc, size_t size);
127157
*/
128158
void buddy_free(buddy_allocator_t* alloc, const void *ptr);
129159

160+
/**
161+
* @brief Allocate an aligned block of memory from the buddy allocator.
162+
*
163+
* @param alloc Allocator instance to allocate from.
164+
* @param size Requested size in bytes.
165+
* @param align Required alignment in bytes (power of two).
166+
* @return Pointer to aligned memory, or NULL if out of memory.
167+
*
168+
* @note If align <= 8, this function behaves identically to buddy_malloc()
169+
* and returns a pointer aligned to at least 8 bytes.
170+
*
171+
* @note For align > 8, additional space is allocated and the returned pointer
172+
* is adjusted to satisfy the requested alignment. The original allocation
173+
* pointer is stored internally and must be released using
174+
* buddy_free_aligned().
175+
*
176+
* @note The minimum guaranteed alignment of all allocations from the buddy
177+
* allocator is 8 bytes, determined by sizeof(buddy_header_t).
178+
*/
179+
void* buddy_malloc_aligned(buddy_allocator_t* alloc, size_t size, size_t align);
180+
181+
/**
182+
* @brief Free memory allocated by buddy_malloc_aligned().
183+
*
184+
* @param alloc Allocator instance.
185+
* @param ptr Pointer previously returned by buddy_malloc_aligned().
186+
* @param align Alignment value originally passed to buddy_malloc_aligned().
187+
*
188+
* @note The align argument must match the value used for allocation.
189+
*
190+
* @note If align <= 8, this function behaves identically to buddy_free(),
191+
* because buddy_malloc_aligned() does not adjust the returned pointer
192+
* for alignments already guaranteed by the allocator.
193+
*
194+
* @note Passing a different alignment value from the one used at allocation
195+
* time results in undefined behaviour.
196+
*/
197+
void buddy_free_aligned(buddy_allocator_t* alloc, void* ptr, size_t align);
198+
130199
/**
131200
* @brief Destroy a buddy allocator and free all regions.
132201
*

modules/virtio_net/virtio_net.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -291,7 +291,7 @@ bool virtio_send_packet(void *data, uint16_t len) {
291291

292292
memset(hdr, 0, VNET_HDR_SIZE);
293293

294-
void *pay = buddy_malloc(&tx_buffer_allocator, len);
294+
void *pay = buddy_malloc_aligned(&tx_buffer_allocator, len, 16);
295295
if (!pay) {
296296
virtq_free_desc(tq, (uint16_t) h);
297297
virtq_free_desc(tq, (uint16_t) p);
@@ -326,7 +326,7 @@ static void vnet_tx_complete(void) {
326326

327327
void* paybuf = (void *) (uintptr_t) tq->desc[pay].addr;
328328
if (paybuf) {
329-
buddy_free(&tx_buffer_allocator, paybuf);
329+
buddy_free_aligned(&tx_buffer_allocator, paybuf, 16);
330330
}
331331

332332
virtq_free_desc(tq, pay);
@@ -443,7 +443,7 @@ bool EXPORTED MOD_INIT_SYM(KMOD_ABI)(void) {
443443
return false;
444444
}
445445
/* We use a buddy allocator for TX buffer as it is faster and aligned as standard */
446-
buddy_init(&tx_buffer_allocator, 6, 22, 22);
446+
buddy_init(&tx_buffer_allocator, buddy_64b, buddy_4mb, buddy_4mb);
447447
if (!virtio_net_start(&dev)) {
448448
return false;
449449
}

src/acpi.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ void init_uacpi(void) {
9393
mhz = tsc_per_sec / 1000000;
9494
dprintf("mhz = %lu, tsc_per_sec = %lu\n", mhz, tsc_per_sec);
9595

96-
buddy_init(&acpi_pool, 6, 22, 22);
96+
buddy_init(&acpi_pool, buddy_64b, buddy_4mb, buddy_4mb);
9797

9898
uacpi_context_set_log_level(UACPI_LOG_INFO);
9999
st = uacpi_initialize(0);

src/basic/flow_control.c

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -97,23 +97,18 @@ void error_statement(struct basic_ctx* ctx)
9797

9898
void if_statement(struct basic_ctx* ctx)
9999
{
100-
basic_debug("line %ld if_statement\n", ctx->current_linenum);
101-
102100
accept_or_return(IF, ctx);
103101
bool r = conditional(ctx);
104102
accept_or_return(THEN, ctx);
105103

106104
if (r) {
107-
basic_debug("conditional is true\n");
108105
if (tokenizer_token(ctx) == NEWLINE) {
109106
/* Multi-statement block IF */
110107
accept_or_return(NEWLINE, ctx);
111108
return;
112109
}
113110
statement(ctx);
114111
} else {
115-
basic_debug("conditional is false\n");
116-
117112
if (tokenizer_token(ctx) == NEWLINE) {
118113
/* --- multiline false-branch with nesting --- */
119114
/* Enter the block and scan forward once, respecting nested multiline IFs */

src/basic/main.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -941,7 +941,7 @@ void basic_run(struct basic_ctx *ctx) {
941941
return;
942942
}
943943
/* TODO Make sure this only runs for foreground processes! */
944-
if (basic_esc() && !ctx->errored) {
944+
if (!ctx->errored && basic_esc()) {
945945
kgetc();
946946
tokenizer_error_print(ctx, "Escape");
947947
return;

src/basic/statement.c

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,16 @@ void statement(struct basic_ctx* ctx)
99
GENERATE_ENUM_STRING_NAMES(TOKEN, token_names)
1010
GENERATE_ENUM_STRING_LENGTHS(TOKEN, token_name_lengths)
1111
enum token_t token = tokenizer_token(ctx);
12-
if (token < DISPATCH_TABLE_COUNT(dispatch_by_token)) {
13-
if (dispatch_by_token[token] != NULL) {
14-
if (is_restricted_len(ctx, token_names[token], token_name_lengths[token])) {
15-
tokenizer_error_printf(ctx, "Keyword '%s' is restricted by parent program", token_names[token]);
16-
return;
17-
}
18-
dispatch_by_token[token](ctx);
12+
if (dispatch_by_token[token] != NULL) {
13+
if (is_restricted_len(ctx, token_names[token], token_name_lengths[token])) {
14+
tokenizer_error_printf(ctx, "Keyword '%s' is restricted by parent program", token_names[token]);
1915
return;
2016
}
17+
dispatch_by_token[token](ctx);
18+
return;
19+
} else if (token != NO_TOKEN) {
20+
tokenizer_error_printf(ctx, "Keyword %s can't be used here", token_names[token]);
21+
return;
2122
}
2223

2324
dprintf("Unknown keyword: %d\n", token);
@@ -26,14 +27,12 @@ void statement(struct basic_ctx* ctx)
2627

2728
void line_statement(struct basic_ctx* ctx)
2829
{
29-
basic_debug("line_statement\n");
3030
if (tokenizer_token(ctx) == NEWLINE) {
3131
/* Empty line! */
3232
accept(NEWLINE, ctx);
3333
return;
3434
}
3535
int64_t line = tokenizer_num(ctx, NUMBER);
36-
basic_debug("line_statement parsed line %ld\n", line);
3736
if (line == 0) {
3837
return tokenizer_error_printf(ctx, "Missing line number after line %lu: %s", ctx->current_linenum, ctx->ptr);
3938
}

src/basic/tokenizer.c

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ static int interned_name_compare(const void *a, const void *b, void *udata)
110110
static bool ensure_interned_variable_names(void)
111111
{
112112
if (!interned_variable_name_allocator_ready) {
113-
buddy_init(&interned_variable_name_allocator, 6, 22, 22);
113+
buddy_init(&interned_variable_name_allocator, buddy_64b, buddy_4mb, buddy_4mb);
114114
interned_variable_name_allocator_ready = true;
115115
}
116116

@@ -379,12 +379,11 @@ int get_next_token(struct basic_ctx* ctx)
379379
}
380380
}
381381

382-
if ((*ctx->ptr >= 'a' && *ctx->ptr <= 'z') || (*ctx->ptr >= 'A' && *ctx->ptr <= 'Z') || *ctx->ptr == '_') {
382+
if (isalpha(*ctx->ptr) || *ctx->ptr == '_') {
383383
ctx->nextptr = ctx->ptr;
384384
int varl = 0;
385385
while (
386-
(*ctx->nextptr >= 'a' && *ctx->nextptr <= 'z') ||
387-
(*ctx->nextptr >= 'A' && *ctx->nextptr <= 'Z') ||
386+
isalpha(*ctx->nextptr) ||
388387
(*ctx->nextptr == '_') ||
389388
(varl > 0 && *ctx->nextptr == '$') ||
390389
(varl > 0 && *ctx->nextptr == '#') ||
@@ -425,11 +424,6 @@ void tokenizer_init(const char *program, struct basic_ctx* ctx)
425424
ctx->current_token = get_next_token(ctx);
426425
}
427426

428-
enum token_t tokenizer_token(struct basic_ctx* ctx)
429-
{
430-
return ctx->current_token;
431-
}
432-
433427
void tokenizer_next(struct basic_ctx* ctx)
434428
{
435429
if (tokenizer_finished(ctx)) {
@@ -557,11 +551,6 @@ void tokenizer_error_print(struct basic_ctx* ctx, const char* error)
557551
}
558552
}
559553

560-
bool tokenizer_finished(struct basic_ctx* ctx)
561-
{
562-
return *ctx->ptr == 0 || ctx->current_token == ENDOFINPUT;
563-
}
564-
565554
const char* tokenizer_variable_name(struct basic_ctx* ctx, size_t* count)
566555
{
567556
char varname[MAX_VARNAME];

src/buddy_allocator.c

Lines changed: 64 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,6 @@
22
#include <stddef.h>
33
#include <kernel.h>
44

5-
#define BUDDY_MAX_ORDER 29
6-
#define BUDDY_MIN_ORDER 6
7-
85
static inline size_t order_size(int order) {
96
return (size_t)1 << order;
107
}
@@ -87,14 +84,15 @@ static buddy_region_t *buddy_grow(buddy_allocator_t *alloc) {
8784
}
8885

8986
size_t size = 1UL << grow;
90-
void *pool = kmalloc(size);
87+
void *pool = kmalloc_aligned(size, 8);
9188
if (!pool) {
9289
return NULL;
9390
}
9491

95-
buddy_region_t *region = (buddy_region_t *)kmalloc(sizeof(buddy_region_t));
92+
buddy_region_t *region = (buddy_region_t *)kmalloc_aligned(sizeof(buddy_region_t), 8);
9693
if (!region) {
97-
kfree_null(&pool);
94+
kfree_aligned(pool);
95+
pool = NULL;
9896
return NULL;
9997
}
10098

@@ -200,6 +198,62 @@ void *buddy_malloc(buddy_allocator_t *alloc, size_t size) {
200198
return NULL; // completely out of memory
201199
}
202200

201+
void* buddy_malloc_aligned(buddy_allocator_t* alloc, size_t size, size_t align)
202+
{
203+
if (!alloc || size == 0) {
204+
return NULL;
205+
}
206+
207+
if (align <= 8) {
208+
return buddy_malloc(alloc, size);
209+
}
210+
211+
if ((align & (align - 1)) != 0) {
212+
dprintf("buddy_malloc_aligned: alignment must be power of two (got %lu)\n", align);
213+
return NULL;
214+
}
215+
216+
/* allocate extra space for alignment slack + pointer storage */
217+
size_t total = size + align - 1 + sizeof(void*);
218+
uint8_t* raw = (uint8_t*)buddy_malloc(alloc, total);
219+
if (!raw) {
220+
return NULL;
221+
}
222+
223+
uintptr_t aligned = ((uintptr_t)(raw + sizeof(void*) + (align - 1))) & ~(uintptr_t)(align - 1);
224+
225+
/* store original pointer just before aligned block */
226+
void** save = (void**)aligned;
227+
save[-1] = raw;
228+
229+
return (void*)aligned;
230+
}
231+
232+
void buddy_free_aligned(buddy_allocator_t* alloc, void* ptr, size_t align)
233+
{
234+
if (!alloc || !ptr) {
235+
return;
236+
}
237+
238+
if (align <= 8) {
239+
buddy_free(alloc, ptr);
240+
return;
241+
}
242+
243+
if ((align & (align - 1)) != 0) {
244+
dprintf("buddy_free_aligned: alignment must be power of two (got %lu)\n", align);
245+
return;
246+
}
247+
248+
void** save = (void**)ptr;
249+
if (!save[-1]) {
250+
dprintf("buddy_free_aligned: missing backing pointer\n");
251+
return;
252+
}
253+
254+
buddy_free(alloc, save[-1]);
255+
}
256+
203257
void buddy_free(buddy_allocator_t *alloc, const void *ptr) {
204258
if (!ptr || !alloc) {
205259
return;
@@ -270,8 +324,10 @@ void buddy_destroy(buddy_allocator_t *alloc) {
270324
while (r) {
271325
buddy_region_t *next = r->next;
272326

273-
kfree_null(&r->pool); // free the pool and null it
274-
kfree_null(&r); // free the region struct itself and null that pointer
327+
kfree_aligned(r->pool); // free the pool and null it
328+
kfree_aligned(r); // free the region struct itself and null that pointer
329+
r->pool = NULL;
330+
r = NULL;
275331

276332
r = next; // use the saved "next" to continue traversal
277333
}

src/devicename.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,7 @@
33

44
struct hashmap* prefix_hash = NULL;
55

6-
int string_compare(const void *a, const void *b, [[maybe_unused]]
7-
__attribute__((unused)) void *udata) {
6+
int string_compare(const void *a, const void *b, [[maybe_unused]] __attribute__((unused)) void *udata) {
87
const devname_prefix_t* ua = a;
98
const devname_prefix_t* ub = b;
109
return strcmp(ua->prefix, ub->prefix);

0 commit comments

Comments
 (0)