From dd1719096af74e9e2ffc2598f98fedd5d4254d06 Mon Sep 17 00:00:00 2001 From: Matheus Date: Sun, 26 May 2024 20:51:25 -0300 Subject: [PATCH] semaphore: fix a race condition --- kernel-src/lib/semaphore.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/kernel-src/lib/semaphore.c b/kernel-src/lib/semaphore.c index da8a8298..ba0038d8 100644 --- a/kernel-src/lib/semaphore.c +++ b/kernel-src/lib/semaphore.c @@ -27,9 +27,37 @@ static thread_t *get(semaphore_t *sem) { else sem->tail->sleepnext = NULL; + thread->sleepprev = NULL; + thread->sleepnext = NULL; + return thread; } +static void removeself(semaphore_t *sem) { + thread_t *thread = _cpu()->thread; + + // first see if we have been removed already + if ((sem->head == NULL && sem->tail == NULL) || // no threads in sleep list + !((thread->sleepnext != NULL || thread->sleepprev != NULL) || // 2 or more threads in sleep list and we are one of them + (sem->head == thread && sem->tail == thread))) // 1 thread in the sleep list and it is us + return; + + if (sem->head == thread) { + sem->head = thread->sleepnext; + } else { + thread->sleepprev->sleepnext = thread->sleepnext; + } + + if (sem->tail == thread) { + sem->tail = thread->sleepprev; + } else { + thread->sleepnext->sleepprev = thread->sleepprev; + } + + thread->sleepprev = NULL; + thread->sleepnext = NULL; +} + int semaphore_wait(semaphore_t *sem, bool interruptible) { if (_cpu()->thread == NULL) { while (semaphore_test(sem) == false) CPU_PAUSE(); @@ -48,6 +76,7 @@ int semaphore_wait(semaphore_t *sem, bool interruptible) { if (ret) { spinlock_acquire(&sem->lock); ++sem->i; + removeself(sem); spinlock_release(&sem->lock); } goto leave;