Skip to content

Commit 5373f8f

Browse files
committed
Replace interrupt masking with spinlock in malloc for SMP support
The original malloc/free implementation used CRITICAL_ENTER() and CRITICAL_LEAVE() to protect critical sections by simply disabling interrupts, which is sufficient on single-core systems. To support SMP, we replace these with a proper spinlock that uses RV32A atomic instructions. This ensures correctness when multiple harts access the allocator concurrently. This change allows future task scheduling across multiple harts without risking race conditions in the memory allocator.
1 parent ab14de1 commit 5373f8f

File tree

1 file changed

+10
-7
lines changed

1 file changed

+10
-7
lines changed

lib/malloc.c

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include <lib/libc.h>
44
#include <sys/task.h>
55
#include <types.h>
6+
#include <spinlock.h>
67

78
#include "private/utils.h"
89

@@ -26,6 +27,8 @@ typedef struct __memblock {
2627
static memblock_t *first_free;
2728
static void *heap_start, *heap_end;
2829
static uint32_t free_blocks_count; /* track fragmentation */
30+
static spinlock_t malloc_lock = SPINLOCK_INITIALIZER;
31+
static uint32_t malloc_flags = 0;
2932

3033
/* Block manipulation macros */
3134
#define IS_USED(b) ((b)->size & 1L)
@@ -64,13 +67,13 @@ void free(void *ptr)
6467
if (!ptr)
6568
return;
6669

67-
CRITICAL_ENTER();
70+
spin_lock_irqsave(&malloc_lock, &malloc_flags);
6871

6972
memblock_t *p = ((memblock_t *) ptr) - 1;
7073

7174
/* Validate the block being freed */
7275
if (!validate_block(p) || !IS_USED(p)) {
73-
CRITICAL_LEAVE();
76+
spin_unlock_irqrestore(&malloc_lock, malloc_flags);
7477
return; /* Invalid or double-free */
7578
}
7679

@@ -102,7 +105,7 @@ void free(void *ptr)
102105
free_blocks_count--;
103106
}
104107

105-
CRITICAL_LEAVE();
108+
spin_unlock_irqrestore(&malloc_lock, malloc_flags);
106109
}
107110

108111
/* Selective coalescing: only when fragmentation becomes significant */
@@ -138,7 +141,7 @@ void *malloc(uint32_t size)
138141
if (size < MALLOC_MIN_SIZE)
139142
size = MALLOC_MIN_SIZE;
140143

141-
CRITICAL_ENTER();
144+
spin_lock_irqsave(&malloc_lock, &malloc_flags);
142145

143146
/* Trigger coalescing only when fragmentation is high */
144147
if (free_blocks_count > COALESCE_THRESHOLD)
@@ -147,7 +150,7 @@ void *malloc(uint32_t size)
147150
memblock_t *p = first_free;
148151
while (p) {
149152
if (!validate_block(p)) {
150-
CRITICAL_LEAVE();
153+
spin_unlock_irqrestore(&malloc_lock, malloc_flags);
151154
return NULL; /* Heap corruption detected */
152155
}
153156

@@ -170,13 +173,13 @@ void *malloc(uint32_t size)
170173
if (free_blocks_count > 0)
171174
free_blocks_count--;
172175

173-
CRITICAL_LEAVE();
176+
spin_unlock_irqrestore(&malloc_lock, malloc_flags);
174177
return (void *) (p + 1);
175178
}
176179
p = p->next;
177180
}
178181

179-
CRITICAL_LEAVE();
182+
spin_unlock_irqrestore(&malloc_lock, malloc_flags);
180183
return NULL; /* allocation failed */
181184
}
182185

0 commit comments

Comments
 (0)