forked from Assunzain/Kernel_asus_X01AD
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
tools include: Adopt kernel's refcount.h
commit 73a9bf95ed1c05698ecabe2f28c47aedfa61b52b upstream. To aid in catching bugs when using atomics as a reference count. This is a trimmed down version with just what is used by tools/ at this point. After this, the patches submitted by Elena for tools/ doing the conversion from atomic_ to recount_ methods can be applied and tested. To activate it, buint perf with: make DEBUG=1 -C tools/perf Cc: Adrian Hunter <[email protected]> Cc: David Ahern <[email protected]> Cc: Elena Reshetova <[email protected]> Cc: Jiri Olsa <[email protected]> Cc: Namhyung Kim <[email protected]> Cc: Wang Nan <[email protected]> Link: http://lkml.kernel.org/n/[email protected] Signed-off-by: Arnaldo Carvalho de Melo <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
- Loading branch information
Showing
2 changed files
with
152 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,151 @@ | ||
#ifndef _TOOLS_LINUX_REFCOUNT_H | ||
#define _TOOLS_LINUX_REFCOUNT_H | ||
|
||
/* | ||
* Variant of atomic_t specialized for reference counts. | ||
* | ||
* The interface matches the atomic_t interface (to aid in porting) but only | ||
* provides the few functions one should use for reference counting. | ||
* | ||
* It differs in that the counter saturates at UINT_MAX and will not move once | ||
* there. This avoids wrapping the counter and causing 'spurious' | ||
* use-after-free issues. | ||
* | ||
* Memory ordering rules are slightly relaxed wrt regular atomic_t functions | ||
* and provide only what is strictly required for refcounts. | ||
* | ||
* The increments are fully relaxed; these will not provide ordering. The | ||
* rationale is that whatever is used to obtain the object we're increasing the | ||
* reference count on will provide the ordering. For locked data structures, | ||
* its the lock acquire, for RCU/lockless data structures its the dependent | ||
* load. | ||
* | ||
* Do note that inc_not_zero() provides a control dependency which will order | ||
* future stores against the inc, this ensures we'll never modify the object | ||
* if we did not in fact acquire a reference. | ||
* | ||
* The decrements will provide release order, such that all the prior loads and | ||
* stores will be issued before, it also provides a control dependency, which | ||
* will order us against the subsequent free(). | ||
* | ||
* The control dependency is against the load of the cmpxchg (ll/sc) that | ||
* succeeded. This means the stores aren't fully ordered, but this is fine | ||
* because the 1->0 transition indicates no concurrency. | ||
* | ||
* Note that the allocator is responsible for ordering things between free() | ||
* and alloc(). | ||
* | ||
*/ | ||
|
||
#include <linux/atomic.h> | ||
#include <linux/kernel.h> | ||
|
||
#ifdef NDEBUG | ||
#define REFCOUNT_WARN(cond, str) (void)(cond) | ||
#define __refcount_check | ||
#else | ||
#define REFCOUNT_WARN(cond, str) BUG_ON(cond) | ||
#define __refcount_check __must_check | ||
#endif | ||
|
||
typedef struct refcount_struct { | ||
atomic_t refs; | ||
} refcount_t; | ||
|
||
#define REFCOUNT_INIT(n) { .refs = ATOMIC_INIT(n), } | ||
|
||
static inline void refcount_set(refcount_t *r, unsigned int n) | ||
{ | ||
atomic_set(&r->refs, n); | ||
} | ||
|
||
static inline unsigned int refcount_read(const refcount_t *r) | ||
{ | ||
return atomic_read(&r->refs); | ||
} | ||
|
||
/* | ||
* Similar to atomic_inc_not_zero(), will saturate at UINT_MAX and WARN. | ||
* | ||
* Provides no memory ordering, it is assumed the caller has guaranteed the | ||
* object memory to be stable (RCU, etc.). It does provide a control dependency | ||
* and thereby orders future stores. See the comment on top. | ||
*/ | ||
static inline __refcount_check | ||
bool refcount_inc_not_zero(refcount_t *r) | ||
{ | ||
unsigned int old, new, val = atomic_read(&r->refs); | ||
|
||
for (;;) { | ||
new = val + 1; | ||
|
||
if (!val) | ||
return false; | ||
|
||
if (unlikely(!new)) | ||
return true; | ||
|
||
old = atomic_cmpxchg_relaxed(&r->refs, val, new); | ||
if (old == val) | ||
break; | ||
|
||
val = old; | ||
} | ||
|
||
REFCOUNT_WARN(new == UINT_MAX, "refcount_t: saturated; leaking memory.\n"); | ||
|
||
return true; | ||
} | ||
|
||
/* | ||
* Similar to atomic_inc(), will saturate at UINT_MAX and WARN. | ||
* | ||
* Provides no memory ordering, it is assumed the caller already has a | ||
* reference on the object, will WARN when this is not so. | ||
*/ | ||
static inline void refcount_inc(refcount_t *r) | ||
{ | ||
REFCOUNT_WARN(!refcount_inc_not_zero(r), "refcount_t: increment on 0; use-after-free.\n"); | ||
} | ||
|
||
/* | ||
* Similar to atomic_dec_and_test(), it will WARN on underflow and fail to | ||
* decrement when saturated at UINT_MAX. | ||
* | ||
* Provides release memory ordering, such that prior loads and stores are done | ||
* before, and provides a control dependency such that free() must come after. | ||
* See the comment on top. | ||
*/ | ||
static inline __refcount_check | ||
bool refcount_sub_and_test(unsigned int i, refcount_t *r) | ||
{ | ||
unsigned int old, new, val = atomic_read(&r->refs); | ||
|
||
for (;;) { | ||
if (unlikely(val == UINT_MAX)) | ||
return false; | ||
|
||
new = val - i; | ||
if (new > val) { | ||
REFCOUNT_WARN(new > val, "refcount_t: underflow; use-after-free.\n"); | ||
return false; | ||
} | ||
|
||
old = atomic_cmpxchg_release(&r->refs, val, new); | ||
if (old == val) | ||
break; | ||
|
||
val = old; | ||
} | ||
|
||
return !new; | ||
} | ||
|
||
static inline __refcount_check | ||
bool refcount_dec_and_test(refcount_t *r) | ||
{ | ||
return refcount_sub_and_test(1, r); | ||
} | ||
|
||
|
||
#endif /* _ATOMIC_LINUX_REFCOUNT_H */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters