| /* SPDX-License-Identifier: GPL-2.0-only */ | |
| /* | |
| * kref.h - library routines for handling generic reference counted objects | |
| * | |
| * Copyright (C) 2004 Greg Kroah-Hartman <greg@kroah.com> | |
| * Copyright (C) 2004 IBM Corp. | |
| * | |
| * based on kobject.h which was: | |
| * Copyright (C) 2002-2003 Patrick Mochel <mochel@osdl.org> | |
| * 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_ */ |