bug-hurd
[Top][All Lists]
Advanced

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

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


From: Samuel Thibault
Subject: Re: [PATCH 5/7] include: add lock-less reference counting primitives
Date: Tue, 13 May 2014 23:14:37 +0200
User-agent: Mutt/1.5.21+34 (58baf7c9f32f) (2010-12-30)

Justus Winter, le Tue 13 May 2014 21:02:54 +0200, a écrit :
> * include/refcount.h: New file.

Ack.

> ---
>  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
> 

-- 
Samuel
* x remarque qu'avec un peu de volonté, on peut faire du code de porc
dans d'importe quel langage Turing-complet
 -+- x sur #ens-mim - codons porc -+-



reply via email to

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