Semaphore try methods
authorBarret Rhoden <brho@cs.berkeley.edu>
Tue, 8 Oct 2013 20:23:27 +0000 (13:23 -0700)
committerBarret Rhoden <brho@cs.berkeley.edu>
Thu, 16 Jan 2014 02:23:22 +0000 (18:23 -0800)
FYI: the irqsave sem_*downs aren't called from IRQ context; they are
used when the ups might be called from IRQ context.

kern/include/kthread.h
kern/src/kthread.c

index a0ffc08..a25fd97 100644 (file)
@@ -74,8 +74,10 @@ void check_poison(char *msg);
 
 void sem_init(struct semaphore *sem, int signals);
 void sem_init_irqsave(struct semaphore *sem, int signals);
+bool sem_trydown(struct semaphore *sem);
 void sem_down(struct semaphore *sem);
 bool sem_up(struct semaphore *sem);
+bool sem_trydown_irqsave(struct semaphore *sem, int8_t *irq_state);
 void sem_down_irqsave(struct semaphore *sem, int8_t *irq_state);
 bool sem_up_irqsave(struct semaphore *sem, int8_t *irq_state);
 
index 5494ab8..5428b87 100644 (file)
@@ -232,6 +232,18 @@ void sem_init_irqsave(struct semaphore *sem, int signals)
        sem->irq_okay = TRUE;
 }
 
+bool sem_trydown(struct semaphore *sem)
+{
+       bool ret = FALSE;
+       spin_lock(&sem->lock);
+       if (sem->nr_signals > 0) {
+               sem->nr_signals--;
+               ret = TRUE;
+       }
+       spin_unlock(&sem->lock);
+       return ret;
+}
+
 /* This downs the semaphore and suspends the current kernel context on its
  * waitqueue if there are no pending signals.  Note that the case where the
  * signal is already there is not optimized. */
@@ -248,13 +260,8 @@ void sem_down(struct semaphore *sem)
        assert(pcpui->cur_kthread);
        /* Try to down the semaphore.  If there is a signal there, we can skip all
         * of the sleep prep and just return. */
-       spin_lock(&sem->lock);  /* no need for irqsave, since we disabled ints */
-       if (sem->nr_signals > 0) {
-               sem->nr_signals--;
-               spin_unlock(&sem->lock);
+       if (sem_trydown(sem))
                goto block_return_path;
-       }
-       spin_unlock(&sem->lock);
        /* We're probably going to sleep, so get ready.  We'll check again later. */
        kthread = pcpui->cur_kthread;
        /* We need to have a spare slot for restart, so we also use it when
@@ -390,6 +397,15 @@ bool sem_up(struct semaphore *sem)
        return FALSE;
 }
 
+bool sem_trydown_irqsave(struct semaphore *sem, int8_t *irq_state)
+{
+       bool ret;
+       disable_irqsave(irq_state);
+       ret = sem_trydown(sem);
+       enable_irqsave(irq_state);
+       return ret;
+}
+
 void sem_down_irqsave(struct semaphore *sem, int8_t *irq_state)
 {
        disable_irqsave(irq_state);