Skip to content

Commit 075a90c

Browse files
committed
Replace interrupt masking with spinlock in mqueue for SMP support
The original message queue implementation used CRITICAL_ENTER() and CRITICAL_LEAVE() to protect critical sections by disabling interrupts. This was sufficient for single-core systems, where only one hart could execute tasks. To support SMP, we replace these macros with a proper spinlock using RV32A atomic instructions. This ensures safe access to the internal queue structures when multiple harts concurrently interact with message queues. This change eliminates potential race conditions in message queue operations as we move toward multi-hart scheduling.
1 parent 0f7eb02 commit 075a90c

File tree

1 file changed

+14
-9
lines changed

1 file changed

+14
-9
lines changed

kernel/mqueue.c

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,13 @@
66
#include <sys/mqueue.h>
77
#include <sys/task.h>
88

9+
#include <spinlock.h>
10+
911
#include "private/error.h"
1012

13+
static spinlock_t queue_lock = SPINLOCK_INITIALIZER;
14+
static uint32_t queue_flags = 0;
15+
1116
mq_t *mo_mq_create(uint16_t max_items)
1217
{
1318
mq_t *mq = malloc(sizeof *mq);
@@ -24,27 +29,27 @@ mq_t *mo_mq_create(uint16_t max_items)
2429

2530
int32_t mo_mq_destroy(mq_t *mq)
2631
{
27-
CRITICAL_ENTER();
32+
spin_lock_irqsave(&queue_lock, &queue_flags);
2833

2934
if (queue_count(mq->q) != 0) { /* refuse to destroy non-empty q */
30-
CRITICAL_LEAVE();
35+
spin_unlock_irqrestore(&queue_lock, queue_flags);
3136
return ERR_MQ_NOTEMPTY;
3237
}
3338

3439
queue_destroy(mq->q);
3540
free(mq);
3641

37-
CRITICAL_LEAVE();
42+
spin_unlock_irqrestore(&queue_lock, queue_flags);
3843
return ERR_OK;
3944
}
4045

4146
int32_t mo_mq_enqueue(mq_t *mq, message_t *msg)
4247
{
4348
int32_t rc;
4449

45-
CRITICAL_ENTER();
50+
spin_lock_irqsave(&queue_lock, &queue_flags);
4651
rc = queue_enqueue(mq->q, msg);
47-
CRITICAL_LEAVE();
52+
spin_unlock_irqrestore(&queue_lock, queue_flags);
4853

4954
return rc; /* 0 on success, −1 on full */
5055
}
@@ -54,9 +59,9 @@ message_t *mo_mq_dequeue(mq_t *mq)
5459
{
5560
message_t *msg;
5661

57-
CRITICAL_ENTER();
62+
spin_lock_irqsave(&queue_lock, &queue_flags);
5863
msg = queue_dequeue(mq->q);
59-
CRITICAL_LEAVE();
64+
spin_unlock_irqrestore(&queue_lock, queue_flags);
6065

6166
return msg; /* NULL when queue is empty */
6267
}
@@ -66,9 +71,9 @@ message_t *mo_mq_peek(mq_t *mq)
6671
{
6772
message_t *msg;
6873

69-
CRITICAL_ENTER();
74+
spin_lock_irqsave(&queue_lock, &queue_flags);
7075
msg = queue_peek(mq->q);
71-
CRITICAL_LEAVE();
76+
spin_unlock_irqrestore(&queue_lock, queue_flags);
7277

7378
return msg; /* NULL when queue is empty */
7479
}

0 commit comments

Comments
 (0)