diff options
Diffstat (limited to 'include/linux')
| -rw-r--r-- | include/linux/kref.h | 124 |
1 files changed, 124 insertions, 0 deletions
diff --git a/include/linux/kref.h b/include/linux/kref.h new file mode 100644 index 00000000000..30927047d54 --- /dev/null +++ b/include/linux/kref.h @@ -0,0 +1,124 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * kref.h - library routines for handling generic reference counted objects + * + * Copyright (C) 2004 Greg Kroah-Hartman <[email protected]> + * Copyright (C) 2004 IBM Corp. + * + * based on kobject.h which was: + * Copyright (C) 2002-2003 Patrick Mochel <[email protected]> + * Copyright (C) 2002-2003 Open Source Development Labs + */ + +#ifndef _KREF_H_ +#define _KREF_H_ + +#include <linux/compat.h> + +struct kref { + long refcount; +}; + +#define KREF_INIT(n) { .refcount = REFCOUNT_INIT(n), } + +/** + * kref_init - initialize object. + * @kref: object in question. + */ +static inline void kref_init(struct kref *kref) +{ + kref->refcount = 1; +} + +static inline unsigned int kref_read(const struct kref *kref) +{ + return kref->refcount; +} + +/** + * kref_get - increment refcount for object. + * @kref: object. + */ +static inline void kref_get(struct kref *kref) +{ + kref->refcount++; +} + +/** + * kref_put - Decrement refcount for object + * @kref: Object + * @release: Pointer to the function that will clean up the object when the + * last reference to the object is released. + * + * Decrement the refcount, and if 0, call @release. The caller may not + * pass NULL or kfree() as the release function. + * + * Return: 1 if this call removed the object, otherwise return 0. Beware, + * if this function returns 0, another caller may have removed the object + * by the time this function returns. The return value is only certain + * if you want to see if the object is definitely released. + */ +static inline int kref_put(struct kref *kref, void (*release)(struct kref *kref)) +{ + if (--kref->refcount == 0) { + release(kref); + return 1; + } + return 0; +} + +/** + * kref_put_mutex - Decrement refcount for object + * @kref: Object + * @release: Pointer to the function that will clean up the object when the + * last reference to the object is released. + * @mutex: Mutex which protects the release function. + * + * This variant of kref_lock() calls the @release function with the @mutex + * held. The @release function will release the mutex. + */ +static inline int kref_put_mutex(struct kref *kref, + void (*release)(struct kref *kref), + struct mutex *mutex) +{ + return kref_put(kref, release); +} + +/** + * kref_put_lock - Decrement refcount for object + * @kref: Object + * @release: Pointer to the function that will clean up the object when the + * last reference to the object is released. + * @lock: Spinlock which protects the release function. + * + * This variant of kref_lock() calls the @release function with the @lock + * held. The @release function will release the lock. + */ +static inline int kref_put_lock(struct kref *kref, + void (*release)(struct kref *kref), + spinlock_t *lock) +{ + return kref_put(kref, release); +} + +/** + * kref_get_unless_zero - Increment refcount for object unless it is zero. + * @kref: object. + * + * This function is intended to simplify locking around refcounting for + * objects that can be looked up from a lookup structure, and which are + * removed from that lookup structure in the object destructor. + * Operations on such objects require at least a read lock around + * lookup + kref_get, and a write lock around kref_put + remove from lookup + * structure. Furthermore, RCU implementations become extremely tricky. + * With a lookup followed by a kref_get_unless_zero *with return value check* + * locking in the kref_put path can be deferred to the actual removal from + * the lookup structure and RCU lookups become trivial. + * + * Return: non-zero if the increment succeeded. Otherwise return 0. + */ +static inline int kref_get_unless_zero(struct kref *kref) +{ + return kref->refcount ? kref->refcount++ : 0; +} +#endif /* _KREF_H_ */ |
