linux-old/arch/sparc64/kernel/semaphore.c
<<
>>
Prefs
   1/* $Id: semaphore.c,v 1.9 2001/11/18 00:12:56 davem Exp $
   2 * semaphore.c: Sparc64 semaphore implementation.
   3 *
   4 * This is basically the PPC semaphore scheme ported to use
   5 * the sparc64 atomic instructions, so see the PPC code for
   6 * credits.
   7 */
   8
   9#include <linux/sched.h>
  10
  11/*
  12 * Atomically update sem->count.
  13 * This does the equivalent of the following:
  14 *
  15 *      old_count = sem->count;
  16 *      tmp = MAX(old_count, 0) + incr;
  17 *      sem->count = tmp;
  18 *      return old_count;
  19 */
  20static __inline__ int __sem_update_count(struct semaphore *sem, int incr)
  21{
  22        int old_count, tmp;
  23
  24        __asm__ __volatile__("\n"
  25"       ! __sem_update_count old_count(%0) tmp(%1) incr(%4) &sem->count(%3)\n"
  26"1:     ldsw    [%3], %0\n"
  27"       mov     %0, %1\n"
  28"       cmp     %0, 0\n"
  29"       movl    %%icc, 0, %1\n"
  30"       add     %1, %4, %1\n"
  31"       cas     [%3], %0, %1\n"
  32"       cmp     %0, %1\n"
  33"       bne,pn  %%icc, 1b\n"
  34"        membar #StoreLoad | #StoreStore\n"
  35        : "=&r" (old_count), "=&r" (tmp), "=m" (sem->count)
  36        : "r" (&sem->count), "r" (incr), "m" (sem->count)
  37        : "cc");
  38
  39        return old_count;
  40}
  41
  42void __up(struct semaphore *sem)
  43{
  44        __sem_update_count(sem, 1);
  45        wake_up(&sem->wait);
  46}
  47
  48void __down(struct semaphore * sem)
  49{
  50        struct task_struct *tsk = current;
  51        DECLARE_WAITQUEUE(wait, tsk);
  52
  53        tsk->state = TASK_UNINTERRUPTIBLE;
  54        add_wait_queue_exclusive(&sem->wait, &wait);
  55
  56        while (__sem_update_count(sem, -1) <= 0) {
  57                schedule();
  58                tsk->state = TASK_UNINTERRUPTIBLE;
  59        }
  60        remove_wait_queue(&sem->wait, &wait);
  61        tsk->state = TASK_RUNNING;
  62
  63        wake_up(&sem->wait);
  64}
  65
  66int __down_interruptible(struct semaphore * sem)
  67{
  68        int retval = 0;
  69        struct task_struct *tsk = current;
  70        DECLARE_WAITQUEUE(wait, tsk);
  71
  72        tsk->state = TASK_INTERRUPTIBLE;
  73        add_wait_queue_exclusive(&sem->wait, &wait);
  74
  75        while (__sem_update_count(sem, -1) <= 0) {
  76                if (signal_pending(current)) {
  77                        __sem_update_count(sem, 0);
  78                        retval = -EINTR;
  79                        break;
  80                }
  81                schedule();
  82                tsk->state = TASK_INTERRUPTIBLE;
  83        }
  84        tsk->state = TASK_RUNNING;
  85        remove_wait_queue(&sem->wait, &wait);
  86        wake_up(&sem->wait);
  87        return retval;
  88}
  89
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.