Semaphore upping done with irqsave
authorBarret Rhoden <brho@cs.berkeley.edu>
Thu, 25 Oct 2012 19:39:27 +0000 (12:39 -0700)
committerBarret Rhoden <brho@cs.berkeley.edu>
Thu, 25 Oct 2012 19:39:27 +0000 (12:39 -0700)
So this isn't actually necessary, but might help us in the future.

If the semaphore is never locked and then potentially interrupted, then
we're okay.  sleep_on() disables IRQs.  If there is only one IRQ handler
that ups a particular sem, then we also aren't in danger of deadlocking.

Anyway, __up_sem() is being used in a bunch of places, and might be used
somewhere in the future that could have an issue with irqsaving.  Like
if process context code was calling __up_sem() *and* there was one IRQ
handler calling __up_sem(), then we could deadlock.

kern/include/kthread.h

index 48714b0..a0f3c56 100644 (file)
@@ -55,14 +55,16 @@ static inline void init_sem(struct semaphore *sem, int signals)
  * the kthread did not need to sleep (the signal was already there). */
 static inline bool __down_sem(struct semaphore *sem, struct kthread *kthread)
 {
+       /* Don't actually use this, this is an example of how to build a sem */
+       assert(0);
        bool retval = FALSE;
-       spin_lock(&sem->lock);
+       spin_lock_irqsave(&sem->lock);
        if (sem->nr_signals-- <= 0) {
                /* Need to sleep */
                retval = TRUE;
                TAILQ_INSERT_TAIL(&sem->waiters, kthread, link);
        }
-       spin_unlock(&sem->lock);
+       spin_unlock_irqsave(&sem->lock);
        return retval;
 }
 
@@ -71,7 +73,7 @@ static inline bool __down_sem(struct semaphore *sem, struct kthread *kthread)
 static inline struct kthread *__up_sem(struct semaphore *sem, bool exactly_one)
 {
        struct kthread *kthread = 0;
-       spin_lock(&sem->lock);
+       spin_lock_irqsave(&sem->lock);
        if (sem->nr_signals++ < 0) {
                /* could do something with 'priority' here */
                kthread = TAILQ_FIRST(&sem->waiters);
@@ -81,7 +83,7 @@ static inline struct kthread *__up_sem(struct semaphore *sem, bool exactly_one)
        } else {
                assert(TAILQ_EMPTY(&sem->waiters));
        }
-       spin_unlock(&sem->lock);
+       spin_unlock_irqsave(&sem->lock);
        return kthread;
 }