The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/include/asm-mips64/semaphore.h

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  * This file is subject to the terms and conditions of the GNU General Public
    3  * License.  See the file "COPYING" in the main directory of this archive
    4  * for more details.
    5  *
    6  * Copyright (C) 1996  Linus Torvalds
    7  * Copyright (C) 1998, 99, 2000, 01  Ralf Baechle
    8  * Copyright (C) 1999, 2000, 01  Silicon Graphics, Inc.
    9  * Copyright (C) 2000, 01 MIPS Technologies, Inc.
   10  */
   11 #ifndef _ASM_SEMAPHORE_H
   12 #define _ASM_SEMAPHORE_H
   13 
   14 #include <linux/config.h>
   15 #include <asm/system.h>
   16 #include <asm/atomic.h>
   17 #include <linux/spinlock.h>
   18 #include <linux/wait.h>
   19 #include <linux/rwsem.h>
   20 
   21 struct semaphore {
   22 #ifdef __MIPSEB__
   23         atomic_t count;
   24         atomic_t waking;
   25 #else
   26         atomic_t waking;
   27         atomic_t count;
   28 #endif
   29         wait_queue_head_t wait;
   30 #if WAITQUEUE_DEBUG
   31         long __magic;
   32 #endif
   33 } __attribute__((aligned(8)));
   34 
   35 #if WAITQUEUE_DEBUG
   36 # define __SEM_DEBUG_INIT(name) \
   37                 , (long)&(name).__magic
   38 #else
   39 # define __SEM_DEBUG_INIT(name)
   40 #endif
   41 
   42 #ifdef __MIPSEB__
   43 #define __SEMAPHORE_INITIALIZER(name,count) \
   44 { ATOMIC_INIT(count), ATOMIC_INIT(0), __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) \
   45         __SEM_DEBUG_INIT(name) }
   46 #else
   47 #define __SEMAPHORE_INITIALIZER(name,count) \
   48 { ATOMIC_INIT(0), ATOMIC_INIT(count), __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) \
   49         __SEM_DEBUG_INIT(name) }
   50 #endif
   51 
   52 #define __MUTEX_INITIALIZER(name) \
   53         __SEMAPHORE_INITIALIZER(name,1)
   54 
   55 #define __DECLARE_SEMAPHORE_GENERIC(name,count) \
   56         struct semaphore name = __SEMAPHORE_INITIALIZER(name,count)
   57 
   58 #define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name,1)
   59 #define DECLARE_MUTEX_LOCKED(name) __DECLARE_SEMAPHORE_GENERIC(name,0)
   60 
   61 static inline void sema_init (struct semaphore *sem, int val)
   62 {
   63         atomic_set(&sem->count, val);
   64         atomic_set(&sem->waking, 0);
   65         init_waitqueue_head(&sem->wait);
   66 #if WAITQUEUE_DEBUG
   67         sem->__magic = (long)&sem->__magic;
   68 #endif
   69 }
   70 
   71 static inline void init_MUTEX (struct semaphore *sem)
   72 {
   73         sema_init(sem, 1);
   74 }
   75 
   76 static inline void init_MUTEX_LOCKED (struct semaphore *sem)
   77 {
   78         sema_init(sem, 0);
   79 }
   80 
   81 asmlinkage void __down(struct semaphore * sem);
   82 asmlinkage int  __down_interruptible(struct semaphore * sem);
   83 asmlinkage int __down_trylock(struct semaphore * sem);
   84 asmlinkage void __up(struct semaphore * sem);
   85 
   86 static inline void down(struct semaphore * sem)
   87 {
   88 #if WAITQUEUE_DEBUG
   89         CHECK_MAGIC(sem->__magic);
   90 #endif
   91         if (atomic_dec_return(&sem->count) < 0)
   92                 __down(sem);
   93 }
   94 
   95 /*
   96  * Interruptible try to acquire a semaphore.  If we obtained
   97  * it, return zero.  If we were interrupted, returns -EINTR
   98  */
   99 static inline int down_interruptible(struct semaphore * sem)
  100 {
  101         int ret = 0;
  102 
  103 #if WAITQUEUE_DEBUG
  104         CHECK_MAGIC(sem->__magic);
  105 #endif
  106         if (atomic_dec_return(&sem->count) < 0)
  107                 ret = __down_interruptible(sem);
  108         return ret;
  109 }
  110 
  111 #ifndef CONFIG_CPU_HAS_LLDSCD
  112 
  113 /*
  114  * Non-blockingly attempt to down() a semaphore.
  115  * Returns zero if we acquired it
  116  */
  117 static inline int down_trylock(struct semaphore * sem)
  118 {
  119         int ret = 0;
  120         if (atomic_dec_return(&sem->count) < 0)
  121                 ret = __down_trylock(sem);
  122         return ret;
  123 }
  124 
  125 #else
  126 
  127 /*
  128  * down_trylock returns 0 on success, 1 if we failed to get the lock.
  129  *
  130  * We must manipulate count and waking simultaneously and atomically.
  131  * Here, we do this by using lld/scd on the pair of 32-bit words.
  132  *
  133  * Pseudocode:
  134  *
  135  *   Decrement(sem->count)
  136  *   If(sem->count >=0) {
  137  *      Return(SUCCESS)                 // resource is free
  138  *   } else {
  139  *      If(sem->waking <= 0) {          // if no wakeup pending
  140  *         Increment(sem->count)        // undo decrement
  141  *         Return(FAILURE)
  142  *      } else {
  143  *         Decrement(sem->waking)       // otherwise "steal" wakeup
  144  *         Return(SUCCESS)
  145  *      }
  146  *   }
  147  */
  148 static inline int down_trylock(struct semaphore * sem)
  149 {
  150         long ret, tmp, tmp2, sub;
  151 
  152 #if WAITQUEUE_DEBUG
  153         CHECK_MAGIC(sem->__magic);
  154 #endif
  155 
  156         __asm__ __volatile__(
  157         ".set\tmips3\t\t\t# down_trylock\n"
  158         "0:\tlld\t%1, %4\n\t"
  159         "dli\t%3, 0x0000000100000000\n\t"
  160         "dsubu\t%1, %3\n\t"
  161         "li\t%0, 0\n\t"
  162         "bgez\t%1, 2f\n\t"
  163         "sll\t%2, %1, 0\n\t"
  164         "blez\t%2, 1f\n\t"
  165         "daddiu\t%1, %1, -1\n\t"
  166         "b\t2f\n"
  167         "1:\tdaddu\t%1, %1, %3\n\t"
  168         "li\t%0, 1\n"
  169         "2:\tscd\t%1, %4\n\t"
  170         "beqz\t%1, 0b\n\t"
  171         ".set\tmips0"
  172         : "=&r"(ret), "=&r"(tmp), "=&r"(tmp2), "=&r"(sub)
  173         : "m"(*sem)
  174         : "memory");
  175 
  176         return ret;
  177 }
  178 
  179 #endif /* CONFIG_CPU_HAS_LLDSCD */
  180 
  181 /*
  182  * Note! This is subtle. We jump to wake people up only if
  183  * the semaphore was negative (== somebody was waiting on it).
  184  */
  185 static inline void up(struct semaphore * sem)
  186 {
  187 #if WAITQUEUE_DEBUG
  188         CHECK_MAGIC(sem->__magic);
  189 #endif
  190         if (atomic_inc_return(&sem->count) <= 0)
  191                 __up(sem);
  192 }
  193 
  194 static inline int sem_getcount(struct semaphore *sem)
  195 {
  196         return atomic_read(&sem->count);
  197 }
  198 
  199 #endif /* _ASM_SEMAPHORE_H */

Cache object: 957d532814b1a2829eb74960d9a42ab8


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.