~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/powerpc/include/asm/cmpxchg.h

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /* SPDX-License-Identifier: GPL-2.0 */
  2 #ifndef _ASM_POWERPC_CMPXCHG_H_
  3 #define _ASM_POWERPC_CMPXCHG_H_
  4 
  5 #ifdef __KERNEL__
  6 #include <linux/compiler.h>
  7 #include <asm/synch.h>
  8 #include <linux/bug.h>
  9 
 10 #ifdef __BIG_ENDIAN
 11 #define BITOFF_CAL(size, off)   ((sizeof(u32) - size - off) * BITS_PER_BYTE)
 12 #else
 13 #define BITOFF_CAL(size, off)   (off * BITS_PER_BYTE)
 14 #endif
 15 
 16 #define XCHG_GEN(type, sfx, cl)                         \
 17 static inline u32 __xchg_##type##sfx(volatile void *p, u32 val) \
 18 {                                                               \
 19         unsigned int prev, prev_mask, tmp, bitoff, off;         \
 20                                                                 \
 21         off = (unsigned long)p % sizeof(u32);                   \
 22         bitoff = BITOFF_CAL(sizeof(type), off);                 \
 23         p -= off;                                               \
 24         val <<= bitoff;                                         \
 25         prev_mask = (u32)(type)-1 << bitoff;                    \
 26                                                                 \
 27         __asm__ __volatile__(                                   \
 28 "1:     lwarx   %0,0,%3\n"                                      \
 29 "       andc    %1,%0,%5\n"                                     \
 30 "       or      %1,%1,%4\n"                                     \
 31 "       stwcx.  %1,0,%3\n"                                      \
 32 "       bne-    1b\n"                                           \
 33         : "=&r" (prev), "=&r" (tmp), "+m" (*(u32*)p)            \
 34         : "r" (p), "r" (val), "r" (prev_mask)                   \
 35         : "cc", cl);                                            \
 36                                                                 \
 37         return prev >> bitoff;                                  \
 38 }
 39 
 40 #define CMPXCHG_GEN(type, sfx, br, br2, cl)                     \
 41 static inline                                                   \
 42 u32 __cmpxchg_##type##sfx(volatile void *p, u32 old, u32 new)   \
 43 {                                                               \
 44         unsigned int prev, prev_mask, tmp, bitoff, off;         \
 45                                                                 \
 46         off = (unsigned long)p % sizeof(u32);                   \
 47         bitoff = BITOFF_CAL(sizeof(type), off);                 \
 48         p -= off;                                               \
 49         old <<= bitoff;                                         \
 50         new <<= bitoff;                                         \
 51         prev_mask = (u32)(type)-1 << bitoff;                    \
 52                                                                 \
 53         __asm__ __volatile__(                                   \
 54         br                                                      \
 55 "1:     lwarx   %0,0,%3\n"                                      \
 56 "       and     %1,%0,%6\n"                                     \
 57 "       cmpw    0,%1,%4\n"                                      \
 58 "       bne-    2f\n"                                           \
 59 "       andc    %1,%0,%6\n"                                     \
 60 "       or      %1,%1,%5\n"                                     \
 61 "       stwcx.  %1,0,%3\n"                                      \
 62 "       bne-    1b\n"                                           \
 63         br2                                                     \
 64         "\n"                                                    \
 65 "2:"                                                            \
 66         : "=&r" (prev), "=&r" (tmp), "+m" (*(u32*)p)            \
 67         : "r" (p), "r" (old), "r" (new), "r" (prev_mask)        \
 68         : "cc", cl);                                            \
 69                                                                 \
 70         return prev >> bitoff;                                  \
 71 }
 72 
 73 /*
 74  * Atomic exchange
 75  *
 76  * Changes the memory location '*p' to be val and returns
 77  * the previous value stored there.
 78  */
 79 
 80 #ifndef CONFIG_PPC_HAS_LBARX_LHARX
 81 XCHG_GEN(u8, _local, "memory");
 82 XCHG_GEN(u8, _relaxed, "cc");
 83 XCHG_GEN(u16, _local, "memory");
 84 XCHG_GEN(u16, _relaxed, "cc");
 85 #else
 86 static __always_inline unsigned long
 87 __xchg_u8_local(volatile void *p, unsigned long val)
 88 {
 89         unsigned long prev;
 90 
 91         __asm__ __volatile__(
 92 "1:     lbarx   %0,0,%2         # __xchg_u8_local\n"
 93 "       stbcx.  %3,0,%2 \n"
 94 "       bne-    1b"
 95         : "=&r" (prev), "+m" (*(volatile unsigned char *)p)
 96         : "r" (p), "r" (val)
 97         : "cc", "memory");
 98 
 99         return prev;
100 }
101 
102 static __always_inline unsigned long
103 __xchg_u8_relaxed(u8 *p, unsigned long val)
104 {
105         unsigned long prev;
106 
107         __asm__ __volatile__(
108 "1:     lbarx   %0,0,%2         # __xchg_u8_relaxed\n"
109 "       stbcx.  %3,0,%2\n"
110 "       bne-    1b"
111         : "=&r" (prev), "+m" (*p)
112         : "r" (p), "r" (val)
113         : "cc");
114 
115         return prev;
116 }
117 
118 static __always_inline unsigned long
119 __xchg_u16_local(volatile void *p, unsigned long val)
120 {
121         unsigned long prev;
122 
123         __asm__ __volatile__(
124 "1:     lharx   %0,0,%2         # __xchg_u16_local\n"
125 "       sthcx.  %3,0,%2\n"
126 "       bne-    1b"
127         : "=&r" (prev), "+m" (*(volatile unsigned short *)p)
128         : "r" (p), "r" (val)
129         : "cc", "memory");
130 
131         return prev;
132 }
133 
134 static __always_inline unsigned long
135 __xchg_u16_relaxed(u16 *p, unsigned long val)
136 {
137         unsigned long prev;
138 
139         __asm__ __volatile__(
140 "1:     lharx   %0,0,%2         # __xchg_u16_relaxed\n"
141 "       sthcx.  %3,0,%2\n"
142 "       bne-    1b"
143         : "=&r" (prev), "+m" (*p)
144         : "r" (p), "r" (val)
145         : "cc");
146 
147         return prev;
148 }
149 #endif
150 
151 static __always_inline unsigned long
152 __xchg_u32_local(volatile void *p, unsigned long val)
153 {
154         unsigned long prev;
155 
156         __asm__ __volatile__(
157 "1:     lwarx   %0,0,%2 \n"
158 "       stwcx.  %3,0,%2 \n\
159         bne-    1b"
160         : "=&r" (prev), "+m" (*(volatile unsigned int *)p)
161         : "r" (p), "r" (val)
162         : "cc", "memory");
163 
164         return prev;
165 }
166 
167 static __always_inline unsigned long
168 __xchg_u32_relaxed(u32 *p, unsigned long val)
169 {
170         unsigned long prev;
171 
172         __asm__ __volatile__(
173 "1:     lwarx   %0,0,%2\n"
174 "       stwcx.  %3,0,%2\n"
175 "       bne-    1b"
176         : "=&r" (prev), "+m" (*p)
177         : "r" (p), "r" (val)
178         : "cc");
179 
180         return prev;
181 }
182 
183 #ifdef CONFIG_PPC64
184 static __always_inline unsigned long
185 __xchg_u64_local(volatile void *p, unsigned long val)
186 {
187         unsigned long prev;
188 
189         __asm__ __volatile__(
190 "1:     ldarx   %0,0,%2 \n"
191 "       stdcx.  %3,0,%2 \n\
192         bne-    1b"
193         : "=&r" (prev), "+m" (*(volatile unsigned long *)p)
194         : "r" (p), "r" (val)
195         : "cc", "memory");
196 
197         return prev;
198 }
199 
200 static __always_inline unsigned long
201 __xchg_u64_relaxed(u64 *p, unsigned long val)
202 {
203         unsigned long prev;
204 
205         __asm__ __volatile__(
206 "1:     ldarx   %0,0,%2\n"
207 "       stdcx.  %3,0,%2\n"
208 "       bne-    1b"
209         : "=&r" (prev), "+m" (*p)
210         : "r" (p), "r" (val)
211         : "cc");
212 
213         return prev;
214 }
215 #endif
216 
217 static __always_inline unsigned long
218 __xchg_local(void *ptr, unsigned long x, unsigned int size)
219 {
220         switch (size) {
221         case 1:
222                 return __xchg_u8_local(ptr, x);
223         case 2:
224                 return __xchg_u16_local(ptr, x);
225         case 4:
226                 return __xchg_u32_local(ptr, x);
227 #ifdef CONFIG_PPC64
228         case 8:
229                 return __xchg_u64_local(ptr, x);
230 #endif
231         }
232         BUILD_BUG_ON_MSG(1, "Unsupported size for __xchg_local");
233         return x;
234 }
235 
236 static __always_inline unsigned long
237 __xchg_relaxed(void *ptr, unsigned long x, unsigned int size)
238 {
239         switch (size) {
240         case 1:
241                 return __xchg_u8_relaxed(ptr, x);
242         case 2:
243                 return __xchg_u16_relaxed(ptr, x);
244         case 4:
245                 return __xchg_u32_relaxed(ptr, x);
246 #ifdef CONFIG_PPC64
247         case 8:
248                 return __xchg_u64_relaxed(ptr, x);
249 #endif
250         }
251         BUILD_BUG_ON_MSG(1, "Unsupported size for __xchg_relaxed");
252         return x;
253 }
254 #define arch_xchg_local(ptr,x)                                               \
255   ({                                                                         \
256      __typeof__(*(ptr)) _x_ = (x);                                           \
257      (__typeof__(*(ptr))) __xchg_local((ptr),                                \
258                 (unsigned long)_x_, sizeof(*(ptr)));                         \
259   })
260 
261 #define arch_xchg_relaxed(ptr, x)                                       \
262 ({                                                                      \
263         __typeof__(*(ptr)) _x_ = (x);                                   \
264         (__typeof__(*(ptr))) __xchg_relaxed((ptr),                      \
265                         (unsigned long)_x_, sizeof(*(ptr)));            \
266 })
267 
268 /*
269  * Compare and exchange - if *p == old, set it to new,
270  * and return the old value of *p.
271  */
272 #ifndef CONFIG_PPC_HAS_LBARX_LHARX
273 CMPXCHG_GEN(u8, , PPC_ATOMIC_ENTRY_BARRIER, PPC_ATOMIC_EXIT_BARRIER, "memory");
274 CMPXCHG_GEN(u8, _local, , , "memory");
275 CMPXCHG_GEN(u8, _acquire, , PPC_ACQUIRE_BARRIER, "memory");
276 CMPXCHG_GEN(u8, _relaxed, , , "cc");
277 CMPXCHG_GEN(u16, , PPC_ATOMIC_ENTRY_BARRIER, PPC_ATOMIC_EXIT_BARRIER, "memory");
278 CMPXCHG_GEN(u16, _local, , , "memory");
279 CMPXCHG_GEN(u16, _acquire, , PPC_ACQUIRE_BARRIER, "memory");
280 CMPXCHG_GEN(u16, _relaxed, , , "cc");
281 #else
282 static __always_inline unsigned long
283 __cmpxchg_u8(volatile unsigned char *p, unsigned long old, unsigned long new)
284 {
285         unsigned int prev;
286 
287         __asm__ __volatile__ (
288         PPC_ATOMIC_ENTRY_BARRIER
289 "1:     lbarx   %0,0,%2         # __cmpxchg_u8\n"
290 "       cmpw    0,%0,%3\n"
291 "       bne-    2f\n"
292 "       stbcx.  %4,0,%2\n"
293 "       bne-    1b"
294         PPC_ATOMIC_EXIT_BARRIER
295         "\n\
296 2:"
297         : "=&r" (prev), "+m" (*p)
298         : "r" (p), "r" (old), "r" (new)
299         : "cc", "memory");
300 
301         return prev;
302 }
303 
304 static __always_inline unsigned long
305 __cmpxchg_u8_local(volatile unsigned char *p, unsigned long old,
306                         unsigned long new)
307 {
308         unsigned int prev;
309 
310         __asm__ __volatile__ (
311 "1:     lbarx   %0,0,%2         # __cmpxchg_u8_local\n"
312 "       cmpw    0,%0,%3\n"
313 "       bne-    2f\n"
314 "       stbcx.  %4,0,%2\n"
315 "       bne-    1b\n"
316 "2:"
317         : "=&r" (prev), "+m" (*p)
318         : "r" (p), "r" (old), "r" (new)
319         : "cc", "memory");
320 
321         return prev;
322 }
323 
324 static __always_inline unsigned long
325 __cmpxchg_u8_relaxed(u8 *p, unsigned long old, unsigned long new)
326 {
327         unsigned long prev;
328 
329         __asm__ __volatile__ (
330 "1:     lbarx   %0,0,%2         # __cmpxchg_u8_relaxed\n"
331 "       cmpw    0,%0,%3\n"
332 "       bne-    2f\n"
333 "       stbcx.  %4,0,%2\n"
334 "       bne-    1b\n"
335 "2:"
336         : "=&r" (prev), "+m" (*p)
337         : "r" (p), "r" (old), "r" (new)
338         : "cc");
339 
340         return prev;
341 }
342 
343 static __always_inline unsigned long
344 __cmpxchg_u8_acquire(u8 *p, unsigned long old, unsigned long new)
345 {
346         unsigned long prev;
347 
348         __asm__ __volatile__ (
349 "1:     lbarx   %0,0,%2         # __cmpxchg_u8_acquire\n"
350 "       cmpw    0,%0,%3\n"
351 "       bne-    2f\n"
352 "       stbcx.  %4,0,%2\n"
353 "       bne-    1b\n"
354         PPC_ACQUIRE_BARRIER
355 "2:"
356         : "=&r" (prev), "+m" (*p)
357         : "r" (p), "r" (old), "r" (new)
358         : "cc", "memory");
359 
360         return prev;
361 }
362 
363 static __always_inline unsigned long
364 __cmpxchg_u16(volatile unsigned short *p, unsigned long old, unsigned long new)
365 {
366         unsigned int prev;
367 
368         __asm__ __volatile__ (
369         PPC_ATOMIC_ENTRY_BARRIER
370 "1:     lharx   %0,0,%2         # __cmpxchg_u16\n"
371 "       cmpw    0,%0,%3\n"
372 "       bne-    2f\n"
373 "       sthcx.  %4,0,%2\n"
374 "       bne-    1b\n"
375         PPC_ATOMIC_EXIT_BARRIER
376 "2:"
377         : "=&r" (prev), "+m" (*p)
378         : "r" (p), "r" (old), "r" (new)
379         : "cc", "memory");
380 
381         return prev;
382 }
383 
384 static __always_inline unsigned long
385 __cmpxchg_u16_local(volatile unsigned short *p, unsigned long old,
386                         unsigned long new)
387 {
388         unsigned int prev;
389 
390         __asm__ __volatile__ (
391 "1:     lharx   %0,0,%2         # __cmpxchg_u16_local\n"
392 "       cmpw    0,%0,%3\n"
393 "       bne-    2f\n"
394 "       sthcx.  %4,0,%2\n"
395 "       bne-    1b"
396 "2:"
397         : "=&r" (prev), "+m" (*p)
398         : "r" (p), "r" (old), "r" (new)
399         : "cc", "memory");
400 
401         return prev;
402 }
403 
404 static __always_inline unsigned long
405 __cmpxchg_u16_relaxed(u16 *p, unsigned long old, unsigned long new)
406 {
407         unsigned long prev;
408 
409         __asm__ __volatile__ (
410 "1:     lharx   %0,0,%2         # __cmpxchg_u16_relaxed\n"
411 "       cmpw    0,%0,%3\n"
412 "       bne-    2f\n"
413 "       sthcx.  %4,0,%2\n"
414 "       bne-    1b\n"
415 "2:"
416         : "=&r" (prev), "+m" (*p)
417         : "r" (p), "r" (old), "r" (new)
418         : "cc");
419 
420         return prev;
421 }
422 
423 static __always_inline unsigned long
424 __cmpxchg_u16_acquire(u16 *p, unsigned long old, unsigned long new)
425 {
426         unsigned long prev;
427 
428         __asm__ __volatile__ (
429 "1:     lharx   %0,0,%2         # __cmpxchg_u16_acquire\n"
430 "       cmpw    0,%0,%3\n"
431 "       bne-    2f\n"
432 "       sthcx.  %4,0,%2\n"
433 "       bne-    1b\n"
434         PPC_ACQUIRE_BARRIER
435 "2:"
436         : "=&r" (prev), "+m" (*p)
437         : "r" (p), "r" (old), "r" (new)
438         : "cc", "memory");
439 
440         return prev;
441 }
442 #endif
443 
444 static __always_inline unsigned long
445 __cmpxchg_u32(volatile unsigned int *p, unsigned long old, unsigned long new)
446 {
447         unsigned int prev;
448 
449         __asm__ __volatile__ (
450         PPC_ATOMIC_ENTRY_BARRIER
451 "1:     lwarx   %0,0,%2         # __cmpxchg_u32\n\
452         cmpw    0,%0,%3\n\
453         bne-    2f\n"
454 "       stwcx.  %4,0,%2\n\
455         bne-    1b"
456         PPC_ATOMIC_EXIT_BARRIER
457         "\n\
458 2:"
459         : "=&r" (prev), "+m" (*p)
460         : "r" (p), "r" (old), "r" (new)
461         : "cc", "memory");
462 
463         return prev;
464 }
465 
466 static __always_inline unsigned long
467 __cmpxchg_u32_local(volatile unsigned int *p, unsigned long old,
468                         unsigned long new)
469 {
470         unsigned int prev;
471 
472         __asm__ __volatile__ (
473 "1:     lwarx   %0,0,%2         # __cmpxchg_u32\n\
474         cmpw    0,%0,%3\n\
475         bne-    2f\n"
476 "       stwcx.  %4,0,%2\n\
477         bne-    1b"
478         "\n\
479 2:"
480         : "=&r" (prev), "+m" (*p)
481         : "r" (p), "r" (old), "r" (new)
482         : "cc", "memory");
483 
484         return prev;
485 }
486 
487 static __always_inline unsigned long
488 __cmpxchg_u32_relaxed(u32 *p, unsigned long old, unsigned long new)
489 {
490         unsigned long prev;
491 
492         __asm__ __volatile__ (
493 "1:     lwarx   %0,0,%2         # __cmpxchg_u32_relaxed\n"
494 "       cmpw    0,%0,%3\n"
495 "       bne-    2f\n"
496 "       stwcx.  %4,0,%2\n"
497 "       bne-    1b\n"
498 "2:"
499         : "=&r" (prev), "+m" (*p)
500         : "r" (p), "r" (old), "r" (new)
501         : "cc");
502 
503         return prev;
504 }
505 
506 /*
507  * cmpxchg family don't have order guarantee if cmp part fails, therefore we
508  * can avoid superfluous barriers if we use assembly code to implement
509  * cmpxchg() and cmpxchg_acquire(), however we don't do the similar for
510  * cmpxchg_release() because that will result in putting a barrier in the
511  * middle of a ll/sc loop, which is probably a bad idea. For example, this
512  * might cause the conditional store more likely to fail.
513  */
514 static __always_inline unsigned long
515 __cmpxchg_u32_acquire(u32 *p, unsigned long old, unsigned long new)
516 {
517         unsigned long prev;
518 
519         __asm__ __volatile__ (
520 "1:     lwarx   %0,0,%2         # __cmpxchg_u32_acquire\n"
521 "       cmpw    0,%0,%3\n"
522 "       bne-    2f\n"
523 "       stwcx.  %4,0,%2\n"
524 "       bne-    1b\n"
525         PPC_ACQUIRE_BARRIER
526         "\n"
527 "2:"
528         : "=&r" (prev), "+m" (*p)
529         : "r" (p), "r" (old), "r" (new)
530         : "cc", "memory");
531 
532         return prev;
533 }
534 
535 #ifdef CONFIG_PPC64
536 static __always_inline unsigned long
537 __cmpxchg_u64(volatile unsigned long *p, unsigned long old, unsigned long new)
538 {
539         unsigned long prev;
540 
541         __asm__ __volatile__ (
542         PPC_ATOMIC_ENTRY_BARRIER
543 "1:     ldarx   %0,0,%2         # __cmpxchg_u64\n\
544         cmpd    0,%0,%3\n\
545         bne-    2f\n\
546         stdcx.  %4,0,%2\n\
547         bne-    1b"
548         PPC_ATOMIC_EXIT_BARRIER
549         "\n\
550 2:"
551         : "=&r" (prev), "+m" (*p)
552         : "r" (p), "r" (old), "r" (new)
553         : "cc", "memory");
554 
555         return prev;
556 }
557 
558 static __always_inline unsigned long
559 __cmpxchg_u64_local(volatile unsigned long *p, unsigned long old,
560                         unsigned long new)
561 {
562         unsigned long prev;
563 
564         __asm__ __volatile__ (
565 "1:     ldarx   %0,0,%2         # __cmpxchg_u64\n\
566         cmpd    0,%0,%3\n\
567         bne-    2f\n\
568         stdcx.  %4,0,%2\n\
569         bne-    1b"
570         "\n\
571 2:"
572         : "=&r" (prev), "+m" (*p)
573         : "r" (p), "r" (old), "r" (new)
574         : "cc", "memory");
575 
576         return prev;
577 }
578 
579 static __always_inline unsigned long
580 __cmpxchg_u64_relaxed(u64 *p, unsigned long old, unsigned long new)
581 {
582         unsigned long prev;
583 
584         __asm__ __volatile__ (
585 "1:     ldarx   %0,0,%2         # __cmpxchg_u64_relaxed\n"
586 "       cmpd    0,%0,%3\n"
587 "       bne-    2f\n"
588 "       stdcx.  %4,0,%2\n"
589 "       bne-    1b\n"
590 "2:"
591         : "=&r" (prev), "+m" (*p)
592         : "r" (p), "r" (old), "r" (new)
593         : "cc");
594 
595         return prev;
596 }
597 
598 static __always_inline unsigned long
599 __cmpxchg_u64_acquire(u64 *p, unsigned long old, unsigned long new)
600 {
601         unsigned long prev;
602 
603         __asm__ __volatile__ (
604 "1:     ldarx   %0,0,%2         # __cmpxchg_u64_acquire\n"
605 "       cmpd    0,%0,%3\n"
606 "       bne-    2f\n"
607 "       stdcx.  %4,0,%2\n"
608 "       bne-    1b\n"
609         PPC_ACQUIRE_BARRIER
610         "\n"
611 "2:"
612         : "=&r" (prev), "+m" (*p)
613         : "r" (p), "r" (old), "r" (new)
614         : "cc", "memory");
615 
616         return prev;
617 }
618 #endif
619 
620 static __always_inline unsigned long
621 __cmpxchg(volatile void *ptr, unsigned long old, unsigned long new,
622           unsigned int size)
623 {
624         switch (size) {
625         case 1:
626                 return __cmpxchg_u8(ptr, old, new);
627         case 2:
628                 return __cmpxchg_u16(ptr, old, new);
629         case 4:
630                 return __cmpxchg_u32(ptr, old, new);
631 #ifdef CONFIG_PPC64
632         case 8:
633                 return __cmpxchg_u64(ptr, old, new);
634 #endif
635         }
636         BUILD_BUG_ON_MSG(1, "Unsupported size for __cmpxchg");
637         return old;
638 }
639 
640 static __always_inline unsigned long
641 __cmpxchg_local(void *ptr, unsigned long old, unsigned long new,
642           unsigned int size)
643 {
644         switch (size) {
645         case 1:
646                 return __cmpxchg_u8_local(ptr, old, new);
647         case 2:
648                 return __cmpxchg_u16_local(ptr, old, new);
649         case 4:
650                 return __cmpxchg_u32_local(ptr, old, new);
651 #ifdef CONFIG_PPC64
652         case 8:
653                 return __cmpxchg_u64_local(ptr, old, new);
654 #endif
655         }
656         BUILD_BUG_ON_MSG(1, "Unsupported size for __cmpxchg_local");
657         return old;
658 }
659 
660 static __always_inline unsigned long
661 __cmpxchg_relaxed(void *ptr, unsigned long old, unsigned long new,
662                   unsigned int size)
663 {
664         switch (size) {
665         case 1:
666                 return __cmpxchg_u8_relaxed(ptr, old, new);
667         case 2:
668                 return __cmpxchg_u16_relaxed(ptr, old, new);
669         case 4:
670                 return __cmpxchg_u32_relaxed(ptr, old, new);
671 #ifdef CONFIG_PPC64
672         case 8:
673                 return __cmpxchg_u64_relaxed(ptr, old, new);
674 #endif
675         }
676         BUILD_BUG_ON_MSG(1, "Unsupported size for __cmpxchg_relaxed");
677         return old;
678 }
679 
680 static __always_inline unsigned long
681 __cmpxchg_acquire(void *ptr, unsigned long old, unsigned long new,
682                   unsigned int size)
683 {
684         switch (size) {
685         case 1:
686                 return __cmpxchg_u8_acquire(ptr, old, new);
687         case 2:
688                 return __cmpxchg_u16_acquire(ptr, old, new);
689         case 4:
690                 return __cmpxchg_u32_acquire(ptr, old, new);
691 #ifdef CONFIG_PPC64
692         case 8:
693                 return __cmpxchg_u64_acquire(ptr, old, new);
694 #endif
695         }
696         BUILD_BUG_ON_MSG(1, "Unsupported size for __cmpxchg_acquire");
697         return old;
698 }
699 #define arch_cmpxchg(ptr, o, n)                                          \
700   ({                                                                     \
701      __typeof__(*(ptr)) _o_ = (o);                                       \
702      __typeof__(*(ptr)) _n_ = (n);                                       \
703      (__typeof__(*(ptr))) __cmpxchg((ptr), (unsigned long)_o_,           \
704                                     (unsigned long)_n_, sizeof(*(ptr))); \
705   })
706 
707 
708 #define arch_cmpxchg_local(ptr, o, n)                                    \
709   ({                                                                     \
710      __typeof__(*(ptr)) _o_ = (o);                                       \
711      __typeof__(*(ptr)) _n_ = (n);                                       \
712      (__typeof__(*(ptr))) __cmpxchg_local((ptr), (unsigned long)_o_,     \
713                                     (unsigned long)_n_, sizeof(*(ptr))); \
714   })
715 
716 #define arch_cmpxchg_relaxed(ptr, o, n)                                 \
717 ({                                                                      \
718         __typeof__(*(ptr)) _o_ = (o);                                   \
719         __typeof__(*(ptr)) _n_ = (n);                                   \
720         (__typeof__(*(ptr))) __cmpxchg_relaxed((ptr),                   \
721                         (unsigned long)_o_, (unsigned long)_n_,         \
722                         sizeof(*(ptr)));                                \
723 })
724 
725 #define arch_cmpxchg_acquire(ptr, o, n)                                 \
726 ({                                                                      \
727         __typeof__(*(ptr)) _o_ = (o);                                   \
728         __typeof__(*(ptr)) _n_ = (n);                                   \
729         (__typeof__(*(ptr))) __cmpxchg_acquire((ptr),                   \
730                         (unsigned long)_o_, (unsigned long)_n_,         \
731                         sizeof(*(ptr)));                                \
732 })
733 #ifdef CONFIG_PPC64
734 #define arch_cmpxchg64(ptr, o, n)                                       \
735   ({                                                                    \
736         BUILD_BUG_ON(sizeof(*(ptr)) != 8);                              \
737         arch_cmpxchg((ptr), (o), (n));                                  \
738   })
739 #define arch_cmpxchg64_local(ptr, o, n)                                 \
740   ({                                                                    \
741         BUILD_BUG_ON(sizeof(*(ptr)) != 8);                              \
742         arch_cmpxchg_local((ptr), (o), (n));                            \
743   })
744 #define arch_cmpxchg64_relaxed(ptr, o, n)                               \
745 ({                                                                      \
746         BUILD_BUG_ON(sizeof(*(ptr)) != 8);                              \
747         arch_cmpxchg_relaxed((ptr), (o), (n));                          \
748 })
749 #define arch_cmpxchg64_acquire(ptr, o, n)                               \
750 ({                                                                      \
751         BUILD_BUG_ON(sizeof(*(ptr)) != 8);                              \
752         arch_cmpxchg_acquire((ptr), (o), (n));                          \
753 })
754 #else
755 #include <asm-generic/cmpxchg-local.h>
756 #define arch_cmpxchg64_local(ptr, o, n) __generic_cmpxchg64_local((ptr), (o), (n))
757 #endif
758 
759 #endif /* __KERNEL__ */
760 #endif /* _ASM_POWERPC_CMPXCHG_H_ */
761 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php