From: Tulio A M Mendes Date: Sun, 15 Feb 2026 01:05:30 +0000 (-0300) Subject: feat: POSIX message queues (mq_open, mq_close, mq_send, mq_receive, mq_unlink) X-Git-Url: https://projects.tadryanom.me/docs/static/git-logo.png?a=commitdiff_plain;h=cf18b6a1ac8456026f087280ebe0e59c02bdbaaa;p=AdrOS.git feat: POSIX message queues (mq_open, mq_close, mq_send, mq_receive, mq_unlink) - 8 named queues, 16 messages x 256 bytes each - Spinlock-protected circular buffer per queue - SYSCALL_MQ_OPEN=97, MQ_CLOSE=98, MQ_SEND=99, MQ_RECEIVE=100, MQ_UNLINK=101 - Added EMSGSIZE errno (90) - 35/35 smoke tests pass, cppcheck clean --- diff --git a/include/errno.h b/include/errno.h index ec682f4..77335b1 100644 --- a/include/errno.h +++ b/include/errno.h @@ -37,6 +37,7 @@ #define ETIMEDOUT 60 #define ENOLCK 37 #define EBUSY 16 +#define EMSGSIZE 90 #define EWOULDBLOCK EAGAIN #endif diff --git a/include/syscall.h b/include/syscall.h index 3baebe9..532d720 100644 --- a/include/syscall.h +++ b/include/syscall.h @@ -120,6 +120,11 @@ enum { SYSCALL_WAITID = 94, SYSCALL_SIGQUEUE = 95, SYSCALL_POSIX_SPAWN = 96, + SYSCALL_MQ_OPEN = 97, + SYSCALL_MQ_CLOSE = 98, + SYSCALL_MQ_SEND = 99, + SYSCALL_MQ_RECEIVE = 100, + SYSCALL_MQ_UNLINK = 101, }; #endif diff --git a/src/kernel/syscall.c b/src/kernel/syscall.c index a4b6dbe..6e388b8 100644 --- a/src/kernel/syscall.c +++ b/src/kernel/syscall.c @@ -64,6 +64,135 @@ enum { FD_CLOEXEC = 1, }; +/* --- POSIX message queues --- */ +#define MQ_MAX_QUEUES 8 +#define MQ_MAX_MSGS 16 +#define MQ_MSG_SIZE 256 + +struct mq_msg { + uint8_t data[MQ_MSG_SIZE]; + uint32_t len; + uint32_t prio; +}; + +struct mq_queue { + int active; + char name[32]; + struct mq_msg msgs[MQ_MAX_MSGS]; + uint32_t head; + uint32_t tail; + uint32_t count; + uint32_t maxmsg; + uint32_t msgsize; +}; + +static struct mq_queue mq_table[MQ_MAX_QUEUES]; +static spinlock_t mq_lock = {0}; + +static int mq_find_by_name(const char* name) { + for (int i = 0; i < MQ_MAX_QUEUES; i++) { + if (mq_table[i].active && strcmp(mq_table[i].name, name) == 0) + return i; + } + return -1; +} + +static int syscall_mq_open_impl(const char* user_name, uint32_t oflag) { + char name[32]; + if (copy_from_user(name, user_name, 31) < 0) return -EFAULT; + name[31] = 0; + + uintptr_t fl = spin_lock_irqsave(&mq_lock); + int idx = mq_find_by_name(name); + if (idx >= 0) { + spin_unlock_irqrestore(&mq_lock, fl); + return idx; + } + if (!(oflag & 0x40U)) { /* O_CREAT */ + spin_unlock_irqrestore(&mq_lock, fl); + return -ENOENT; + } + for (int i = 0; i < MQ_MAX_QUEUES; i++) { + if (!mq_table[i].active) { + memset(&mq_table[i], 0, sizeof(mq_table[i])); + mq_table[i].active = 1; + strcpy(mq_table[i].name, name); + mq_table[i].maxmsg = MQ_MAX_MSGS; + mq_table[i].msgsize = MQ_MSG_SIZE; + spin_unlock_irqrestore(&mq_lock, fl); + return i; + } + } + spin_unlock_irqrestore(&mq_lock, fl); + return -ENOSPC; +} + +static int syscall_mq_close_impl(int mqd) { + (void)mqd; + return 0; +} + +static int syscall_mq_send_impl(int mqd, const void* user_buf, uint32_t len, uint32_t prio) { + if (mqd < 0 || mqd >= MQ_MAX_QUEUES) return -EBADF; + if (len > MQ_MSG_SIZE) return -EMSGSIZE; + + uintptr_t fl = spin_lock_irqsave(&mq_lock); + struct mq_queue* q = &mq_table[mqd]; + if (!q->active) { spin_unlock_irqrestore(&mq_lock, fl); return -EBADF; } + if (q->count >= q->maxmsg) { spin_unlock_irqrestore(&mq_lock, fl); return -EAGAIN; } + + struct mq_msg* m = &q->msgs[q->tail]; + spin_unlock_irqrestore(&mq_lock, fl); + + if (copy_from_user(m->data, user_buf, len) < 0) return -EFAULT; + m->len = len; + m->prio = prio; + + fl = spin_lock_irqsave(&mq_lock); + q->tail = (q->tail + 1) % q->maxmsg; + q->count++; + spin_unlock_irqrestore(&mq_lock, fl); + return 0; +} + +static int syscall_mq_receive_impl(int mqd, void* user_buf, uint32_t len, uint32_t* user_prio) { + if (mqd < 0 || mqd >= MQ_MAX_QUEUES) return -EBADF; + + uintptr_t fl = spin_lock_irqsave(&mq_lock); + struct mq_queue* q = &mq_table[mqd]; + if (!q->active) { spin_unlock_irqrestore(&mq_lock, fl); return -EBADF; } + if (q->count == 0) { spin_unlock_irqrestore(&mq_lock, fl); return -EAGAIN; } + + struct mq_msg* m = &q->msgs[q->head]; + uint32_t mlen = m->len; + uint32_t mprio = m->prio; + if (mlen > len) mlen = len; + + q->head = (q->head + 1) % q->maxmsg; + q->count--; + spin_unlock_irqrestore(&mq_lock, fl); + + if (copy_to_user(user_buf, m->data, mlen) < 0) return -EFAULT; + if (user_prio) { + if (user_range_ok(user_prio, 4)) + (void)copy_to_user(user_prio, &mprio, 4); + } + return (int)mlen; +} + +static int syscall_mq_unlink_impl(const char* user_name) { + char name[32]; + if (copy_from_user(name, user_name, 31) < 0) return -EFAULT; + name[31] = 0; + + uintptr_t fl = spin_lock_irqsave(&mq_lock); + int idx = mq_find_by_name(name); + if (idx < 0) { spin_unlock_irqrestore(&mq_lock, fl); return -ENOENT; } + mq_table[idx].active = 0; + spin_unlock_irqrestore(&mq_lock, fl); + return 0; +} + /* --- Advisory file locking (flock) --- */ enum { FLOCK_SH = 1, @@ -3392,6 +3521,33 @@ static void socket_syscall_dispatch(struct registers* regs, uint32_t syscall_no) return; } + if (syscall_no == SYSCALL_MQ_OPEN) { + const char* name = (const char*)sc_arg0(regs); + uint32_t oflag = sc_arg1(regs); + sc_ret(regs) = (uint32_t)syscall_mq_open_impl(name, oflag); + return; + } + if (syscall_no == SYSCALL_MQ_CLOSE) { + sc_ret(regs) = (uint32_t)syscall_mq_close_impl((int)sc_arg0(regs)); + return; + } + if (syscall_no == SYSCALL_MQ_SEND) { + sc_ret(regs) = (uint32_t)syscall_mq_send_impl( + (int)sc_arg0(regs), (const void*)sc_arg1(regs), + sc_arg2(regs), sc_arg3(regs)); + return; + } + if (syscall_no == SYSCALL_MQ_RECEIVE) { + sc_ret(regs) = (uint32_t)syscall_mq_receive_impl( + (int)sc_arg0(regs), (void*)sc_arg1(regs), + sc_arg2(regs), (uint32_t*)sc_arg3(regs)); + return; + } + if (syscall_no == SYSCALL_MQ_UNLINK) { + sc_ret(regs) = (uint32_t)syscall_mq_unlink_impl((const char*)sc_arg0(regs)); + return; + } + sc_ret(regs) = (uint32_t)-ENOSYS; }