1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
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 */
|