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 . */
+
+#ifndef _HURD_REFCOUNT_H_
+#define _HURD_REFCOUNT_H_
+
+#include
+
+/* 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