LCOV - code coverage report
Current view: top level - include/asm-generic - qrwlock.h (source / functions) Hit Total Coverage
Test: btrfstest.info Lines: 2 2 100.0 %
Date: 2014-11-28 Functions: 0 0 -

          Line data    Source code
       1             : /*
       2             :  * Queue read/write lock
       3             :  *
       4             :  * This program is free software; you can redistribute it and/or modify
       5             :  * it under the terms of the GNU General Public License as published by
       6             :  * the Free Software Foundation; either version 2 of the License, or
       7             :  * (at your option) any later version.
       8             :  *
       9             :  * This program is distributed in the hope that it will be useful,
      10             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      11             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      12             :  * GNU General Public License for more details.
      13             :  *
      14             :  * (C) Copyright 2013-2014 Hewlett-Packard Development Company, L.P.
      15             :  *
      16             :  * Authors: Waiman Long <waiman.long@hp.com>
      17             :  */
      18             : #ifndef __ASM_GENERIC_QRWLOCK_H
      19             : #define __ASM_GENERIC_QRWLOCK_H
      20             : 
      21             : #include <linux/atomic.h>
      22             : #include <asm/barrier.h>
      23             : #include <asm/processor.h>
      24             : 
      25             : #include <asm-generic/qrwlock_types.h>
      26             : 
      27             : /*
      28             :  * Writer states & reader shift and bias
      29             :  */
      30             : #define _QW_WAITING     1               /* A writer is waiting     */
      31             : #define _QW_LOCKED      0xff            /* A writer holds the lock */
      32             : #define _QW_WMASK       0xff            /* Writer mask             */
      33             : #define _QR_SHIFT       8               /* Reader count shift      */
      34             : #define _QR_BIAS        (1U << _QR_SHIFT)
      35             : 
      36             : /*
      37             :  * External function declarations
      38             :  */
      39             : extern void queue_read_lock_slowpath(struct qrwlock *lock);
      40             : extern void queue_write_lock_slowpath(struct qrwlock *lock);
      41             : 
      42             : /**
      43             :  * queue_read_can_lock- would read_trylock() succeed?
      44             :  * @lock: Pointer to queue rwlock structure
      45             :  */
      46             : static inline int queue_read_can_lock(struct qrwlock *lock)
      47             : {
      48             :         return !(atomic_read(&lock->cnts) & _QW_WMASK);
      49             : }
      50             : 
      51             : /**
      52             :  * queue_write_can_lock- would write_trylock() succeed?
      53             :  * @lock: Pointer to queue rwlock structure
      54             :  */
      55             : static inline int queue_write_can_lock(struct qrwlock *lock)
      56             : {
      57             :         return !atomic_read(&lock->cnts);
      58             : }
      59             : 
      60             : /**
      61             :  * queue_read_trylock - try to acquire read lock of a queue rwlock
      62             :  * @lock : Pointer to queue rwlock structure
      63             :  * Return: 1 if lock acquired, 0 if failed
      64             :  */
      65             : static inline int queue_read_trylock(struct qrwlock *lock)
      66             : {
      67             :         u32 cnts;
      68             : 
      69             :         cnts = atomic_read(&lock->cnts);
      70             :         if (likely(!(cnts & _QW_WMASK))) {
      71             :                 cnts = (u32)atomic_add_return(_QR_BIAS, &lock->cnts);
      72             :                 if (likely(!(cnts & _QW_WMASK)))
      73             :                         return 1;
      74             :                 atomic_sub(_QR_BIAS, &lock->cnts);
      75             :         }
      76             :         return 0;
      77             : }
      78             : 
      79             : /**
      80             :  * queue_write_trylock - try to acquire write lock of a queue rwlock
      81             :  * @lock : Pointer to queue rwlock structure
      82             :  * Return: 1 if lock acquired, 0 if failed
      83             :  */
      84             : static inline int queue_write_trylock(struct qrwlock *lock)
      85             : {
      86             :         u32 cnts;
      87             : 
      88             :         cnts = atomic_read(&lock->cnts);
      89             :         if (unlikely(cnts))
      90             :                 return 0;
      91             : 
      92             :         return likely(atomic_cmpxchg(&lock->cnts,
      93             :                                      cnts, cnts | _QW_LOCKED) == cnts);
      94             : }
      95             : /**
      96             :  * queue_read_lock - acquire read lock of a queue rwlock
      97             :  * @lock: Pointer to queue rwlock structure
      98             :  */
      99             : static inline void queue_read_lock(struct qrwlock *lock)
     100             : {
     101             :         u32 cnts;
     102             : 
     103             :         cnts = atomic_add_return(_QR_BIAS, &lock->cnts);
     104             :         if (likely(!(cnts & _QW_WMASK)))
     105             :                 return;
     106             : 
     107             :         /* The slowpath will decrement the reader count, if necessary. */
     108             :         queue_read_lock_slowpath(lock);
     109             : }
     110             : 
     111             : /**
     112             :  * queue_write_lock - acquire write lock of a queue rwlock
     113             :  * @lock : Pointer to queue rwlock structure
     114             :  */
     115             : static inline void queue_write_lock(struct qrwlock *lock)
     116             : {
     117             :         /* Optimize for the unfair lock case where the fair flag is 0. */
     118             :         if (atomic_cmpxchg(&lock->cnts, 0, _QW_LOCKED) == 0)
     119             :                 return;
     120             : 
     121             :         queue_write_lock_slowpath(lock);
     122             : }
     123             : 
     124             : /**
     125             :  * queue_read_unlock - release read lock of a queue rwlock
     126             :  * @lock : Pointer to queue rwlock structure
     127             :  */
     128             : static inline void queue_read_unlock(struct qrwlock *lock)
     129             : {
     130             :         /*
     131             :          * Atomically decrement the reader count
     132             :          */
     133     6317893 :         smp_mb__before_atomic();
     134     6317887 :         atomic_sub(_QR_BIAS, &lock->cnts);
     135             : }
     136             : 
     137             : #ifndef queue_write_unlock
     138             : /**
     139             :  * queue_write_unlock - release write lock of a queue rwlock
     140             :  * @lock : Pointer to queue rwlock structure
     141             :  */
     142             : static inline void queue_write_unlock(struct qrwlock *lock)
     143             : {
     144             :         /*
     145             :          * If the writer field is atomic, it can be cleared directly.
     146             :          * Otherwise, an atomic subtraction will be used to clear it.
     147             :          */
     148             :         smp_mb__before_atomic();
     149             :         atomic_sub(_QW_LOCKED, &lock->cnts);
     150             : }
     151             : #endif
     152             : 
     153             : /*
     154             :  * Remapping rwlock architecture specific functions to the corresponding
     155             :  * queue rwlock functions.
     156             :  */
     157             : #define arch_read_can_lock(l)   queue_read_can_lock(l)
     158             : #define arch_write_can_lock(l)  queue_write_can_lock(l)
     159             : #define arch_read_lock(l)       queue_read_lock(l)
     160             : #define arch_write_lock(l)      queue_write_lock(l)
     161             : #define arch_read_trylock(l)    queue_read_trylock(l)
     162             : #define arch_write_trylock(l)   queue_write_trylock(l)
     163             : #define arch_read_unlock(l)     queue_read_unlock(l)
     164             : #define arch_write_unlock(l)    queue_write_unlock(l)
     165             : 
     166             : #endif /* __ASM_GENERIC_QRWLOCK_H */

Generated by: LCOV version 1.10