From: Tulio A M Mendes Date: Sun, 15 Feb 2026 01:09:55 +0000 (-0300) Subject: feat: POSIX named semaphores (sem_open, sem_close, sem_wait, sem_post, sem_unlink... X-Git-Url: https://projects.tadryanom.me/docs/static/gitweb.js?a=commitdiff_plain;h=81ac3048c5029faab70fa8e84062654306b5bb17;p=AdrOS.git feat: POSIX named semaphores (sem_open, sem_close, sem_wait, sem_post, sem_unlink, sem_getvalue) - 16 named semaphores with spinlock-protected value - sem_wait spins with process_sleep(1) until value > 0 - SYSCALL_SEM_OPEN=102 through SYSCALL_SEM_GETVALUE=107 - 35/35 smoke tests pass, cppcheck clean --- diff --git a/include/syscall.h b/include/syscall.h index 532d720..52dbf2c 100644 --- a/include/syscall.h +++ b/include/syscall.h @@ -125,6 +125,12 @@ enum { SYSCALL_MQ_SEND = 99, SYSCALL_MQ_RECEIVE = 100, SYSCALL_MQ_UNLINK = 101, + SYSCALL_SEM_OPEN = 102, + SYSCALL_SEM_CLOSE = 103, + SYSCALL_SEM_WAIT = 104, + SYSCALL_SEM_POST = 105, + SYSCALL_SEM_UNLINK = 106, + SYSCALL_SEM_GETVALUE = 107, }; #endif diff --git a/src/kernel/syscall.c b/src/kernel/syscall.c index 6e388b8..8dd98f6 100644 --- a/src/kernel/syscall.c +++ b/src/kernel/syscall.c @@ -193,6 +193,117 @@ static int syscall_mq_unlink_impl(const char* user_name) { return 0; } +/* --- POSIX named semaphores --- */ +#define SEM_MAX 16 + +struct ksem_named { + int active; + char name[32]; + int32_t value; + spinlock_t lock; +}; + +static struct ksem_named sem_table[SEM_MAX]; +static spinlock_t sem_table_lock = {0}; + +static int syscall_sem_open_impl(const char* user_name, uint32_t oflag, uint32_t init_val) { + char name[32]; + if (copy_from_user(name, user_name, 31) < 0) return -EFAULT; + name[31] = 0; + + uintptr_t fl = spin_lock_irqsave(&sem_table_lock); + for (int i = 0; i < SEM_MAX; i++) { + if (sem_table[i].active && strcmp(sem_table[i].name, name) == 0) { + spin_unlock_irqrestore(&sem_table_lock, fl); + return i; + } + } + if (!(oflag & 0x40U)) { /* O_CREAT */ + spin_unlock_irqrestore(&sem_table_lock, fl); + return -ENOENT; + } + for (int i = 0; i < SEM_MAX; i++) { + if (!sem_table[i].active) { + memset(&sem_table[i], 0, sizeof(sem_table[i])); + sem_table[i].active = 1; + strcpy(sem_table[i].name, name); + sem_table[i].value = (int32_t)init_val; + spin_unlock_irqrestore(&sem_table_lock, fl); + return i; + } + } + spin_unlock_irqrestore(&sem_table_lock, fl); + return -ENOSPC; +} + +static int syscall_sem_close_impl(int sid) { + (void)sid; + return 0; +} + +static int syscall_sem_wait_impl(int sid) { + if (sid < 0 || sid >= SEM_MAX) return -EINVAL; + extern void process_sleep(uint32_t ticks); + + for (;;) { + uintptr_t fl = spin_lock_irqsave(&sem_table[sid].lock); + if (!sem_table[sid].active) { + spin_unlock_irqrestore(&sem_table[sid].lock, fl); + return -EINVAL; + } + if (sem_table[sid].value > 0) { + sem_table[sid].value--; + spin_unlock_irqrestore(&sem_table[sid].lock, fl); + return 0; + } + spin_unlock_irqrestore(&sem_table[sid].lock, fl); + process_sleep(1); + } +} + +static int syscall_sem_post_impl(int sid) { + if (sid < 0 || sid >= SEM_MAX) return -EINVAL; + uintptr_t fl = spin_lock_irqsave(&sem_table[sid].lock); + if (!sem_table[sid].active) { + spin_unlock_irqrestore(&sem_table[sid].lock, fl); + return -EINVAL; + } + sem_table[sid].value++; + spin_unlock_irqrestore(&sem_table[sid].lock, fl); + return 0; +} + +static int syscall_sem_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(&sem_table_lock); + for (int i = 0; i < SEM_MAX; i++) { + if (sem_table[i].active && strcmp(sem_table[i].name, name) == 0) { + sem_table[i].active = 0; + spin_unlock_irqrestore(&sem_table_lock, fl); + return 0; + } + } + spin_unlock_irqrestore(&sem_table_lock, fl); + return -ENOENT; +} + +static int syscall_sem_getvalue_impl(int sid, int* user_val) { + if (sid < 0 || sid >= SEM_MAX) return -EINVAL; + if (!user_val || user_range_ok(user_val, 4) == 0) return -EFAULT; + uintptr_t fl = spin_lock_irqsave(&sem_table[sid].lock); + if (!sem_table[sid].active) { + spin_unlock_irqrestore(&sem_table[sid].lock, fl); + return -EINVAL; + } + int32_t v = sem_table[sid].value; + spin_unlock_irqrestore(&sem_table[sid].lock, fl); + if (copy_to_user(user_val, &v, 4) < 0) return -EFAULT; + return 0; +} + /* --- Advisory file locking (flock) --- */ enum { FLOCK_SH = 1, @@ -3548,6 +3659,33 @@ static void socket_syscall_dispatch(struct registers* regs, uint32_t syscall_no) return; } + if (syscall_no == SYSCALL_SEM_OPEN) { + sc_ret(regs) = (uint32_t)syscall_sem_open_impl( + (const char*)sc_arg0(regs), sc_arg1(regs), sc_arg2(regs)); + return; + } + if (syscall_no == SYSCALL_SEM_CLOSE) { + sc_ret(regs) = (uint32_t)syscall_sem_close_impl((int)sc_arg0(regs)); + return; + } + if (syscall_no == SYSCALL_SEM_WAIT) { + sc_ret(regs) = (uint32_t)syscall_sem_wait_impl((int)sc_arg0(regs)); + return; + } + if (syscall_no == SYSCALL_SEM_POST) { + sc_ret(regs) = (uint32_t)syscall_sem_post_impl((int)sc_arg0(regs)); + return; + } + if (syscall_no == SYSCALL_SEM_UNLINK) { + sc_ret(regs) = (uint32_t)syscall_sem_unlink_impl((const char*)sc_arg0(regs)); + return; + } + if (syscall_no == SYSCALL_SEM_GETVALUE) { + sc_ret(regs) = (uint32_t)syscall_sem_getvalue_impl( + (int)sc_arg0(regs), (int*)sc_arg1(regs)); + return; + } + sc_ret(regs) = (uint32_t)-ENOSYS; }