1 /* Copyright (c) 2010 The Regents of the University of California
2 * Barret Rhoden <brho@cs.berkeley.edu>
3 * See LICENSE for details.
5 * Kernel reference counting, based on Linux's kref:
6 * - http://www.kroah.com/linux/talks/ols_2004_kref_paper/
7 * Reprint-Kroah-Hartman-OLS2004.pdf
8 * - http://lwn.net/Articles/336224/
9 * - Linux's Documentation/kref.txt
11 * See our Documentation/kref.txt for more info. */
13 #ifndef ROS_KERN_KREF_H
14 #define ROS_KERN_KREF_H
19 /* Current versions of Linux pass in 'release' on the kref_put() callsite to
20 * save on space in whatever struct these are embedded in. We don't, since it's
21 * a little more complicated and we will probably change the release function a
22 * lot for subsystems in development. */
25 void (*release)(struct kref *kref);
28 /* Helper for some debugging situations */
29 static long kref_refcnt(struct kref *kref)
31 return atomic_read(&kref->refcount);
34 static void kref_init(struct kref *kref, void (*release)(struct kref *kref),
38 atomic_init(&kref->refcount, init);
39 kref->release = release;
42 /* Will blindly incref */
43 static struct kref *__kref_get(struct kref *kref, unsigned int inc)
45 atomic_add(&kref->refcount, inc);
49 /* Returns the kref ptr on success, 0 on failure */
50 static struct kref *kref_get_not_zero(struct kref *kref, unsigned int inc)
52 if (atomic_add_not_zero(&kref->refcount, inc))
57 /* Will panic on zero */
58 static struct kref *kref_get(struct kref *kref, unsigned int inc)
60 kref = kref_get_not_zero(kref, inc);
65 /* Returns True if we hit 0 and executed 'release', False otherwise */
66 static bool kref_put(struct kref *kref)
68 assert(kref_refcnt(kref) > 0); /* catch some bugs */
69 if (atomic_sub_and_test(&kref->refcount, 1)) {
76 /* Dev / debugging function to catch the attempted freeing of objects we don't
77 * know how to free yet. */
78 static void fake_release(struct kref *kref)
80 panic("Cleaning up this object is not supported!\n");
83 #endif /* ROS_KERN_KREF_H */