bug-hurd
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH 5/7] include: add lock-less reference counting primitives


From: Justus Winter
Subject: [PATCH 5/7] include: add lock-less reference counting primitives
Date: Tue, 13 May 2014 21:02:54 +0200

* 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




reply via email to

[Prev in Thread] Current Thread [Next in Thread]