xref: /openbsd-src/sys/dev/pci/drm/include/linux/kref.h (revision 4b70baf6e17fc8b27fc1f7fa7929335753fa94c3)
1 /*	$OpenBSD: kref.h,v 1.1 2019/04/14 10:14:53 jsg Exp $	*/
2 /*
3  * Copyright (c) 2015 Mark Kettenis
4  *
5  * Permission to use, copy, modify, and distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16  */
17 
18 #ifndef _LINUX_KREF_H
19 #define _LINUX_KREF_H
20 
21 #include <sys/types.h>
22 #include <sys/rwlock.h>
23 #include <sys/atomic.h>
24 #include <linux/atomic.h>
25 #include <linux/compiler.h>
26 #include <linux/refcount.h>
27 
28 struct kref {
29 	uint32_t refcount;
30 };
31 
32 static inline void
33 kref_init(struct kref *ref)
34 {
35 	ref->refcount = 1;
36 }
37 
38 static inline unsigned int
39 kref_read(const struct kref *ref)
40 {
41 	return atomic_read(&ref->refcount);
42 }
43 
44 static inline void
45 kref_get(struct kref *ref)
46 {
47 	atomic_inc_int(&ref->refcount);
48 }
49 
50 static inline int
51 kref_get_unless_zero(struct kref *ref)
52 {
53 	if (ref->refcount != 0) {
54 		atomic_inc_int(&ref->refcount);
55 		return (1);
56 	} else {
57 		return (0);
58 	}
59 }
60 
61 static inline int
62 kref_put(struct kref *ref, void (*release)(struct kref *ref))
63 {
64 	if (atomic_dec_int_nv(&ref->refcount) == 0) {
65 		release(ref);
66 		return 1;
67 	}
68 	return 0;
69 }
70 
71 static inline void
72 kref_sub(struct kref *ref, unsigned int v, void (*release)(struct kref *ref))
73 {
74 	if (atomic_sub_int_nv(&ref->refcount, v) == 0)
75 		release(ref);
76 }
77 
78 static inline int
79 kref_put_mutex(struct kref *kref, void (*release)(struct kref *kref),
80     struct rwlock *lock)
81 {
82 	if (!atomic_add_unless(&kref->refcount, -1, 1)) {
83 		rw_enter_write(lock);
84 		if (likely(atomic_dec_and_test(&kref->refcount))) {
85 			release(kref);
86 			return 1;
87 		}
88 		rw_exit_write(lock);
89 		return 0;
90 	}
91 
92 	return 0;
93 }
94 
95 #endif
96