From 0b15dd9f750e91d8036100c18d32739226264063 Mon Sep 17 00:00:00 2001 From: Matthias Kruk Date: Sun, 5 Apr 2020 00:57:03 +0900 Subject: [PATCH] klibc/sem: Make sem_wait() return -EINTR if interrupted due to a signal --- kernel/include/sem.h | 10 +++++++++- kernel/klibc/sem.c | 14 +++++++++++++- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/kernel/include/sem.h b/kernel/include/sem.h index 169f13e..10a4753 100644 --- a/kernel/include/sem.h +++ b/kernel/include/sem.h @@ -29,9 +29,17 @@ typedef struct { * keep trying until it succeeds, meaning that the calling task may * be suspended indefinitely if no other task invokes sem_post() on * the same semaphore. + * A task that is waiting on a semaphore may, however, be interrupted + * by the scheduler due to the advent of a signal. In this case, the + * function call will return early and the semaphore will not have + * been modified. In such a case, it is not safe for the caller to + * proceed - i.e. the intended synchronisation has not taken place. + * Therefore, a check of the return value of this function must not + * be omitted. * * RETURN VALUE - * 0 the value of the semaphore has been successfully decreased + * 0 the value of the semaphore has been successfully decreased + * -EINTR The task was woken up by the scheduler due to a signal */ int sem_wait(sem_t*); diff --git a/kernel/klibc/sem.c b/kernel/klibc/sem.c index 955e64d..281bc4d 100644 --- a/kernel/klibc/sem.c +++ b/kernel/klibc/sem.c @@ -72,7 +72,19 @@ int sem_wait(sem_t *sem) * If we have a valid slot, go to bed and wait for * someone to wake us up. */ - sched_sleep(NULL); + if(sched_sleep(NULL) == -EINTR) { + /* + * A signal has interrupted the sleep. Free the slot that + * we've been using and return to the caller immediately. + */ + + spinlock_lock(&(sem->sem_lock)); + sem->sem_waitq[slot] = NULL; + spinlock_unlock(&(sem->sem_lock)); + + ret_val = -EINTR; + break; + } } } while(ret_val < 0); -- 2.47.3