diff options
Diffstat (limited to 'libglusterfs/src/atomic.h')
| -rw-r--r-- | libglusterfs/src/atomic.h | 109 | 
1 files changed, 109 insertions, 0 deletions
diff --git a/libglusterfs/src/atomic.h b/libglusterfs/src/atomic.h new file mode 100644 index 00000000000..71fcb1ee972 --- /dev/null +++ b/libglusterfs/src/atomic.h @@ -0,0 +1,109 @@ +/* +  Copyright (c) 2017 Red Hat, Inc. <http://www.redhat.com> +  This file is part of GlusterFS. + +  This file is licensed to you under your choice of the GNU Lesser +  General Public License, version 3 or any later version (LGPLv3 or +  later), or the GNU General Public License, version 2 (GPLv2), in all +  cases as published by the Free Software Foundation. +*/ + +#ifndef _ATOMIC_H +#define _ATOMIC_H + +#include <inttypes.h> + +#if defined(HAVE_ATOMIC_BUILTINS) || defined(HAVE_SYNC_BUILTINS) +/* optimized implementation, macros only */ + +typedef struct gf_atomic_t { +        int64_t    cnt; +} gf_atomic_t; + +#if defined(HAVE_ATOMIC_BUILTINS) + +/* all macros have a 'gf_atomic_t' as 1st argument */ +#define GF_ATOMIC_INIT(op, n)     __atomic_store (&(op.cnt), __ATOMIC_RELEASE) +#define GF_ATOMIC_GET(op)         __atomic_load (&(op.cnt), __ATOMIC_ACQUIRE) +#define GF_ATOMIC_INC(op)         __atomic_add_and_fetch (&(op.cnt), 1, \ +                                                          __ATOMIC_ACQ_REL) +#define GF_ATOMIC_DEC(op)         __atomic_sub_and_fetch (&(op.cnt), 1, \ +                                                          __ATOMIC_ACQ_REL) +#define GF_ATOMIC_ADD(op, n)      __atomic_add_and_fetch (&(op.cnt), n, \ +                                                          __ATOMIC_ACQ_REL) +#define GF_ATOMIC_SUB(op, n)      __atomic_sub_and_fetch (&(op.cnt), n, \ +                                                          __ATOMIC_ACQ_REL) + +#else /* !HAVE_ATOMIC_BUILTINS, but HAVE_SYNC_BUILTINS */ + +/* all macros have a 'gf_atomic_t' as 1st argument */ +#define GF_ATOMIC_INIT(op, n)     ({ op.cnt = n; __sync_synchronize (); }) +#define GF_ATOMIC_GET(op)         __sync_add_and_fetch (&(op.cnt), 0) +#define GF_ATOMIC_INC(op)         __sync_add_and_fetch (&(op.cnt), 1) +#define GF_ATOMIC_DEC(op)         __sync_sub_and_fetch (&(op.cnt), 1) +#define GF_ATOMIC_ADD(op, n)      __sync_add_and_fetch (&(op.cnt), n) +#define GF_ATOMIC_SUB(op, n)      __sync_sub_and_fetch (&(op.cnt), n) + +#endif /* HAVE_ATOMIC_BUILTINS || HAVE_SYNC_BUILTINS */ + +#else /* no HAVE_(ATOMIC|SYNC)_BUILTINS */ +/* fallback implementation, using small inline functions to improve type + * checking while compiling */ + +#include "locking.h" + +typedef struct gf_atomic_t { +        int64_t    cnt; +        gf_lock_t  lk; +} gf_atomic_t; + + +static inline void +gf_atomic_init (gf_atomic_t *op, int64_t cnt) +{ +        LOCK_INIT (&op->lk); +        op->cnt = cnt; +} + + +static inline uint64_t +gf_atomic_get (gf_atomic_t *op) +{ +        uint64_t ret; + +        LOCK (&op->lk); +        { +               ret = op->cnt; +        } +        UNLOCK (&op->lk); + +        return ret; +} + + +static inline int64_t +gf_atomic_add (gf_atomic_t *op, int64_t n) +{ +        uint64_t ret; + +        LOCK (&op->lk); +        { +                op->cnt += n; +                ret = op->cnt; +        } +        UNLOCK (&op->lk); + +        return ret; +} + + +#define GF_ATOMIC_INIT(op, cnt)   gf_atomic_init (&op, cnt) +#define GF_ATOMIC_GET(op)         gf_atomic_get (&op) +#define GF_ATOMIC_INC(op)         gf_atomic_add (&op, 1) +#define GF_ATOMIC_DEC(op)         gf_atomic_add (&op, -1) +#define GF_ATOMIC_ADD(op, n)      gf_atomic_add (&op, n) +#define GF_ATOMIC_SUB(op, n)      gf_atomic_add (&op, -n) + +#endif /* HAVE_ATOMIC_SYNC_OPS */ + +#endif /* _ATOMIC_H */  | 
