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

          Line data    Source code
       1             : /*
       2             :  * kref.h - library routines for handling generic reference counted objects
       3             :  *
       4             :  * Copyright (C) 2004 Greg Kroah-Hartman <greg@kroah.com>
       5             :  * Copyright (C) 2004 IBM Corp.
       6             :  *
       7             :  * based on kobject.h which was:
       8             :  * Copyright (C) 2002-2003 Patrick Mochel <mochel@osdl.org>
       9             :  * Copyright (C) 2002-2003 Open Source Development Labs
      10             :  *
      11             :  * This file is released under the GPLv2.
      12             :  *
      13             :  */
      14             : 
      15             : #ifndef _KREF_H_
      16             : #define _KREF_H_
      17             : 
      18             : #include <linux/bug.h>
      19             : #include <linux/atomic.h>
      20             : #include <linux/kernel.h>
      21             : #include <linux/mutex.h>
      22             : #include <linux/spinlock.h>
      23             : 
      24             : struct kref {
      25             :         atomic_t refcount;
      26             : };
      27             : 
      28             : /**
      29             :  * kref_init - initialize object.
      30             :  * @kref: object in question.
      31             :  */
      32             : static inline void kref_init(struct kref *kref)
      33             : {
      34             :         atomic_set(&kref->refcount, 1);
      35             : }
      36             : 
      37             : /**
      38             :  * kref_get - increment refcount for object.
      39             :  * @kref: object.
      40             :  */
      41       26766 : static inline void kref_get(struct kref *kref)
      42             : {
      43             :         /* If refcount was 0 before incrementing then we have a race
      44             :          * condition when this kref is freeing by some other thread right now.
      45             :          * In this case one should use kref_get_unless_zero()
      46             :          */
      47       53550 :         WARN_ON_ONCE(atomic_inc_return(&kref->refcount) < 2);
      48       26784 : }
      49             : 
      50             : /**
      51             :  * kref_sub - subtract a number of refcounts for object.
      52             :  * @kref: object.
      53             :  * @count: Number of recounts to subtract.
      54             :  * @release: pointer to the function that will clean up the object when the
      55             :  *           last reference to the object is released.
      56             :  *           This pointer is required, and it is not acceptable to pass kfree
      57             :  *           in as this function.  If the caller does pass kfree to this
      58             :  *           function, you will be publicly mocked mercilessly by the kref
      59             :  *           maintainer, and anyone else who happens to notice it.  You have
      60             :  *           been warned.
      61             :  *
      62             :  * Subtract @count from the refcount, and if 0, call release().
      63             :  * Return 1 if the object was removed, otherwise return 0.  Beware, if this
      64             :  * function returns 0, you still can not count on the kref from remaining in
      65             :  * memory.  Only use the return value if you want to see if the kref is now
      66             :  * gone, not present.
      67             :  */
      68       27223 : static inline int kref_sub(struct kref *kref, unsigned int count,
      69             :              void (*release)(struct kref *kref))
      70             : {
      71       27223 :         WARN_ON(release == NULL);
      72             : 
      73       54465 :         if (atomic_sub_and_test((int) count, &kref->refcount)) {
      74         460 :                 release(kref);
      75         460 :                 return 1;
      76             :         }
      77             :         return 0;
      78             : }
      79             : 
      80             : /**
      81             :  * kref_put - decrement refcount for object.
      82             :  * @kref: object.
      83             :  * @release: pointer to the function that will clean up the object when the
      84             :  *           last reference to the object is released.
      85             :  *           This pointer is required, and it is not acceptable to pass kfree
      86             :  *           in as this function.  If the caller does pass kfree to this
      87             :  *           function, you will be publicly mocked mercilessly by the kref
      88             :  *           maintainer, and anyone else who happens to notice it.  You have
      89             :  *           been warned.
      90             :  *
      91             :  * Decrement the refcount, and if 0, call release().
      92             :  * Return 1 if the object was removed, otherwise return 0.  Beware, if this
      93             :  * function returns 0, you still can not count on the kref from remaining in
      94             :  * memory.  Only use the return value if you want to see if the kref is now
      95             :  * gone, not present.
      96             :  */
      97             : static inline int kref_put(struct kref *kref, void (*release)(struct kref *kref))
      98             : {
      99       27254 :         return kref_sub(kref, 1, release);
     100             : }
     101             : 
     102             : /**
     103             :  * kref_put_spinlock_irqsave - decrement refcount for object.
     104             :  * @kref: object.
     105             :  * @release: pointer to the function that will clean up the object when the
     106             :  *           last reference to the object is released.
     107             :  *           This pointer is required, and it is not acceptable to pass kfree
     108             :  *           in as this function.
     109             :  * @lock: lock to take in release case
     110             :  *
     111             :  * Behaves identical to kref_put with one exception.  If the reference count
     112             :  * drops to zero, the lock will be taken atomically wrt dropping the reference
     113             :  * count.  The release function has to call spin_unlock() without _irqrestore.
     114             :  */
     115             : static inline int kref_put_spinlock_irqsave(struct kref *kref,
     116             :                 void (*release)(struct kref *kref),
     117             :                 spinlock_t *lock)
     118             : {
     119             :         unsigned long flags;
     120             : 
     121             :         WARN_ON(release == NULL);
     122             :         if (atomic_add_unless(&kref->refcount, -1, 1))
     123             :                 return 0;
     124             :         spin_lock_irqsave(lock, flags);
     125             :         if (atomic_dec_and_test(&kref->refcount)) {
     126             :                 release(kref);
     127             :                 local_irq_restore(flags);
     128             :                 return 1;
     129             :         }
     130             :         spin_unlock_irqrestore(lock, flags);
     131             :         return 0;
     132             : }
     133             : 
     134             : static inline int kref_put_mutex(struct kref *kref,
     135             :                                  void (*release)(struct kref *kref),
     136             :                                  struct mutex *lock)
     137             : {
     138             :         WARN_ON(release == NULL);
     139             :         if (unlikely(!atomic_add_unless(&kref->refcount, -1, 1))) {
     140             :                 mutex_lock(lock);
     141             :                 if (unlikely(!atomic_dec_and_test(&kref->refcount))) {
     142             :                         mutex_unlock(lock);
     143             :                         return 0;
     144             :                 }
     145             :                 release(kref);
     146             :                 return 1;
     147             :         }
     148             :         return 0;
     149             : }
     150             : 
     151             : /**
     152             :  * kref_get_unless_zero - Increment refcount for object unless it is zero.
     153             :  * @kref: object.
     154             :  *
     155             :  * Return non-zero if the increment succeeded. Otherwise return 0.
     156             :  *
     157             :  * This function is intended to simplify locking around refcounting for
     158             :  * objects that can be looked up from a lookup structure, and which are
     159             :  * removed from that lookup structure in the object destructor.
     160             :  * Operations on such objects require at least a read lock around
     161             :  * lookup + kref_get, and a write lock around kref_put + remove from lookup
     162             :  * structure. Furthermore, RCU implementations become extremely tricky.
     163             :  * With a lookup followed by a kref_get_unless_zero *with return value check*
     164             :  * locking in the kref_put path can be deferred to the actual removal from
     165             :  * the lookup structure and RCU lookups become trivial.
     166             :  */
     167             : static inline int __must_check kref_get_unless_zero(struct kref *kref)
     168             : {
     169             :         return atomic_add_unless(&kref->refcount, 1, 0);
     170             : }
     171             : #endif /* _KREF_H_ */

Generated by: LCOV version 1.10