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
|
From 2fdfbfae579a84a00bcca2f4888e716ef0bb7578 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 1/4] include: add lock-less reference counting primitives
* include/refcount.h: New file.
---
include/refcount.h | 132 +++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 132 insertions(+)
create mode 100644 include/refcount.h
diff --git a/include/refcount.h b/include/refcount.h
new file mode 100644
index 0000000..6e20342
--- /dev/null
+++ b/include/refcount.h
@@ -0,0 +1,132 @@
+/* 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. */
+extern inline void
+refcount_init (refcount_t *ref, uint32_t references)
+{
+ *ref = references;
+}
+
+/* Increment REF. Return the result of the operation. */
+extern inline uint32_t
+refcount_ref (refcount_t *ref)
+{
+ return __atomic_add_fetch (ref, 1, __ATOMIC_RELAXED);
+}
+
+/* Decrement REF. Return the result of the operation. */
+extern inline uint32_t
+refcount_deref (refcount_t *ref)
+{
+ return __atomic_sub_fetch (ref, 1, __ATOMIC_RELAXED);
+}
+
+/* Return REF. */
+extern inline uint32_t
+refcount_references (refcount_t *ref)
+{
+ return __atomic_load_n (ref, __ATOMIC_RELAXED);
+}
+
+
+typedef uint64_t refcounts_t;
+
+struct references {
+ uint32_t hard;
+ uint32_t weak;
+};
+
+union _references {
+ struct references refs;
+ refcounts_t rc;
+};
+
+extern inline void
+refcounts_init (refcounts_t *ref, uint32_t hard, uint32_t weak)
+{
+ ((union _references *) ref)->refs =
+ (struct references) { .hard = hard, .weak = weak };
+}
+
+extern 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;
+}
+
+extern 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;
+}
+
+extern 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;
+}
+
+extern 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;
+}
+
+extern inline uint32_t
+refcounts_hard_references (refcounts_t *ref)
+{
+ union _references result;
+ result.rc = __atomic_load_n (ref, __ATOMIC_RELAXED);
+ return result.refs.hard;
+}
+
+extern inline uint32_t
+refcounts_weak_references (refcounts_t *ref)
+{
+ union _references result;
+ result.rc = __atomic_load_n (ref, __ATOMIC_RELAXED);
+ return result.refs.weak;
+}
+
+#endif /* _HURD_REFCOUNT_H_ */
--
2.0.0.rc0
|