Skip to content

Commit 0f7eb02

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 364cbb8 commit 0f7eb02

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
@@ -1,6 +1,7 @@
11
#include <lib/libc.h>
22
#include <sys/task.h>
33
#include <types.h>
4+
#include <spinlock.h>
45

56
#include "private/utils.h"
67

@@ -24,6 +25,8 @@ typedef struct __memblock {
2425
static memblock_t *first_free;
2526
static void *heap_start, *heap_end;
2627
static uint32_t free_blocks_count; /* track fragmentation */
28+
static spinlock_t malloc_lock = SPINLOCK_INITIALIZER;
29+
static uint32_t malloc_flags = 0;
2730

2831
/* Block manipulation macros */
2932
#define IS_USED(b) ((b)->size & 1L)
@@ -62,13 +65,13 @@ void free(void *ptr)
6265
if (!ptr)
6366
return;
6467

65-
CRITICAL_ENTER();
68+
spin_lock_irqsave(&malloc_lock, &malloc_flags);
6669

6770
memblock_t *p = ((memblock_t *) ptr) - 1;
6871

6972
/* Validate the block being freed */
7073
if (!validate_block(p) || !IS_USED(p)) {
71-
CRITICAL_LEAVE();
74+
spin_unlock_irqrestore(&malloc_lock, malloc_flags);
7275
return; /* Invalid or double-free */
7376
}
7477

@@ -100,7 +103,7 @@ void free(void *ptr)
100103
free_blocks_count--;
101104
}
102105

103-
CRITICAL_LEAVE();
106+
spin_unlock_irqrestore(&malloc_lock, malloc_flags);
104107
}
105108

106109
/* Selective coalescing: only when fragmentation becomes significant */
@@ -136,7 +139,7 @@ void *malloc(uint32_t size)
136139
if (size < MALLOC_MIN_SIZE)
137140
size = MALLOC_MIN_SIZE;
138141

139-
CRITICAL_ENTER();
142+
spin_lock_irqsave(&malloc_lock, &malloc_flags);
140143

141144
/* Trigger coalescing only when fragmentation is high */
142145
if (free_blocks_count > COALESCE_THRESHOLD)
@@ -145,7 +148,7 @@ void *malloc(uint32_t size)
145148
memblock_t *p = first_free;
146149
while (p) {
147150
if (!validate_block(p)) {
148-
CRITICAL_LEAVE();
151+
spin_unlock_irqrestore(&malloc_lock, malloc_flags);
149152
return NULL; /* Heap corruption detected */
150153
}
151154

@@ -168,13 +171,13 @@ void *malloc(uint32_t size)
168171
if (free_blocks_count > 0)
169172
free_blocks_count--;
170173

171-
CRITICAL_LEAVE();
174+
spin_unlock_irqrestore(&malloc_lock, malloc_flags);
172175
return (void *) (p + 1);
173176
}
174177
p = p->next;
175178
}
176179

177-
CRITICAL_LEAVE();
180+
spin_unlock_irqrestore(&malloc_lock, malloc_flags);
178181
return NULL; /* allocation failed */
179182
}
180183

0 commit comments

Comments
 (0)