1#ifndef __ASM_METAG_ATOMIC_LOCK1_H
2#define __ASM_METAG_ATOMIC_LOCK1_H
3
4#define ATOMIC_INIT(i) { (i) }
5
6#include <linux/compiler.h>
7
8#include <asm/barrier.h>
9#include <asm/global_lock.h>
10
11static inline int atomic_read(const atomic_t *v)
12{
13 return READ_ONCE((v)->counter);
14}
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29static inline int atomic_set(atomic_t *v, int i)
30{
31 unsigned long flags;
32
33 __global_lock1(flags);
34 fence();
35 v->counter = i;
36 __global_unlock1(flags);
37 return i;
38}
39
40#define ATOMIC_OP(op, c_op) \
41static inline void atomic_##op(int i, atomic_t *v) \
42{ \
43 unsigned long flags; \
44 \
45 __global_lock1(flags); \
46 fence(); \
47 v->counter c_op i; \
48 __global_unlock1(flags); \
49} \
50
51#define ATOMIC_OP_RETURN(op, c_op) \
52static inline int atomic_##op##_return(int i, atomic_t *v) \
53{ \
54 unsigned long result; \
55 unsigned long flags; \
56 \
57 __global_lock1(flags); \
58 result = v->counter; \
59 result c_op i; \
60 fence(); \
61 v->counter = result; \
62 __global_unlock1(flags); \
63 \
64 return result; \
65}
66
67#define ATOMIC_FETCH_OP(op, c_op) \
68static inline int atomic_fetch_##op(int i, atomic_t *v) \
69{ \
70 unsigned long result; \
71 unsigned long flags; \
72 \
73 __global_lock1(flags); \
74 result = v->counter; \
75 fence(); \
76 v->counter c_op i; \
77 __global_unlock1(flags); \
78 \
79 return result; \
80}
81
82#define ATOMIC_OPS(op, c_op) \
83 ATOMIC_OP(op, c_op) \
84 ATOMIC_OP_RETURN(op, c_op) \
85 ATOMIC_FETCH_OP(op, c_op)
86
87ATOMIC_OPS(add, +=)
88ATOMIC_OPS(sub, -=)
89
90#undef ATOMIC_OPS
91#define ATOMIC_OPS(op, c_op) \
92 ATOMIC_OP(op, c_op) \
93 ATOMIC_FETCH_OP(op, c_op)
94
95ATOMIC_OPS(and, &=)
96ATOMIC_OPS(or, |=)
97ATOMIC_OPS(xor, ^=)
98
99#undef ATOMIC_OPS
100#undef ATOMIC_FETCH_OP
101#undef ATOMIC_OP_RETURN
102#undef ATOMIC_OP
103
104static inline int atomic_cmpxchg(atomic_t *v, int old, int new)
105{
106 int ret;
107 unsigned long flags;
108
109 __global_lock1(flags);
110 ret = v->counter;
111 if (ret == old) {
112 fence();
113 v->counter = new;
114 }
115 __global_unlock1(flags);
116
117 return ret;
118}
119
120#define atomic_xchg(v, new) (xchg(&((v)->counter), new))
121
122static inline int __atomic_add_unless(atomic_t *v, int a, int u)
123{
124 int ret;
125 unsigned long flags;
126
127 __global_lock1(flags);
128 ret = v->counter;
129 if (ret != u) {
130 fence();
131 v->counter += a;
132 }
133 __global_unlock1(flags);
134
135 return ret;
136}
137
138static inline int atomic_sub_if_positive(int i, atomic_t *v)
139{
140 int ret;
141 unsigned long flags;
142
143 __global_lock1(flags);
144 ret = v->counter - 1;
145 if (ret >= 0) {
146 fence();
147 v->counter = ret;
148 }
149 __global_unlock1(flags);
150
151 return ret;
152}
153
154#endif
155