summaryrefslogtreecommitdiff
path: root/debian/patches/0001-include-add-lock-less-reference-counting-primitives.patch
blob: 4a194b54dfdb63829b8ba66cafb93d3f3777a626 (plain)
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
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
From 6d56f1b470b40176e0386012648333ba9b2aa95b 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 01/13] include: add lock-less reference counting primitives

* include/refcount.h: New file.
---
 include/refcount.h | 193 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 193 insertions(+)
 create mode 100644 include/refcount.h

diff --git a/include/refcount.h b/include/refcount.h
new file mode 100644
index 0000000..0816220
--- /dev/null
+++ b/include/refcount.h
@@ -0,0 +1,193 @@
+/* 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 <assert.h>
+#include <stdint.h>
+
+/* Simple reference counting.  */
+
+/* An opaque type.  You must not access these values directly.  */
+typedef unsigned int refcount_t;
+
+/* Initialize REF with REFERENCES.  */
+static inline void
+refcount_init (refcount_t *ref, unsigned int references)
+{
+  *ref = references;
+}
+
+/* Increment REF.  Return the result of the operation.  This function
+   uses atomic operations.  It is not required to serialize calls to
+   this function.  */
+static inline unsigned int
+refcount_ref (refcount_t *ref)
+{
+  unsigned int r;
+  r = __atomic_add_fetch (ref, 1, __ATOMIC_RELAXED);
+  assert (r != UINT_MAX);
+  return r;
+}
+
+/* Decrement REF.  Return the result of the operation.  This function
+   uses atomic operations.  It is not required to serialize calls to
+   this function.  */
+static inline unsigned int
+refcount_deref (refcount_t *ref)
+{
+  unsigned int r;
+  r = __atomic_sub_fetch (ref, 1, __ATOMIC_RELAXED);
+  assert (r != UINT_MAX);
+  return r;
+}
+
+/* Return REF.  This function uses atomic operations.  It is not
+   required to serialize calls to this function.  */
+static inline unsigned int
+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 union _references 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;
+};
+
+/* We use a union to convert struct reference values to uint64_t which
+   we can manipulate atomically.  While this behavior is not
+   guaranteed by the C standard, it is supported by all major
+   compilers.  */
+union _references {
+  struct references references;
+  uint64_t value;
+};
+
+/* Initialize REF with HARD and WEAK references.  */
+static inline void
+refcounts_init (refcounts_t *ref, uint32_t hard, uint32_t weak)
+{
+  ref->references = (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.  This function uses
+   atomic operations.  It is not required to serialize calls to this
+   function.  */
+static inline void
+refcounts_ref (refcounts_t *ref, struct references *result)
+{
+  const union _references op = { .references = { .hard = 1 } };
+  union _references r;
+  r.value = __atomic_add_fetch (&ref->value, op.value, __ATOMIC_RELAXED);
+  assert (r.references.hard != UINT32_MAX);
+  if (result)
+    *result = r.references;
+}
+
+/* Decrement the hard reference count of REF.  If RESULT is not NULL,
+   the result of the operation is written there.  This function uses
+   atomic operations.  It is not required to serialize calls to this
+   function.  */
+static inline void
+refcounts_deref (refcounts_t *ref, struct references *result)
+{
+  const union _references op = { .references = { .hard = 1 } };
+  union _references r;
+  r.value = __atomic_sub_fetch (&ref->value, op.value, __ATOMIC_RELAXED);
+  assert (r.references.hard != UINT32_MAX);
+  if (result)
+    *result = r.references;
+}
+
+/* Increment the weak reference count of REF.  If RESULT is not NULL,
+   the result of the operation is written there.  This function uses
+   atomic operations.  It is not required to serialize calls to this
+   function.  */
+static inline void
+refcounts_ref_weak (refcounts_t *ref, struct references *result)
+{
+  const union _references op = { .references = { .weak = 1 } };
+  union _references r;
+  r.value = __atomic_add_fetch (&ref->value, op.value, __ATOMIC_RELAXED);
+  assert (r.references.weak != UINT32_MAX);
+  if (result)
+    *result = r.references;
+}
+
+/* Decrement the weak reference count of REF.  If RESULT is not NULL,
+   the result of the operation is written there.  This function uses
+   atomic operations.  It is not required to serialize calls to this
+   function.  */
+static inline void
+refcounts_deref_weak (refcounts_t *ref, struct references *result)
+{
+  const union _references op = { .references = { .weak = 1 } };
+  union _references r;
+  r.value = __atomic_sub_fetch (&ref->value, op.value, __ATOMIC_RELAXED);
+  assert (r.references.weak != UINT32_MAX);
+  if (result)
+    *result = r.references;
+}
+
+/* Store the current reference counts of REF in RESULT.  This function
+   uses atomic operations.  It is not required to serialize calls to
+   this function.  */
+static inline void
+refcounts_references (refcounts_t *ref, struct references *result)
+{
+  union _references r;
+  r.value =__atomic_load_n (&ref->value, __ATOMIC_RELAXED);
+  *result = r.references;
+}
+
+/* Return the hard reference count of REF.  This function uses atomic
+   operations.  It is not required to serialize calls to this
+   function.  */
+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.  This function uses atomic
+   operations.  It is not required to serialize calls to this
+   function.  */
+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