From 1fd2f6bc50a4d7fd26fd1c8cd35a995ab48256de Mon Sep 17 00:00:00 2001 From: Matheus Date: Sun, 22 Sep 2024 11:39:40 -0300 Subject: [PATCH] semaphore: semaphore_signal_limit --- kernel-src/include/semaphore.h | 1 + kernel-src/lib/semaphore.c | 26 ++++++++++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/kernel-src/include/semaphore.h b/kernel-src/include/semaphore.h index 3d235fcd..eb2bbf6e 100644 --- a/kernel-src/include/semaphore.h +++ b/kernel-src/include/semaphore.h @@ -30,5 +30,6 @@ void semaphore_signal(semaphore_t *sem); void semaphore_reset(semaphore_t *sem); bool semaphore_test(semaphore_t *sem); bool semaphore_haswaiters(semaphore_t *sem); +bool semaphore_signal_limit(semaphore_t *sem, int limit); #endif diff --git a/kernel-src/lib/semaphore.c b/kernel-src/lib/semaphore.c index 15baa646..52a6ab81 100644 --- a/kernel-src/lib/semaphore.c +++ b/kernel-src/lib/semaphore.c @@ -127,6 +127,32 @@ void semaphore_signal(semaphore_t *sem) { interrupt_set(intstate); } +bool semaphore_signal_limit(semaphore_t *sem, int limit) { + bool intstate = interrupt_set(false); + spinlock_acquire(&sem->lock); + + bool successful = false; + + if (sem->i >= limit) + goto leave; + + if (++sem->i <= 0) { + thread_t *thread = get(sem); + // a thread will always be returned if sem->i <= 0 + __assert(thread); + + // XXX the current method doesn't respect thread priorities + sched_wakeup(thread, 0); + } + + successful = true; + + leave: + spinlock_release(&sem->lock); + interrupt_set(intstate); + return successful; +} + void semaphore_reset(semaphore_t *sem) { bool intstate = spinlock_acquireirqclear(&sem->lock); __assert(sem->head == NULL);