summaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorJustus Winter <4winter@informatik.uni-hamburg.de>2014-11-23 19:09:51 +0100
committerJustus Winter <4winter@informatik.uni-hamburg.de>2014-12-01 11:28:15 +0100
commit0d3b80f04a1caee51b9995c9626838f85295bb06 (patch)
tree232a7cf64cd052d1f86ff0bfcc0292a17a7050ae /include
parent40d433fd1ca3aedac58a281f982725bfa9f77997 (diff)
libshouldbeinlibc: move the reference counting primitives here
Declare all functions `extern inline' instead of `static inline'. This allows us to use them in functions declared as `extern inline'. * libshouldbeinlibc/refcount.h: Move here, and declare all functions `extern inline'. * libshouldbeinlibc/refcount.c: And define the functions here. * libshouldbeinlibc/Makefile: Add `refcount.{c,h}'.
Diffstat (limited to 'include')
-rw-r--r--include/refcount.h320
1 files changed, 0 insertions, 320 deletions
diff --git a/include/refcount.h b/include/refcount.h
deleted file mode 100644
index ebde42da..00000000
--- a/include/refcount.h
+++ /dev/null
@@ -1,320 +0,0 @@
-/* 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 <limits.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. REFERENCES must not be zero. */
-static inline void
-refcount_init (refcount_t *ref, unsigned int references)
-{
- assert (references > 0 || !"references must not be zero!");
- *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.
-
- This is the unsafe version of refcount_ref. refcount_ref also
- checks for use-after-free errors. When in doubt, use that one
- instead. */
-static inline unsigned int
-refcount_unsafe_ref (refcount_t *ref)
-{
- unsigned int r;
- r = __atomic_add_fetch (ref, 1, __ATOMIC_RELAXED);
- assert (r != UINT_MAX || !"refcount overflowed!");
- return r;
-}
-
-/* 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 = refcount_unsafe_ref (ref);
- assert (r != 1 || !"refcount detected use-after-free!");
- 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 || !"refcount underflowed!");
- 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 {
- /* We chose the layout of this struct so that when it is used in the
- union _references, the hard reference counts occupy the least
- significant bits. We rely on this layout for atomic promotion
- and demotion of references. See refcounts_promote and
- refcounts_demote for details. */
-#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
- uint32_t hard;
- uint32_t weak;
-#else
- uint32_t weak;
- uint32_t hard;
-#endif
-};
-
-/* 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. HARD and WEAK must
- not both be zero. */
-static inline void
-refcounts_init (refcounts_t *ref, uint32_t hard, uint32_t weak)
-{
- assert ((hard != 0 || weak != 0) || !"references must not both be zero!");
- 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.
-
- This is the unsafe version of refcounts_ref. refcounts_ref also
- checks for use-after-free errors. When in doubt, use that one
- instead. */
-static inline void
-refcounts_unsafe_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 || !"refcount overflowed!");
- if (result)
- *result = r.references;
-}
-
-/* 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)
-{
- struct references r;
- refcounts_unsafe_ref (ref, &r);
- assert (! (r.hard == 1 && r.weak == 0)
- || !"refcount detected use-after-free!");
- if (result)
- *result = r;
-}
-
-/* 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 || !"refcount underflowed!");
- if (result)
- *result = r.references;
-}
-
-/* Promote a weak reference to a hard reference. 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_promote (refcounts_t *ref, struct references *result)
-{
- /* To promote a weak reference, we need to atomically subtract 1
- from the weak reference count, and add 1 to the hard reference
- count.
-
- We can subtract by 1 by adding the two's complement of 1 = ~0 to
- a fixed-width value, discarding the overflow.
-
- We do the same in our uint64_t value, but we have chosen the
- layout of struct references so that when it is used in the union
- _references, the weak reference counts occupy the most
- significant bits. When we add ~0 to the weak references, the
- overflow will be discarded as unsigned arithmetic is modulo 2^n.
- So we just add a hard reference. In combination, this is the
- desired operation. */
- const union _references op =
- { .references = { .weak = ~0U, .hard = 1} };
- union _references r;
- r.value = __atomic_add_fetch (&ref->value, op.value, __ATOMIC_RELAXED);
- assert (r.references.hard != UINT32_MAX || !"refcount overflowed!");
- assert (r.references.weak != UINT32_MAX || !"refcount underflowed!");
- if (result)
- *result = r.references;
-}
-
-/* Demote a hard reference to a weak reference. 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_demote (refcounts_t *ref, struct references *result)
-{
- /* To demote a hard reference, we need to atomically subtract 1 from
- the hard reference count, and add 1 to the weak reference count.
-
- We can subtract by 1 by adding the two's complement of 1 = ~0 to
- a fixed-width value, discarding the overflow.
-
- We do the same in our uint64_t value, but we have chosen the
- layout of struct references so that when it is used in the union
- _references, the hard reference counts occupy the least
- significant bits. When we add ~0 to the hard references, it will
- overflow into the weak references. This is the desired
- operation. */
- const union _references op = { .references = { .hard = ~0U } };
- union _references r;
- r.value = __atomic_add_fetch (&ref->value, op.value, __ATOMIC_RELAXED);
- assert (r.references.hard != UINT32_MAX || !"refcount underflowed!");
- assert (r.references.weak != UINT32_MAX || !"refcount overflowed!");
- 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.
-
- This is the unsafe version of refcounts_ref_weak.
- refcounts_ref_weak also checks for use-after-free errors. When in
- doubt, use that one instead. */
-static inline void
-refcounts_unsafe_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 || !"refcount overflowed!");
- 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)
-{
- struct references r;
- refcounts_unsafe_ref_weak (ref, &r);
- assert (! (r.hard == 0 && r.weak == 1)
- || !"refcount detected use-after-free!");
- if (result)
- *result = r;
-}
-
-/* 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 || !"refcount underflowed!");
- 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_ */