1*53e1df33Sjsg /* $OpenBSD: kref.h,v 1.6 2023/03/21 09:44:35 jsg Exp $ */
27f4dd379Sjsg /*
37f4dd379Sjsg * Copyright (c) 2015 Mark Kettenis
47f4dd379Sjsg *
57f4dd379Sjsg * Permission to use, copy, modify, and distribute this software for any
67f4dd379Sjsg * purpose with or without fee is hereby granted, provided that the above
77f4dd379Sjsg * copyright notice and this permission notice appear in all copies.
87f4dd379Sjsg *
97f4dd379Sjsg * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
107f4dd379Sjsg * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
117f4dd379Sjsg * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
127f4dd379Sjsg * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
137f4dd379Sjsg * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
147f4dd379Sjsg * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
157f4dd379Sjsg * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
167f4dd379Sjsg */
177f4dd379Sjsg
187f4dd379Sjsg #ifndef _LINUX_KREF_H
197f4dd379Sjsg #define _LINUX_KREF_H
207f4dd379Sjsg
217f4dd379Sjsg #include <sys/types.h>
227f4dd379Sjsg #include <sys/rwlock.h>
237f4dd379Sjsg #include <linux/refcount.h>
241bb76ff1Sjsg #include <linux/spinlock.h>
257f4dd379Sjsg
267f4dd379Sjsg struct kref {
277f4dd379Sjsg uint32_t refcount;
287f4dd379Sjsg };
297f4dd379Sjsg
307f4dd379Sjsg static inline void
kref_init(struct kref * ref)317f4dd379Sjsg kref_init(struct kref *ref)
327f4dd379Sjsg {
33614b2142Sjsg atomic_set(&ref->refcount, 1);
347f4dd379Sjsg }
357f4dd379Sjsg
367f4dd379Sjsg static inline unsigned int
kref_read(const struct kref * ref)377f4dd379Sjsg kref_read(const struct kref *ref)
387f4dd379Sjsg {
397f4dd379Sjsg return atomic_read(&ref->refcount);
407f4dd379Sjsg }
417f4dd379Sjsg
427f4dd379Sjsg static inline void
kref_get(struct kref * ref)437f4dd379Sjsg kref_get(struct kref *ref)
447f4dd379Sjsg {
457f4dd379Sjsg atomic_inc_int(&ref->refcount);
467f4dd379Sjsg }
477f4dd379Sjsg
487f4dd379Sjsg static inline int
kref_get_unless_zero(struct kref * ref)497f4dd379Sjsg kref_get_unless_zero(struct kref *ref)
507f4dd379Sjsg {
517f4dd379Sjsg if (ref->refcount != 0) {
527f4dd379Sjsg atomic_inc_int(&ref->refcount);
537f4dd379Sjsg return (1);
547f4dd379Sjsg } else {
557f4dd379Sjsg return (0);
567f4dd379Sjsg }
577f4dd379Sjsg }
587f4dd379Sjsg
597f4dd379Sjsg static inline int
kref_put(struct kref * ref,void (* release)(struct kref * ref))607f4dd379Sjsg kref_put(struct kref *ref, void (*release)(struct kref *ref))
617f4dd379Sjsg {
627f4dd379Sjsg if (atomic_dec_int_nv(&ref->refcount) == 0) {
637f4dd379Sjsg release(ref);
647f4dd379Sjsg return 1;
657f4dd379Sjsg }
667f4dd379Sjsg return 0;
677f4dd379Sjsg }
687f4dd379Sjsg
697f4dd379Sjsg static inline int
kref_put_mutex(struct kref * kref,void (* release)(struct kref * kref),struct rwlock * lock)707f4dd379Sjsg kref_put_mutex(struct kref *kref, void (*release)(struct kref *kref),
717f4dd379Sjsg struct rwlock *lock)
727f4dd379Sjsg {
737f4dd379Sjsg if (!atomic_add_unless(&kref->refcount, -1, 1)) {
747f4dd379Sjsg rw_enter_write(lock);
757f4dd379Sjsg if (likely(atomic_dec_and_test(&kref->refcount))) {
767f4dd379Sjsg release(kref);
777f4dd379Sjsg return 1;
787f4dd379Sjsg }
797f4dd379Sjsg rw_exit_write(lock);
807f4dd379Sjsg return 0;
817f4dd379Sjsg }
827f4dd379Sjsg
837f4dd379Sjsg return 0;
847f4dd379Sjsg }
857f4dd379Sjsg
86c349dbc7Sjsg static inline int
kref_put_lock(struct kref * kref,void (* release)(struct kref * kref),struct mutex * lock)87c349dbc7Sjsg kref_put_lock(struct kref *kref, void (*release)(struct kref *kref),
88c349dbc7Sjsg struct mutex *lock)
89c349dbc7Sjsg {
90c349dbc7Sjsg if (!atomic_add_unless(&kref->refcount, -1, 1)) {
91c349dbc7Sjsg mtx_enter(lock);
92c349dbc7Sjsg if (likely(atomic_dec_and_test(&kref->refcount))) {
93c349dbc7Sjsg release(kref);
94c349dbc7Sjsg return 1;
95c349dbc7Sjsg }
96c349dbc7Sjsg mtx_leave(lock);
97c349dbc7Sjsg return 0;
98c349dbc7Sjsg }
99c349dbc7Sjsg
100c349dbc7Sjsg return 0;
101c349dbc7Sjsg }
102c349dbc7Sjsg
1037f4dd379Sjsg #endif
104