1f919b7a6SHans Petter Selasky /*-
262bae5d4SHans Petter Selasky * Copyright (c) 2016-2017 Mellanox Technologies, Ltd.
3f919b7a6SHans Petter Selasky * All rights reserved.
4f919b7a6SHans Petter Selasky *
5f919b7a6SHans Petter Selasky * Redistribution and use in source and binary forms, with or without
6f919b7a6SHans Petter Selasky * modification, are permitted provided that the following conditions
7f919b7a6SHans Petter Selasky * are met:
8f919b7a6SHans Petter Selasky * 1. Redistributions of source code must retain the above copyright
9f919b7a6SHans Petter Selasky * notice unmodified, this list of conditions, and the following
10f919b7a6SHans Petter Selasky * disclaimer.
11f919b7a6SHans Petter Selasky * 2. Redistributions in binary form must reproduce the above copyright
12f919b7a6SHans Petter Selasky * notice, this list of conditions and the following disclaimer in the
13f919b7a6SHans Petter Selasky * documentation and/or other materials provided with the distribution.
14f919b7a6SHans Petter Selasky *
15f919b7a6SHans Petter Selasky * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16f919b7a6SHans Petter Selasky * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17f919b7a6SHans Petter Selasky * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18f919b7a6SHans Petter Selasky * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19f919b7a6SHans Petter Selasky * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20f919b7a6SHans Petter Selasky * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21f919b7a6SHans Petter Selasky * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22f919b7a6SHans Petter Selasky * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23f919b7a6SHans Petter Selasky * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24f919b7a6SHans Petter Selasky * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25f919b7a6SHans Petter Selasky */
26307f78f3SVladimir Kondratyev #ifndef _LINUXKPI_ASM_ATOMIC64_H_
27307f78f3SVladimir Kondratyev #define _LINUXKPI_ASM_ATOMIC64_H_
28f919b7a6SHans Petter Selasky
2962bae5d4SHans Petter Selasky #include <linux/compiler.h>
30f919b7a6SHans Petter Selasky #include <sys/types.h>
31f919b7a6SHans Petter Selasky #include <machine/atomic.h>
32f919b7a6SHans Petter Selasky
33f919b7a6SHans Petter Selasky typedef struct {
34f919b7a6SHans Petter Selasky volatile int64_t counter;
35f919b7a6SHans Petter Selasky } atomic64_t;
36622f2291SHans Petter Selasky #define ATOMIC64_INIT(x) { .counter = (x) }
37622f2291SHans Petter Selasky
38f919b7a6SHans Petter Selasky /*------------------------------------------------------------------------*
39f919b7a6SHans Petter Selasky * 64-bit atomic operations
40f919b7a6SHans Petter Selasky *------------------------------------------------------------------------*/
41f919b7a6SHans Petter Selasky
42f919b7a6SHans Petter Selasky #define atomic64_add(i, v) atomic64_add_return((i), (v))
43f919b7a6SHans Petter Selasky #define atomic64_sub(i, v) atomic64_sub_return((i), (v))
44f919b7a6SHans Petter Selasky #define atomic64_inc_return(v) atomic64_add_return(1, (v))
45f919b7a6SHans Petter Selasky #define atomic64_add_negative(i, v) (atomic64_add_return((i), (v)) < 0)
4684577195SHans Petter Selasky #define atomic64_add_and_test(i, v) (atomic64_add_return((i), (v)) == 0)
47f919b7a6SHans Petter Selasky #define atomic64_sub_and_test(i, v) (atomic64_sub_return((i), (v)) == 0)
48f919b7a6SHans Petter Selasky #define atomic64_dec_and_test(v) (atomic64_sub_return(1, (v)) == 0)
49f919b7a6SHans Petter Selasky #define atomic64_inc_and_test(v) (atomic64_add_return(1, (v)) == 0)
50f919b7a6SHans Petter Selasky #define atomic64_dec_return(v) atomic64_sub_return(1, (v))
51f919b7a6SHans Petter Selasky #define atomic64_inc_not_zero(v) atomic64_add_unless((v), 1, 0)
52f919b7a6SHans Petter Selasky
53f919b7a6SHans Petter Selasky static inline int64_t
atomic64_fetch_add(int64_t i,atomic64_t * v)541889bed2SEmmanuel Vadot atomic64_fetch_add(int64_t i, atomic64_t *v)
551889bed2SEmmanuel Vadot {
561889bed2SEmmanuel Vadot return (atomic_fetchadd_64(&v->counter, i));
571889bed2SEmmanuel Vadot }
581889bed2SEmmanuel Vadot
591889bed2SEmmanuel Vadot static inline int64_t
atomic64_add_return(int64_t i,atomic64_t * v)60f919b7a6SHans Petter Selasky atomic64_add_return(int64_t i, atomic64_t *v)
61f919b7a6SHans Petter Selasky {
62f919b7a6SHans Petter Selasky return i + atomic_fetchadd_64(&v->counter, i);
63f919b7a6SHans Petter Selasky }
64f919b7a6SHans Petter Selasky
65f919b7a6SHans Petter Selasky static inline int64_t
atomic64_sub_return(int64_t i,atomic64_t * v)66f919b7a6SHans Petter Selasky atomic64_sub_return(int64_t i, atomic64_t *v)
67f919b7a6SHans Petter Selasky {
68f919b7a6SHans Petter Selasky return atomic_fetchadd_64(&v->counter, -i) - i;
69f919b7a6SHans Petter Selasky }
70f919b7a6SHans Petter Selasky
71f919b7a6SHans Petter Selasky static inline void
atomic64_set(atomic64_t * v,int64_t i)72f919b7a6SHans Petter Selasky atomic64_set(atomic64_t *v, int64_t i)
73f919b7a6SHans Petter Selasky {
74f919b7a6SHans Petter Selasky atomic_store_rel_64(&v->counter, i);
75f919b7a6SHans Petter Selasky }
76f919b7a6SHans Petter Selasky
77f919b7a6SHans Petter Selasky static inline int64_t
atomic64_read(atomic64_t * v)78f919b7a6SHans Petter Selasky atomic64_read(atomic64_t *v)
79f919b7a6SHans Petter Selasky {
8062bae5d4SHans Petter Selasky return READ_ONCE(v->counter);
81f919b7a6SHans Petter Selasky }
82f919b7a6SHans Petter Selasky
83f919b7a6SHans Petter Selasky static inline int64_t
atomic64_inc(atomic64_t * v)84f919b7a6SHans Petter Selasky atomic64_inc(atomic64_t *v)
85f919b7a6SHans Petter Selasky {
86f919b7a6SHans Petter Selasky return atomic_fetchadd_64(&v->counter, 1) + 1;
87f919b7a6SHans Petter Selasky }
88f919b7a6SHans Petter Selasky
89f919b7a6SHans Petter Selasky static inline int64_t
atomic64_dec(atomic64_t * v)90f919b7a6SHans Petter Selasky atomic64_dec(atomic64_t *v)
91f919b7a6SHans Petter Selasky {
92f919b7a6SHans Petter Selasky return atomic_fetchadd_64(&v->counter, -1) - 1;
93f919b7a6SHans Petter Selasky }
94f919b7a6SHans Petter Selasky
95f919b7a6SHans Petter Selasky static inline int64_t
atomic64_add_unless(atomic64_t * v,int64_t a,int64_t u)96f919b7a6SHans Petter Selasky atomic64_add_unless(atomic64_t *v, int64_t a, int64_t u)
97f919b7a6SHans Petter Selasky {
986402bc3dSHans Petter Selasky int64_t c = atomic64_read(v);
99f919b7a6SHans Petter Selasky
100f919b7a6SHans Petter Selasky for (;;) {
101f919b7a6SHans Petter Selasky if (unlikely(c == u))
102f919b7a6SHans Petter Selasky break;
1036402bc3dSHans Petter Selasky if (likely(atomic_fcmpset_64(&v->counter, &c, c + a)))
104f919b7a6SHans Petter Selasky break;
105f919b7a6SHans Petter Selasky }
106f919b7a6SHans Petter Selasky return (c != u);
107f919b7a6SHans Petter Selasky }
108f919b7a6SHans Petter Selasky
10984577195SHans Petter Selasky static inline int64_t
atomic64_fetch_add_unless(atomic64_t * v,int64_t a,int64_t u)110b9bf16adSHans Petter Selasky atomic64_fetch_add_unless(atomic64_t *v, int64_t a, int64_t u)
111b9bf16adSHans Petter Selasky {
112b9bf16adSHans Petter Selasky int64_t c = atomic64_read(v);
113b9bf16adSHans Petter Selasky
114b9bf16adSHans Petter Selasky for (;;) {
115b9bf16adSHans Petter Selasky if (unlikely(c == u))
116b9bf16adSHans Petter Selasky break;
117b9bf16adSHans Petter Selasky if (likely(atomic_fcmpset_64(&v->counter, &c, c + a)))
118b9bf16adSHans Petter Selasky break;
119b9bf16adSHans Petter Selasky }
120b9bf16adSHans Petter Selasky return (c);
121b9bf16adSHans Petter Selasky }
122b9bf16adSHans Petter Selasky
123b9bf16adSHans Petter Selasky static inline int64_t
atomic64_xchg(atomic64_t * v,int64_t i)12484577195SHans Petter Selasky atomic64_xchg(atomic64_t *v, int64_t i)
12584577195SHans Petter Selasky {
126*9f6097d6SEd Maste #if !(defined(__powerpc__) && !defined(__powerpc64__))
12784577195SHans Petter Selasky return (atomic_swap_64(&v->counter, i));
12884577195SHans Petter Selasky #else
1296402bc3dSHans Petter Selasky int64_t ret = atomic64_read(v);
1306402bc3dSHans Petter Selasky
1316402bc3dSHans Petter Selasky while (!atomic_fcmpset_64(&v->counter, &ret, i))
1326402bc3dSHans Petter Selasky ;
13384577195SHans Petter Selasky return (ret);
13484577195SHans Petter Selasky #endif
13584577195SHans Petter Selasky }
13684577195SHans Petter Selasky
13784577195SHans Petter Selasky static inline int64_t
atomic64_cmpxchg(atomic64_t * v,int64_t old,int64_t new)13884577195SHans Petter Selasky atomic64_cmpxchg(atomic64_t *v, int64_t old, int64_t new)
13984577195SHans Petter Selasky {
14084577195SHans Petter Selasky int64_t ret = old;
14184577195SHans Petter Selasky
14284577195SHans Petter Selasky for (;;) {
1436402bc3dSHans Petter Selasky if (atomic_fcmpset_64(&v->counter, &ret, new))
14484577195SHans Petter Selasky break;
14584577195SHans Petter Selasky if (ret != old)
14684577195SHans Petter Selasky break;
14784577195SHans Petter Selasky }
14884577195SHans Petter Selasky return (ret);
14984577195SHans Petter Selasky }
15084577195SHans Petter Selasky
151307f78f3SVladimir Kondratyev #endif /* _LINUXKPI_ASM_ATOMIC64_H_ */
152