Subversion Repositories Kolibri OS

Rev

Rev 5270 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 5270 Rev 6082
Line 23... Line 23...
23
 
23
 
24
struct kref {
24
struct kref {
25
	atomic_t refcount;
25
	atomic_t refcount;
Line -... Line 26...
-
 
26
};
26
};
27
 
27
 
28
/**
-
 
29
 * kref_init - initialize object.
28
void kref_init(struct kref *kref);
30
 * @kref: object in question.
29
void kref_get(struct kref *kref);
-
 
-
 
31
 */
30
int kref_put(struct kref *kref, void (*release) (struct kref *kref));
32
static inline void kref_init(struct kref *kref)
-
 
33
{
Line -... Line 34...
-
 
34
	atomic_set(&kref->refcount, 1);
-
 
35
}
-
 
36
 
-
 
37
/**
-
 
38
 * kref_get - increment refcount for object.
-
 
39
 * @kref: object.
-
 
40
 */
-
 
41
static inline void kref_get(struct kref *kref)
-
 
42
{
-
 
43
	/* If refcount was 0 before incrementing then we have a race
-
 
44
	 * condition when this kref is freeing by some other thread right now.
-
 
45
	 * In this case one should use kref_get_unless_zero()
-
 
46
	 */
-
 
47
	WARN_ON_ONCE(atomic_inc_return(&kref->refcount) < 2);
-
 
48
}
-
 
49
 
-
 
50
/**
-
 
51
 * kref_sub - subtract a number of refcounts for object.
-
 
52
 * @kref: object.
-
 
53
 * @count: Number of recounts to subtract.
-
 
54
 * @release: pointer to the function that will clean up the object when the
-
 
55
 *	     last reference to the object is released.
-
 
56
 *	     This pointer is required, and it is not acceptable to pass kfree
-
 
57
 *	     in as this function.  If the caller does pass kfree to this
-
 
58
 *	     function, you will be publicly mocked mercilessly by the kref
-
 
59
 *	     maintainer, and anyone else who happens to notice it.  You have
-
 
60
 *	     been warned.
-
 
61
 *
-
 
62
 * Subtract @count from the refcount, and if 0, call release().
-
 
63
 * Return 1 if the object was removed, otherwise return 0.  Beware, if this
-
 
64
 * function returns 0, you still can not count on the kref from remaining in
-
 
65
 * memory.  Only use the return value if you want to see if the kref is now
-
 
66
 * gone, not present.
-
 
67
 */
-
 
68
static inline int kref_sub(struct kref *kref, unsigned int count,
-
 
69
	     void (*release)(struct kref *kref))
-
 
70
{
-
 
71
	WARN_ON(release == NULL);
-
 
72
 
-
 
73
	if (atomic_sub_and_test((int) count, &kref->refcount)) {
-
 
74
		release(kref);
-
 
75
		return 1;
-
 
76
	}
-
 
77
	return 0;
-
 
78
}
-
 
79
 
-
 
80
/**
-
 
81
 * kref_put - decrement refcount for object.
-
 
82
 * @kref: object.
-
 
83
 * @release: pointer to the function that will clean up the object when the
-
 
84
 *	     last reference to the object is released.
-
 
85
 *	     This pointer is required, and it is not acceptable to pass kfree
-
 
86
 *	     in as this function.  If the caller does pass kfree to this
-
 
87
 *	     function, you will be publicly mocked mercilessly by the kref
-
 
88
 *	     maintainer, and anyone else who happens to notice it.  You have
-
 
89
 *	     been warned.
-
 
90
 *
-
 
91
 * Decrement the refcount, and if 0, call release().
-
 
92
 * Return 1 if the object was removed, otherwise return 0.  Beware, if this
-
 
93
 * function returns 0, you still can not count on the kref from remaining in
-
 
94
 * memory.  Only use the return value if you want to see if the kref is now
-
 
95
 * gone, not present.
-
 
96
 */
-
 
97
static inline int kref_put(struct kref *kref, void (*release)(struct kref *kref))
-
 
98
{
-
 
99
	return kref_sub(kref, 1, release);
-
 
100
}
-
 
101
 
-
 
102
/**
-
 
103
 * kref_put_spinlock_irqsave - decrement refcount for object.
-
 
104
 * @kref: object.
-
 
105
 * @release: pointer to the function that will clean up the object when the
-
 
106
 *	     last reference to the object is released.
-
 
107
 *	     This pointer is required, and it is not acceptable to pass kfree
-
 
108
 *	     in as this function.
-
 
109
 * @lock: lock to take in release case
-
 
110
 *
-
 
111
 * Behaves identical to kref_put with one exception.  If the reference count
-
 
112
 * drops to zero, the lock will be taken atomically wrt dropping the reference
-
 
113
 * count.  The release function has to call spin_unlock() without _irqrestore.
-
 
114
 */
-
 
115
static inline int kref_put_spinlock_irqsave(struct kref *kref,
-
 
116
		void (*release)(struct kref *kref),
-
 
117
		spinlock_t *lock)
-
 
118
{
-
 
119
	unsigned long flags;
-
 
120
 
-
 
121
	WARN_ON(release == NULL);
-
 
122
	if (atomic_add_unless(&kref->refcount, -1, 1))
-
 
123
		return 0;
-
 
124
	spin_lock_irqsave(lock, flags);
-
 
125
	if (atomic_dec_and_test(&kref->refcount)) {
-
 
126
		release(kref);
-
 
127
		local_irq_restore(flags);
-
 
128
		return 1;
-
 
129
	}
-
 
130
	spin_unlock_irqrestore(lock, flags);
-
 
131
	return 0;
-
 
132
}
-
 
133
 
-
 
134
static inline int kref_put_mutex(struct kref *kref,
-
 
135
				 void (*release)(struct kref *kref),
-
 
136
				 struct mutex *lock)
-
 
137
{
-
 
138
	WARN_ON(release == NULL);
-
 
139
	if (unlikely(!atomic_add_unless(&kref->refcount, -1, 1))) {
-
 
140
		mutex_lock(lock);
-
 
141
		if (unlikely(!atomic_dec_and_test(&kref->refcount))) {
-
 
142
			mutex_unlock(lock);
-
 
143
			return 0;
-
 
144
		}
-
 
145
		release(kref);
-
 
146
		return 1;
-
 
147
	}
-
 
148
	return 0;
-
 
149
}
-
 
150
 
-
 
151
/**
-
 
152
 * kref_get_unless_zero - Increment refcount for object unless it is zero.
-
 
153
 * @kref: object.
-
 
154
 *
-
 
155
 * Return non-zero if the increment succeeded. Otherwise return 0.
-
 
156
 *
-
 
157
 * This function is intended to simplify locking around refcounting for
-
 
158
 * objects that can be looked up from a lookup structure, and which are
-
 
159
 * removed from that lookup structure in the object destructor.
-
 
160
 * Operations on such objects require at least a read lock around
-
 
161
 * lookup + kref_get, and a write lock around kref_put + remove from lookup
-
 
162
 * structure. Furthermore, RCU implementations become extremely tricky.
-
 
163
 * With a lookup followed by a kref_get_unless_zero *with return value check*
-
 
164
 * locking in the kref_put path can be deferred to the actual removal from
-
 
165
 * the lookup structure and RCU lookups become trivial.
-
 
166
 */
-
 
167
static inline int __must_check kref_get_unless_zero(struct kref *kref)
31
int kref_sub(struct kref *kref, unsigned int count,
168
{