Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0 */
0002 #ifndef __ASM_GENERIC_CMPXCHG_LOCAL_H
0003 #define __ASM_GENERIC_CMPXCHG_LOCAL_H
0004 
0005 #include <linux/types.h>
0006 #include <linux/irqflags.h>
0007 
0008 extern unsigned long wrong_size_cmpxchg(volatile void *ptr)
0009     __noreturn;
0010 
0011 /*
0012  * Generic version of __cmpxchg_local (disables interrupts). Takes an unsigned
0013  * long parameter, supporting various types of architectures.
0014  */
0015 static inline unsigned long __generic_cmpxchg_local(volatile void *ptr,
0016         unsigned long old, unsigned long new, int size)
0017 {
0018     unsigned long flags, prev;
0019 
0020     /*
0021      * Sanity checking, compile-time.
0022      */
0023     if (size == 8 && sizeof(unsigned long) != 8)
0024         wrong_size_cmpxchg(ptr);
0025 
0026     raw_local_irq_save(flags);
0027     switch (size) {
0028     case 1: prev = *(u8 *)ptr;
0029         if (prev == old)
0030             *(u8 *)ptr = (u8)new;
0031         break;
0032     case 2: prev = *(u16 *)ptr;
0033         if (prev == old)
0034             *(u16 *)ptr = (u16)new;
0035         break;
0036     case 4: prev = *(u32 *)ptr;
0037         if (prev == old)
0038             *(u32 *)ptr = (u32)new;
0039         break;
0040     case 8: prev = *(u64 *)ptr;
0041         if (prev == old)
0042             *(u64 *)ptr = (u64)new;
0043         break;
0044     default:
0045         wrong_size_cmpxchg(ptr);
0046     }
0047     raw_local_irq_restore(flags);
0048     return prev;
0049 }
0050 
0051 /*
0052  * Generic version of __cmpxchg64_local. Takes an u64 parameter.
0053  */
0054 static inline u64 __generic_cmpxchg64_local(volatile void *ptr,
0055         u64 old, u64 new)
0056 {
0057     u64 prev;
0058     unsigned long flags;
0059 
0060     raw_local_irq_save(flags);
0061     prev = *(u64 *)ptr;
0062     if (prev == old)
0063         *(u64 *)ptr = new;
0064     raw_local_irq_restore(flags);
0065     return prev;
0066 }
0067 
0068 #endif