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-alpha/rwsem.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 #ifndef _ALPHA_RWSEM_H
    2 #define _ALPHA_RWSEM_H
    3 
    4 /*
    5  * Written by Ivan Kokshaysky <ink@jurassic.park.msu.ru>, 2001.
    6  * Based on asm-alpha/semaphore.h and asm-i386/rwsem.h
    7  */
    8 
    9 #ifndef _LINUX_RWSEM_H
   10 #error please dont include asm/rwsem.h directly, use linux/rwsem.h instead
   11 #endif
   12 
   13 #ifdef __KERNEL__
   14 
   15 #include <linux/compiler.h>
   16 #include <linux/list.h>
   17 #include <linux/spinlock.h>
   18 
   19 struct rwsem_waiter;
   20 
   21 extern struct rw_semaphore *rwsem_down_read_failed(struct rw_semaphore *sem);
   22 extern struct rw_semaphore *rwsem_down_write_failed(struct rw_semaphore *sem);
   23 extern struct rw_semaphore *rwsem_wake(struct rw_semaphore *);
   24 
   25 /*
   26  * the semaphore definition
   27  */
   28 struct rw_semaphore {
   29         long                    count;
   30 #define RWSEM_UNLOCKED_VALUE            0x0000000000000000L
   31 #define RWSEM_ACTIVE_BIAS               0x0000000000000001L
   32 #define RWSEM_ACTIVE_MASK               0x00000000ffffffffL
   33 #define RWSEM_WAITING_BIAS              (-0x0000000100000000L)
   34 #define RWSEM_ACTIVE_READ_BIAS          RWSEM_ACTIVE_BIAS
   35 #define RWSEM_ACTIVE_WRITE_BIAS         (RWSEM_WAITING_BIAS + RWSEM_ACTIVE_BIAS)
   36         spinlock_t              wait_lock;
   37         struct list_head        wait_list;
   38 #if RWSEM_DEBUG
   39         int                     debug;
   40 #endif
   41 };
   42 
   43 #if RWSEM_DEBUG
   44 #define __RWSEM_DEBUG_INIT      , 0
   45 #else
   46 #define __RWSEM_DEBUG_INIT      /* */
   47 #endif
   48 
   49 #define __RWSEM_INITIALIZER(name) \
   50         { RWSEM_UNLOCKED_VALUE, SPIN_LOCK_UNLOCKED, \
   51         LIST_HEAD_INIT((name).wait_list) __RWSEM_DEBUG_INIT }
   52 
   53 #define DECLARE_RWSEM(name) \
   54         struct rw_semaphore name = __RWSEM_INITIALIZER(name)
   55 
   56 static inline void init_rwsem(struct rw_semaphore *sem)
   57 {
   58         sem->count = RWSEM_UNLOCKED_VALUE;
   59         spin_lock_init(&sem->wait_lock);
   60         INIT_LIST_HEAD(&sem->wait_list);
   61 #if RWSEM_DEBUG
   62         sem->debug = 0;
   63 #endif
   64 }
   65 
   66 static inline void __down_read(struct rw_semaphore *sem)
   67 {
   68         long oldcount;
   69 #ifndef CONFIG_SMP
   70         oldcount = sem->count;
   71         sem->count += RWSEM_ACTIVE_READ_BIAS;
   72 #else
   73         long temp;
   74         __asm__ __volatile__(
   75         "1:     ldq_l   %0,%1\n"
   76         "       addq    %0,%3,%2\n"
   77         "       stq_c   %2,%1\n"
   78         "       beq     %2,2f\n"
   79         "       mb\n"
   80         ".subsection 2\n"
   81         "2:     br      1b\n"
   82         ".previous"
   83         :"=&r" (oldcount), "=m" (sem->count), "=&r" (temp)
   84         :"Ir" (RWSEM_ACTIVE_READ_BIAS), "m" (sem->count) : "memory");
   85 #endif
   86         if (__builtin_expect(oldcount < 0, 0))
   87                 rwsem_down_read_failed(sem);
   88 }
   89 
   90 /*
   91  * trylock for reading -- returns 1 if successful, 0 if contention
   92  */
   93 static inline int __down_read_trylock(struct rw_semaphore *sem)
   94 {
   95         long old, new, res;
   96 
   97         res = sem->count;
   98         do {
   99                 new = res + RWSEM_ACTIVE_READ_BIAS;
  100                 if (new <= 0)
  101                         break;
  102                 old = res;
  103                 res = cmpxchg(&sem->count, old, new);
  104         } while (res != old);
  105         return res >= 0 ? 1 : 0;
  106 }
  107 
  108 static inline void __down_write(struct rw_semaphore *sem)
  109 {
  110         long oldcount;
  111 #ifndef CONFIG_SMP
  112         oldcount = sem->count;
  113         sem->count += RWSEM_ACTIVE_WRITE_BIAS;
  114 #else
  115         long temp;
  116         __asm__ __volatile__(
  117         "1:     ldq_l   %0,%1\n"
  118         "       addq    %0,%3,%2\n"
  119         "       stq_c   %2,%1\n"
  120         "       beq     %2,2f\n"
  121         "       mb\n"
  122         ".subsection 2\n"
  123         "2:     br      1b\n"
  124         ".previous"
  125         :"=&r" (oldcount), "=m" (sem->count), "=&r" (temp)
  126         :"Ir" (RWSEM_ACTIVE_WRITE_BIAS), "m" (sem->count) : "memory");
  127 #endif
  128         if (__builtin_expect(oldcount, 0))
  129                 rwsem_down_write_failed(sem);
  130 }
  131 
  132 /*
  133  * trylock for writing -- returns 1 if successful, 0 if contention
  134  */
  135 static inline int __down_write_trylock(struct rw_semaphore *sem)
  136 {
  137         long ret = cmpxchg(&sem->count, RWSEM_UNLOCKED_VALUE,
  138                            RWSEM_ACTIVE_WRITE_BIAS);
  139         if (ret == RWSEM_UNLOCKED_VALUE)
  140                 return 1;
  141         return 0;
  142 }
  143 
  144 static inline void __up_read(struct rw_semaphore *sem)
  145 {
  146         long oldcount;
  147 #ifndef CONFIG_SMP
  148         oldcount = sem->count;
  149         sem->count -= RWSEM_ACTIVE_READ_BIAS;
  150 #else
  151         long temp;
  152         __asm__ __volatile__(
  153         "       mb\n"
  154         "1:     ldq_l   %0,%1\n"
  155         "       subq    %0,%3,%2\n"
  156         "       stq_c   %2,%1\n"
  157         "       beq     %2,2f\n"
  158         ".subsection 2\n"
  159         "2:     br      1b\n"
  160         ".previous"
  161         :"=&r" (oldcount), "=m" (sem->count), "=&r" (temp)
  162         :"Ir" (RWSEM_ACTIVE_READ_BIAS), "m" (sem->count) : "memory");
  163 #endif
  164         if (__builtin_expect(oldcount < 0, 0)) 
  165                 if ((int)oldcount - RWSEM_ACTIVE_READ_BIAS == 0)
  166                         rwsem_wake(sem);
  167 }
  168 
  169 static inline void __up_write(struct rw_semaphore *sem)
  170 {
  171         long count;
  172 #ifndef CONFIG_SMP
  173         sem->count -= RWSEM_ACTIVE_WRITE_BIAS;
  174         count = sem->count;
  175 #else
  176         long temp;
  177         __asm__ __volatile__(
  178         "       mb\n"
  179         "1:     ldq_l   %0,%1\n"
  180         "       subq    %0,%3,%2\n"
  181         "       stq_c   %2,%1\n"
  182         "       beq     %2,2f\n"
  183         "       subq    %0,%3,%0\n"
  184         ".subsection 2\n"
  185         "2:     br      1b\n"
  186         ".previous"
  187         :"=&r" (count), "=m" (sem->count), "=&r" (temp)
  188         :"Ir" (RWSEM_ACTIVE_WRITE_BIAS), "m" (sem->count) : "memory");
  189 #endif
  190         if (__builtin_expect(count, 0))
  191                 if ((int)count == 0)
  192                         rwsem_wake(sem);
  193 }
  194 
  195 static inline void rwsem_atomic_add(long val, struct rw_semaphore *sem)
  196 {
  197 #ifndef CONFIG_SMP
  198         sem->count += val;
  199 #else
  200         long temp;
  201         __asm__ __volatile__(
  202         "1:     ldq_l   %0,%1\n"
  203         "       addq    %0,%2,%0\n"
  204         "       stq_c   %0,%1\n"
  205         "       beq     %0,2f\n"
  206         ".subsection 2\n"
  207         "2:     br      1b\n"
  208         ".previous"
  209         :"=&r" (temp), "=m" (sem->count)
  210         :"Ir" (val), "m" (sem->count));
  211 #endif
  212 }
  213 
  214 static inline long rwsem_atomic_update(long val, struct rw_semaphore *sem)
  215 {
  216 #ifndef CONFIG_SMP
  217         sem->count += val;
  218         return sem->count;
  219 #else
  220         long ret, temp;
  221         __asm__ __volatile__(
  222         "1:     ldq_l   %0,%1\n"
  223         "       addq    %0,%3,%2\n"
  224         "       addq    %0,%3,%0\n"
  225         "       stq_c   %2,%1\n"
  226         "       beq     %2,2f\n"
  227         ".subsection 2\n"
  228         "2:     br      1b\n"
  229         ".previous"
  230         :"=&r" (ret), "=m" (sem->count), "=&r" (temp)
  231         :"Ir" (val), "m" (sem->count));
  232 
  233         return ret;
  234 #endif
  235 }
  236 
  237 #endif /* __KERNEL__ */
  238 #endif /* _ALPHA_RWSEM_H */

Cache object: ea5872d5ebe827a5287e1859b4d986b1


[ 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.