History

locking/refcount: Consolidate implementations of refcount_t

The generic implementation of refcount_t should be good enough for everybody, so remove ARCH_HAS_REFCOUNT and REFCOUNT_FULL entirely, leaving the generic implementation enabled unconditionally.

Will Deacon committed 6 years ago

Commit fb041bb1 parent 65b008511 files · +59 −308Browse files

Showing the changes to include/linux (1 of 11 files). Show all

Unified · Split

include/linux/refcount.h+58−100
@@ -1,64 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */1/* SPDX-License-Identifier: GPL-2.0 */
2#ifndef _LINUX_REFCOUNT_H
3#define _LINUX_REFCOUNT_H
4
5#include <linux/atomic.h>
6#include <linux/compiler.h>
7#include <linux/limits.h>
8#include <linux/spinlock_types.h>
9
10struct mutex;
11
12/**
13 * struct refcount_t - variant of atomic_t specialized for reference counts
14 * @refs: atomic_t counter field
15 *
16 * The counter saturates at REFCOUNT_SATURATED and will not move once
17 * there. This avoids wrapping the counter and causing 'spurious'
18 * use-after-free bugs.
19 */
20typedef struct refcount_struct {
21 atomic_t refs;
22} refcount_t;
23
24#define REFCOUNT_INIT(n) { .refs = ATOMIC_INIT(n), }
25#define REFCOUNT_MAX INT_MAX
26#define REFCOUNT_SATURATED (INT_MIN / 2)
27
28enum refcount_saturation_type {
29 REFCOUNT_ADD_NOT_ZERO_OVF,
30 REFCOUNT_ADD_OVF,
31 REFCOUNT_ADD_UAF,
32 REFCOUNT_SUB_UAF,
33 REFCOUNT_DEC_LEAK,
34};
35
36void refcount_warn_saturate(refcount_t *r, enum refcount_saturation_type t);
37
38/**
39 * refcount_set - set a refcount's value
40 * @r: the refcount
41 * @n: value to which the refcount will be set
42 */
43static inline void refcount_set(refcount_t *r, int n)
44{
45 atomic_set(&r->refs, n);
46}
47
48/**
49 * refcount_read - get a refcount's value
50 * @r: the refcount
51 *
52 * Return: the refcount's value
53 */
54static inline unsigned int refcount_read(const refcount_t *r)
55{
56 return atomic_read(&r->refs);
57}
58
59#ifdef CONFIG_REFCOUNT_FULL
60#include <linux/bug.h>
61
62/*2/*
63 * Variant of atomic_t specialized for reference counts.3 * Variant of atomic_t specialized for reference counts.
64 *4 *
@@ -136,6 +76,64 @@ static inline unsigned int refcount_read(const refcount_t *r) · 71 unmodified lines
136 *76 *
137 */77 */
138 78
79#ifndef _LINUX_REFCOUNT_H
80#define _LINUX_REFCOUNT_H
81
82#include <linux/atomic.h>
83#include <linux/bug.h>
84#include <linux/compiler.h>
85#include <linux/limits.h>
86#include <linux/spinlock_types.h>
87
88struct mutex;
89
90/**
91 * struct refcount_t - variant of atomic_t specialized for reference counts
92 * @refs: atomic_t counter field
93 *
94 * The counter saturates at REFCOUNT_SATURATED and will not move once
95 * there. This avoids wrapping the counter and causing 'spurious'
96 * use-after-free bugs.
97 */
98typedef struct refcount_struct {
99 atomic_t refs;
100} refcount_t;
101
102#define REFCOUNT_INIT(n) { .refs = ATOMIC_INIT(n), }
103#define REFCOUNT_MAX INT_MAX
104#define REFCOUNT_SATURATED (INT_MIN / 2)
105
106enum refcount_saturation_type {
107 REFCOUNT_ADD_NOT_ZERO_OVF,
108 REFCOUNT_ADD_OVF,
109 REFCOUNT_ADD_UAF,
110 REFCOUNT_SUB_UAF,
111 REFCOUNT_DEC_LEAK,
112};
113
114void refcount_warn_saturate(refcount_t *r, enum refcount_saturation_type t);
115
116/**
117 * refcount_set - set a refcount's value
118 * @r: the refcount
119 * @n: value to which the refcount will be set
120 */
121static inline void refcount_set(refcount_t *r, int n)
122{
123 atomic_set(&r->refs, n);
124}
125
126/**
127 * refcount_read - get a refcount's value
128 * @r: the refcount
129 *
130 * Return: the refcount's value
131 */
132static inline unsigned int refcount_read(const refcount_t *r)
133{
134 return atomic_read(&r->refs);
135}
136
139/**137/**
140 * refcount_add_not_zero - add a value to a refcount unless it is 0138 * refcount_add_not_zero - add a value to a refcount unless it is 0
141 * @i: the value to add to the refcount139 * @i: the value to add to the refcount
@@ -298,46 +296,6 @@ static inline void refcount_dec(refcount_t *r) · 156 unmodified lines
298 if (unlikely(atomic_fetch_sub_release(1, &r->refs) <= 1))296 if (unlikely(atomic_fetch_sub_release(1, &r->refs) <= 1))
299 refcount_warn_saturate(r, REFCOUNT_DEC_LEAK);297 refcount_warn_saturate(r, REFCOUNT_DEC_LEAK);
300}298}
301#else /* CONFIG_REFCOUNT_FULL */
302# ifdef CONFIG_ARCH_HAS_REFCOUNT
303# include <asm/refcount.h>
304# else
305static inline __must_check bool refcount_add_not_zero(int i, refcount_t *r)
306{
307 return atomic_add_unless(&r->refs, i, 0);
308}
309
310static inline void refcount_add(int i, refcount_t *r)
311{
312 atomic_add(i, &r->refs);
313}
314
315static inline __must_check bool refcount_inc_not_zero(refcount_t *r)
316{
317 return atomic_add_unless(&r->refs, 1, 0);
318}
319
320static inline void refcount_inc(refcount_t *r)
321{
322 atomic_inc(&r->refs);
323}
324
325static inline __must_check bool refcount_sub_and_test(int i, refcount_t *r)
326{
327 return atomic_sub_and_test(i, &r->refs);
328}
329
330static inline __must_check bool refcount_dec_and_test(refcount_t *r)
331{
332 return atomic_dec_and_test(&r->refs);
333}
334
335static inline void refcount_dec(refcount_t *r)
336{
337 atomic_dec(&r->refs);
338}
339# endif /* !CONFIG_ARCH_HAS_REFCOUNT */
340#endif /* !CONFIG_REFCOUNT_FULL */
341 299
342extern __must_check bool refcount_dec_if_one(refcount_t *r);300extern __must_check bool refcount_dec_if_one(refcount_t *r);
343extern __must_check bool refcount_dec_not_one(refcount_t *r);301extern __must_check bool refcount_dec_not_one(refcount_t *r);

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t