* 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*);
* 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);