diff options
Diffstat (limited to 'debian/patches/0001-libshouldbeinlibc-move-the-reference-counting-primit.patch')
-rw-r--r-- | debian/patches/0001-libshouldbeinlibc-move-the-reference-counting-primit.patch | 733 |
1 files changed, 733 insertions, 0 deletions
diff --git a/debian/patches/0001-libshouldbeinlibc-move-the-reference-counting-primit.patch b/debian/patches/0001-libshouldbeinlibc-move-the-reference-counting-primit.patch new file mode 100644 index 00000000..da210e9b --- /dev/null +++ b/debian/patches/0001-libshouldbeinlibc-move-the-reference-counting-primit.patch @@ -0,0 +1,733 @@ +From 0d3b80f04a1caee51b9995c9626838f85295bb06 Mon Sep 17 00:00:00 2001 +From: Justus Winter <4winter@informatik.uni-hamburg.de> +Date: Sun, 23 Nov 2014 19:09:51 +0100 +Subject: [PATCH hurd 01/28] 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}'. +--- + include/refcount.h | 320 ------------------------------------------ + libshouldbeinlibc/Makefile | 8 +- + libshouldbeinlibc/refcount.c | 23 +++ + libshouldbeinlibc/refcount.h | 326 +++++++++++++++++++++++++++++++++++++++++++ + 4 files changed, 355 insertions(+), 322 deletions(-) + delete mode 100644 include/refcount.h + create mode 100644 libshouldbeinlibc/refcount.c + create mode 100644 libshouldbeinlibc/refcount.h + +diff --git a/include/refcount.h b/include/refcount.h +deleted file mode 100644 +index ebde42d..0000000 +--- 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_ */ +diff --git a/libshouldbeinlibc/Makefile b/libshouldbeinlibc/Makefile +index 14a7939..633d60e 100644 +--- a/libshouldbeinlibc/Makefile ++++ b/libshouldbeinlibc/Makefile +@@ -27,9 +27,13 @@ SRCS = termsize.c timefmt.c exec-reauth.c maptime-funcs.c \ + idvec-impgids.c idvec-verify.c idvec-rep.c \ + ugids.c ugids-argp.c ugids-rep.c ugids-verify.c ugids-subtract.c \ + ugids-auth.c ugids-xinl.c ugids-merge.c ugids-imply.c ugids-posix.c \ +- ugids-verify-auth.c nullauth.c ++ ugids-verify-auth.c nullauth.c \ ++ refcount.c \ ++ + installhdrs = idvec.h timefmt.h maptime.h \ +- wire.h portinfo.h portxlate.h cacheq.h ugids.h nullauth.h ++ wire.h portinfo.h portxlate.h cacheq.h ugids.h nullauth.h \ ++ refcount.h \ ++ + installhdrsubdir = . + + OBJS = $(SRCS:.c=.o) +diff --git a/libshouldbeinlibc/refcount.c b/libshouldbeinlibc/refcount.c +new file mode 100644 +index 0000000..17e01c5 +--- /dev/null ++++ b/libshouldbeinlibc/refcount.c +@@ -0,0 +1,23 @@ ++/* 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/>. */ ++ ++#define REFCOUNT_DEFINE_EI ++#include "refcount.h" +diff --git a/libshouldbeinlibc/refcount.h b/libshouldbeinlibc/refcount.h +new file mode 100644 +index 0000000..e8b0f5b +--- /dev/null ++++ b/libshouldbeinlibc/refcount.h +@@ -0,0 +1,326 @@ ++/* 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_ ++ ++#ifdef REFCOUNT_DEFINE_EI ++#define REFCOUNT_EI ++#else ++#define REFCOUNT_EI __extern_inline ++#endif ++ ++#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. */ ++REFCOUNT_EI 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. */ ++REFCOUNT_EI 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. */ ++REFCOUNT_EI 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. */ ++REFCOUNT_EI 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. */ ++REFCOUNT_EI 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. */ ++REFCOUNT_EI 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. */ ++REFCOUNT_EI 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. */ ++REFCOUNT_EI 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. */ ++REFCOUNT_EI 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. */ ++REFCOUNT_EI 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. */ ++REFCOUNT_EI 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. */ ++REFCOUNT_EI 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. */ ++REFCOUNT_EI 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. */ ++REFCOUNT_EI 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. */ ++REFCOUNT_EI 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. */ ++REFCOUNT_EI 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. */ ++REFCOUNT_EI uint32_t ++refcounts_weak_references (refcounts_t *ref) ++{ ++ struct references result; ++ refcounts_references (ref, &result); ++ return result.weak; ++} ++ ++#endif /* _HURD_REFCOUNT_H_ */ +-- +2.1.3 + |