]> git.ipfire.org Git - thirdparty/linux.git/blame - arch/powerpc/include/asm/local.h
License cleanup: add SPDX GPL-2.0 license identifier to files with no license
[thirdparty/linux.git] / arch / powerpc / include / asm / local.h
CommitLineData
b2441318 1/* SPDX-License-Identifier: GPL-2.0 */
6d8944a0
MD
2#ifndef _ARCH_POWERPC_LOCAL_H
3#define _ARCH_POWERPC_LOCAL_H
4
5#include <linux/percpu.h>
60063497 6#include <linux/atomic.h>
6d8944a0
MD
7
8typedef struct
9{
10 atomic_long_t a;
11} local_t;
12
13#define LOCAL_INIT(i) { ATOMIC_LONG_INIT(i) }
14
15#define local_read(l) atomic_long_read(&(l)->a)
16#define local_set(l,i) atomic_long_set(&(l)->a, (i))
17
18#define local_add(i,l) atomic_long_add((i),(&(l)->a))
19#define local_sub(i,l) atomic_long_sub((i),(&(l)->a))
20#define local_inc(l) atomic_long_inc(&(l)->a)
21#define local_dec(l) atomic_long_dec(&(l)->a)
22
23static __inline__ long local_add_return(long a, local_t *l)
24{
25 long t;
26
27 __asm__ __volatile__(
864b9e6f 28"1:" PPC_LLARX(%0,0,%2,0) " # local_add_return\n\
6d8944a0
MD
29 add %0,%1,%0\n"
30 PPC405_ERR77(0,%2)
31 PPC_STLCX "%0,0,%2 \n\
32 bne- 1b"
33 : "=&r" (t)
34 : "r" (a), "r" (&(l->a.counter))
35 : "cc", "memory");
36
37 return t;
38}
39
40#define local_add_negative(a, l) (local_add_return((a), (l)) < 0)
41
42static __inline__ long local_sub_return(long a, local_t *l)
43{
44 long t;
45
46 __asm__ __volatile__(
864b9e6f 47"1:" PPC_LLARX(%0,0,%2,0) " # local_sub_return\n\
6d8944a0
MD
48 subf %0,%1,%0\n"
49 PPC405_ERR77(0,%2)
50 PPC_STLCX "%0,0,%2 \n\
51 bne- 1b"
52 : "=&r" (t)
53 : "r" (a), "r" (&(l->a.counter))
54 : "cc", "memory");
55
56 return t;
57}
58
59static __inline__ long local_inc_return(local_t *l)
60{
61 long t;
62
63 __asm__ __volatile__(
864b9e6f 64"1:" PPC_LLARX(%0,0,%1,0) " # local_inc_return\n\
6d8944a0
MD
65 addic %0,%0,1\n"
66 PPC405_ERR77(0,%1)
67 PPC_STLCX "%0,0,%1 \n\
68 bne- 1b"
69 : "=&r" (t)
70 : "r" (&(l->a.counter))
efc3624c 71 : "cc", "xer", "memory");
6d8944a0
MD
72
73 return t;
74}
75
76/*
77 * local_inc_and_test - increment and test
78 * @l: pointer of type local_t
79 *
80 * Atomically increments @l by 1
81 * and returns true if the result is zero, or false for all
82 * other cases.
83 */
84#define local_inc_and_test(l) (local_inc_return(l) == 0)
85
86static __inline__ long local_dec_return(local_t *l)
87{
88 long t;
89
90 __asm__ __volatile__(
864b9e6f 91"1:" PPC_LLARX(%0,0,%1,0) " # local_dec_return\n\
6d8944a0
MD
92 addic %0,%0,-1\n"
93 PPC405_ERR77(0,%1)
94 PPC_STLCX "%0,0,%1\n\
95 bne- 1b"
96 : "=&r" (t)
97 : "r" (&(l->a.counter))
efc3624c 98 : "cc", "xer", "memory");
6d8944a0
MD
99
100 return t;
101}
102
103#define local_cmpxchg(l, o, n) \
104 (cmpxchg_local(&((l)->a.counter), (o), (n)))
105#define local_xchg(l, n) (xchg_local(&((l)->a.counter), (n)))
106
107/**
108 * local_add_unless - add unless the number is a given value
109 * @l: pointer of type local_t
110 * @a: the amount to add to v...
111 * @u: ...unless v is equal to u.
112 *
113 * Atomically adds @a to @l, so long as it was not @u.
114 * Returns non-zero if @l was not @u, and zero otherwise.
115 */
116static __inline__ int local_add_unless(local_t *l, long a, long u)
117{
118 long t;
119
120 __asm__ __volatile__ (
864b9e6f 121"1:" PPC_LLARX(%0,0,%1,0) " # local_add_unless\n\
6d8944a0
MD
122 cmpw 0,%0,%3 \n\
123 beq- 2f \n\
124 add %0,%2,%0 \n"
125 PPC405_ERR77(0,%2)
126 PPC_STLCX "%0,0,%1 \n\
127 bne- 1b \n"
128" subf %0,%2,%0 \n\
1292:"
130 : "=&r" (t)
131 : "r" (&(l->a.counter)), "r" (a), "r" (u)
132 : "cc", "memory");
133
134 return t != u;
135}
136
137#define local_inc_not_zero(l) local_add_unless((l), 1, 0)
138
139#define local_sub_and_test(a, l) (local_sub_return((a), (l)) == 0)
140#define local_dec_and_test(l) (local_dec_return((l)) == 0)
141
142/*
143 * Atomically test *l and decrement if it is greater than 0.
144 * The function returns the old value of *l minus 1.
145 */
146static __inline__ long local_dec_if_positive(local_t *l)
147{
148 long t;
149
150 __asm__ __volatile__(
864b9e6f 151"1:" PPC_LLARX(%0,0,%1,0) " # local_dec_if_positive\n\
6d8944a0
MD
152 cmpwi %0,1\n\
153 addi %0,%0,-1\n\
154 blt- 2f\n"
155 PPC405_ERR77(0,%1)
156 PPC_STLCX "%0,0,%1\n\
157 bne- 1b"
158 "\n\
1592:" : "=&b" (t)
160 : "r" (&(l->a.counter))
161 : "cc", "memory");
162
163 return t;
164}
165
166/* Use these for per-cpu local_t variables: on some archs they are
167 * much more efficient than these naive implementations. Note they take
168 * a variable, not an address.
169 */
170
171#define __local_inc(l) ((l)->a.counter++)
172#define __local_dec(l) ((l)->a.counter++)
173#define __local_add(i,l) ((l)->a.counter+=(i))
174#define __local_sub(i,l) ((l)->a.counter-=(i))
175
6d8944a0 176#endif /* _ARCH_POWERPC_LOCAL_H */