1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
|
From 8faea20349dc1d8cfd0117d28a3f1271083192d0 Mon Sep 17 00:00:00 2001
From: Justus Winter <4winter@informatik.uni-hamburg.de>
Date: Tue, 6 May 2014 19:52:04 +0200
Subject: [PATCH 2/5] include: add lock-less reference counting primitives
* include/refcount.h: New file.
---
include/refcount.h | 155 +++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 155 insertions(+)
create mode 100644 include/refcount.h
diff --git a/include/refcount.h b/include/refcount.h
new file mode 100644
index 0000000..946938a
--- /dev/null
+++ b/include/refcount.h
@@ -0,0 +1,155 @@
+/* Lock-less reference counting primitives
+
+ Copyright (C) 2014 Free Software Foundation, Inc.
+
+ Written by Justus Winter <4winter@informatik.uni-hamburg.de>
+
+ This file is part of the GNU Hurd.
+
+ The GNU Hurd is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ The GNU Hurd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with the GNU Hurd. If not, see <http://www.gnu.org/licenses/>. */
+
+#ifndef _HURD_REFCOUNT_H_
+#define _HURD_REFCOUNT_H_
+
+#include <stdint.h>
+
+/* Simple reference counting. */
+
+/* An opaque type. You must not access these values directly. */
+typedef uint32_t refcount_t;
+
+/* Initialize REF with REFERENCES. */
+static inline void
+refcount_init (refcount_t *ref, uint32_t references)
+{
+ *ref = references;
+}
+
+/* Increment REF. Return the result of the operation. */
+static inline uint32_t
+refcount_ref (refcount_t *ref)
+{
+ return __atomic_add_fetch (ref, 1, __ATOMIC_RELAXED);
+}
+
+/* Decrement REF. Return the result of the operation. */
+static inline uint32_t
+refcount_deref (refcount_t *ref)
+{
+ return __atomic_sub_fetch (ref, 1, __ATOMIC_RELAXED);
+}
+
+/* Return REF. */
+static inline uint32_t
+refcount_references (refcount_t *ref)
+{
+ return __atomic_load_n (ref, __ATOMIC_RELAXED);
+}
+
+/* Reference counting with weak references. */
+
+/* An opaque type. You must not access these values directly. */
+typedef uint64_t refcounts_t;
+
+/* Instead, the functions manipulating refcounts_t values write the
+ results into this kind of objects. */
+struct references {
+ uint32_t hard;
+ uint32_t weak;
+};
+
+union _references {
+ struct references refs;
+ refcounts_t rc;
+};
+
+/* Initialize REF with HARD and WEAK references. */
+static inline void
+refcounts_init (refcounts_t *ref, uint32_t hard, uint32_t weak)
+{
+ ((union _references *) ref)->refs =
+ (struct references) { .hard = hard, .weak = weak };
+}
+
+/* Increment the hard reference count of REF. If RESULT is not NULL,
+ the result of the operation is written there. */
+static inline void
+refcounts_ref (refcounts_t *ref, struct references *result)
+{
+ const union _references op = { .refs = { .hard = 1 } };
+ refcounts_t r = __atomic_add_fetch (ref, op.rc, __ATOMIC_RELAXED);
+ if (result)
+ ((union _references *) result)->rc = r;
+}
+
+/* Decrement the hard reference count of REF. If RESULT is not NULL,
+ the result of the operation is written there. */
+static inline void
+refcounts_deref (refcounts_t *ref, struct references *result)
+{
+ const union _references op = { .refs = { .hard = 1 } };
+ refcounts_t r = __atomic_sub_fetch (ref, op.rc, __ATOMIC_RELAXED);
+ if (result)
+ ((union _references *) result)->rc = r;
+}
+
+/* Increment the weak reference count of REF. If RESULT is not NULL,
+ the result of the operation is written there. */
+static inline void
+refcounts_ref_weak (refcounts_t *ref, struct references *result)
+{
+ const union _references op = { .refs = { .weak = 1 } };
+ refcounts_t r = __atomic_add_fetch (ref, op.rc, __ATOMIC_RELAXED);
+ if (result)
+ ((union _references *) result)->rc = r;
+}
+
+/* Decrement the weak reference count of REF. If RESULT is not NULL,
+ the result of the operation is written there. */
+static inline void
+refcounts_deref_weak (refcounts_t *ref, struct references *result)
+{
+ const union _references op = { .refs = { .weak = 1 } };
+ refcounts_t r = __atomic_sub_fetch (ref, op.rc, __ATOMIC_RELAXED);
+ if (result)
+ ((union _references *) result)->rc = r;
+}
+
+/* Store the current reference counts of REF in RESULT. */
+static inline void
+refcounts_references (refcounts_t *ref, struct references *result)
+{
+ ((union _references *) result)->rc =
+ __atomic_load_n (ref, __ATOMIC_RELAXED);
+}
+
+/* Return the hard reference count of REF. */
+static inline uint32_t
+refcounts_hard_references (refcounts_t *ref)
+{
+ struct references result;
+ refcounts_references (ref, &result);
+ return result.hard;
+}
+
+/* Return the weak reference count of REF. */
+static inline uint32_t
+refcounts_weak_references (refcounts_t *ref)
+{
+ struct references result;
+ refcounts_references (ref, &result);
+ return result.weak;
+}
+
+#endif /* _HURD_REFCOUNT_H_ */
--
2.0.0.rc0
|