18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */ 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * kref.h - library routines for handling generic reference counted objects 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (C) 2004 Greg Kroah-Hartman <greg@kroah.com> 68c2ecf20Sopenharmony_ci * Copyright (C) 2004 IBM Corp. 78c2ecf20Sopenharmony_ci * 88c2ecf20Sopenharmony_ci * based on kobject.h which was: 98c2ecf20Sopenharmony_ci * Copyright (C) 2002-2003 Patrick Mochel <mochel@osdl.org> 108c2ecf20Sopenharmony_ci * Copyright (C) 2002-2003 Open Source Development Labs 118c2ecf20Sopenharmony_ci */ 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_ci#ifndef _KREF_H_ 148c2ecf20Sopenharmony_ci#define _KREF_H_ 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_ci#include <linux/spinlock.h> 178c2ecf20Sopenharmony_ci#include <linux/refcount.h> 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_cistruct kref { 208c2ecf20Sopenharmony_ci refcount_t refcount; 218c2ecf20Sopenharmony_ci}; 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_ci#define KREF_INIT(n) { .refcount = REFCOUNT_INIT(n), } 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_ci/** 268c2ecf20Sopenharmony_ci * kref_init - initialize object. 278c2ecf20Sopenharmony_ci * @kref: object in question. 288c2ecf20Sopenharmony_ci */ 298c2ecf20Sopenharmony_cistatic inline void kref_init(struct kref *kref) 308c2ecf20Sopenharmony_ci{ 318c2ecf20Sopenharmony_ci refcount_set(&kref->refcount, 1); 328c2ecf20Sopenharmony_ci} 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_cistatic inline unsigned int kref_read(const struct kref *kref) 358c2ecf20Sopenharmony_ci{ 368c2ecf20Sopenharmony_ci return refcount_read(&kref->refcount); 378c2ecf20Sopenharmony_ci} 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_ci/** 408c2ecf20Sopenharmony_ci * kref_get - increment refcount for object. 418c2ecf20Sopenharmony_ci * @kref: object. 428c2ecf20Sopenharmony_ci */ 438c2ecf20Sopenharmony_cistatic inline void kref_get(struct kref *kref) 448c2ecf20Sopenharmony_ci{ 458c2ecf20Sopenharmony_ci refcount_inc(&kref->refcount); 468c2ecf20Sopenharmony_ci} 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_ci/** 498c2ecf20Sopenharmony_ci * kref_put - decrement refcount for object. 508c2ecf20Sopenharmony_ci * @kref: object. 518c2ecf20Sopenharmony_ci * @release: pointer to the function that will clean up the object when the 528c2ecf20Sopenharmony_ci * last reference to the object is released. 538c2ecf20Sopenharmony_ci * This pointer is required, and it is not acceptable to pass kfree 548c2ecf20Sopenharmony_ci * in as this function. 558c2ecf20Sopenharmony_ci * 568c2ecf20Sopenharmony_ci * Decrement the refcount, and if 0, call release(). 578c2ecf20Sopenharmony_ci * Return 1 if the object was removed, otherwise return 0. Beware, if this 588c2ecf20Sopenharmony_ci * function returns 0, you still can not count on the kref from remaining in 598c2ecf20Sopenharmony_ci * memory. Only use the return value if you want to see if the kref is now 608c2ecf20Sopenharmony_ci * gone, not present. 618c2ecf20Sopenharmony_ci */ 628c2ecf20Sopenharmony_cistatic inline int kref_put(struct kref *kref, void (*release)(struct kref *kref)) 638c2ecf20Sopenharmony_ci{ 648c2ecf20Sopenharmony_ci if (refcount_dec_and_test(&kref->refcount)) { 658c2ecf20Sopenharmony_ci release(kref); 668c2ecf20Sopenharmony_ci return 1; 678c2ecf20Sopenharmony_ci } 688c2ecf20Sopenharmony_ci return 0; 698c2ecf20Sopenharmony_ci} 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_cistatic inline int kref_put_mutex(struct kref *kref, 728c2ecf20Sopenharmony_ci void (*release)(struct kref *kref), 738c2ecf20Sopenharmony_ci struct mutex *lock) 748c2ecf20Sopenharmony_ci{ 758c2ecf20Sopenharmony_ci if (refcount_dec_and_mutex_lock(&kref->refcount, lock)) { 768c2ecf20Sopenharmony_ci release(kref); 778c2ecf20Sopenharmony_ci return 1; 788c2ecf20Sopenharmony_ci } 798c2ecf20Sopenharmony_ci return 0; 808c2ecf20Sopenharmony_ci} 818c2ecf20Sopenharmony_ci 828c2ecf20Sopenharmony_cistatic inline int kref_put_lock(struct kref *kref, 838c2ecf20Sopenharmony_ci void (*release)(struct kref *kref), 848c2ecf20Sopenharmony_ci spinlock_t *lock) 858c2ecf20Sopenharmony_ci{ 868c2ecf20Sopenharmony_ci if (refcount_dec_and_lock(&kref->refcount, lock)) { 878c2ecf20Sopenharmony_ci release(kref); 888c2ecf20Sopenharmony_ci return 1; 898c2ecf20Sopenharmony_ci } 908c2ecf20Sopenharmony_ci return 0; 918c2ecf20Sopenharmony_ci} 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_ci/** 948c2ecf20Sopenharmony_ci * kref_get_unless_zero - Increment refcount for object unless it is zero. 958c2ecf20Sopenharmony_ci * @kref: object. 968c2ecf20Sopenharmony_ci * 978c2ecf20Sopenharmony_ci * Return non-zero if the increment succeeded. Otherwise return 0. 988c2ecf20Sopenharmony_ci * 998c2ecf20Sopenharmony_ci * This function is intended to simplify locking around refcounting for 1008c2ecf20Sopenharmony_ci * objects that can be looked up from a lookup structure, and which are 1018c2ecf20Sopenharmony_ci * removed from that lookup structure in the object destructor. 1028c2ecf20Sopenharmony_ci * Operations on such objects require at least a read lock around 1038c2ecf20Sopenharmony_ci * lookup + kref_get, and a write lock around kref_put + remove from lookup 1048c2ecf20Sopenharmony_ci * structure. Furthermore, RCU implementations become extremely tricky. 1058c2ecf20Sopenharmony_ci * With a lookup followed by a kref_get_unless_zero *with return value check* 1068c2ecf20Sopenharmony_ci * locking in the kref_put path can be deferred to the actual removal from 1078c2ecf20Sopenharmony_ci * the lookup structure and RCU lookups become trivial. 1088c2ecf20Sopenharmony_ci */ 1098c2ecf20Sopenharmony_cistatic inline int __must_check kref_get_unless_zero(struct kref *kref) 1108c2ecf20Sopenharmony_ci{ 1118c2ecf20Sopenharmony_ci return refcount_inc_not_zero(&kref->refcount); 1128c2ecf20Sopenharmony_ci} 1138c2ecf20Sopenharmony_ci#endif /* _KREF_H_ */ 114