| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1 | /* | 
| Robert P. J. Day | 932fb06 | 2010-03-13 07:58:13 -0500 | [diff] [blame] | 2 | * kref.h - library routines for handling generic reference counted objects | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 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 |  | 
| Greg Kroah-Hartman | 6261dde | 2011-12-14 11:19:07 -0800 | [diff] [blame] | 18 | #include <linux/bug.h> | 
|  | 19 | #include <linux/atomic.h> | 
| James Bottomley | 67175b8 | 2012-01-17 21:14:05 +0000 | [diff] [blame] | 20 | #include <linux/kernel.h> | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 21 |  | 
|  | 22 | struct kref { | 
|  | 23 | atomic_t refcount; | 
|  | 24 | }; | 
|  | 25 |  | 
| Peter Zijlstra | 4af679c | 2011-12-13 10:36:20 +0100 | [diff] [blame] | 26 | /** | 
|  | 27 | * kref_init - initialize object. | 
|  | 28 | * @kref: object in question. | 
|  | 29 | */ | 
|  | 30 | static inline void kref_init(struct kref *kref) | 
|  | 31 | { | 
|  | 32 | atomic_set(&kref->refcount, 1); | 
| Peter Zijlstra | 4af679c | 2011-12-13 10:36:20 +0100 | [diff] [blame] | 33 | } | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 34 |  | 
| Peter Zijlstra | 4af679c | 2011-12-13 10:36:20 +0100 | [diff] [blame] | 35 | /** | 
|  | 36 | * kref_get - increment refcount for object. | 
|  | 37 | * @kref: object. | 
|  | 38 | */ | 
|  | 39 | static inline void kref_get(struct kref *kref) | 
|  | 40 | { | 
|  | 41 | WARN_ON(!atomic_read(&kref->refcount)); | 
|  | 42 | atomic_inc(&kref->refcount); | 
| Peter Zijlstra | 4af679c | 2011-12-13 10:36:20 +0100 | [diff] [blame] | 43 | } | 
|  | 44 |  | 
|  | 45 | /** | 
| Peter Zijlstra | 4af679c | 2011-12-13 10:36:20 +0100 | [diff] [blame] | 46 | * kref_sub - subtract a number of refcounts for object. | 
|  | 47 | * @kref: object. | 
|  | 48 | * @count: Number of recounts to subtract. | 
|  | 49 | * @release: pointer to the function that will clean up the object when the | 
|  | 50 | *	     last reference to the object is released. | 
|  | 51 | *	     This pointer is required, and it is not acceptable to pass kfree | 
| Greg Kroah-Hartman | 6261dde | 2011-12-14 11:19:07 -0800 | [diff] [blame] | 52 | *	     in as this function.  If the caller does pass kfree to this | 
|  | 53 | *	     function, you will be publicly mocked mercilessly by the kref | 
|  | 54 | *	     maintainer, and anyone else who happens to notice it.  You have | 
|  | 55 | *	     been warned. | 
| Peter Zijlstra | 4af679c | 2011-12-13 10:36:20 +0100 | [diff] [blame] | 56 | * | 
|  | 57 | * Subtract @count from the refcount, and if 0, call release(). | 
|  | 58 | * Return 1 if the object was removed, otherwise return 0.  Beware, if this | 
|  | 59 | * function returns 0, you still can not count on the kref from remaining in | 
|  | 60 | * memory.  Only use the return value if you want to see if the kref is now | 
|  | 61 | * gone, not present. | 
|  | 62 | */ | 
|  | 63 | static inline int kref_sub(struct kref *kref, unsigned int count, | 
|  | 64 | void (*release)(struct kref *kref)) | 
|  | 65 | { | 
|  | 66 | WARN_ON(release == NULL); | 
| Peter Zijlstra | 4af679c | 2011-12-13 10:36:20 +0100 | [diff] [blame] | 67 |  | 
|  | 68 | if (atomic_sub_and_test((int) count, &kref->refcount)) { | 
|  | 69 | release(kref); | 
|  | 70 | return 1; | 
|  | 71 | } | 
|  | 72 | return 0; | 
|  | 73 | } | 
| Peter Zijlstra | 47dbd7d | 2011-12-10 11:43:43 +0100 | [diff] [blame] | 74 |  | 
|  | 75 | /** | 
|  | 76 | * kref_put - decrement refcount for object. | 
|  | 77 | * @kref: object. | 
|  | 78 | * @release: pointer to the function that will clean up the object when the | 
|  | 79 | *	     last reference to the object is released. | 
|  | 80 | *	     This pointer is required, and it is not acceptable to pass kfree | 
| Greg Kroah-Hartman | 6261dde | 2011-12-14 11:19:07 -0800 | [diff] [blame] | 81 | *	     in as this function.  If the caller does pass kfree to this | 
|  | 82 | *	     function, you will be publicly mocked mercilessly by the kref | 
|  | 83 | *	     maintainer, and anyone else who happens to notice it.  You have | 
|  | 84 | *	     been warned. | 
| Peter Zijlstra | 47dbd7d | 2011-12-10 11:43:43 +0100 | [diff] [blame] | 85 | * | 
|  | 86 | * Decrement the refcount, and if 0, call release(). | 
|  | 87 | * Return 1 if the object was removed, otherwise return 0.  Beware, if this | 
|  | 88 | * function returns 0, you still can not count on the kref from remaining in | 
|  | 89 | * memory.  Only use the return value if you want to see if the kref is now | 
|  | 90 | * gone, not present. | 
|  | 91 | */ | 
|  | 92 | static inline int kref_put(struct kref *kref, void (*release)(struct kref *kref)) | 
|  | 93 | { | 
|  | 94 | return kref_sub(kref, 1, release); | 
|  | 95 | } | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 96 | #endif /* _KREF_H_ */ |