atomic.h revision 7224c0d1045327d637dab2c90777b6d5ec6d6804
169f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer#ifndef __ARCH_M68K_ATOMIC__ 269f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer#define __ARCH_M68K_ATOMIC__ 369f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer 469f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer#include <linux/types.h> 5803f69144f0d48863c68f9d111b56849c7cef5bbDavid Howells#include <linux/irqflags.h> 67224c0d1045327d637dab2c90777b6d5ec6d6804Greg Ungerer#include <asm/cmpxchg.h> 769f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer 869f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer/* 969f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer * Atomic operations that C can't guarantee us. Useful for 1069f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer * resource counting etc.. 1169f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer */ 1269f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer 1369f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer/* 1469f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer * We do not have SMP m68k systems, so we don't have to deal with that. 1569f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer */ 1669f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer 1769f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer#define ATOMIC_INIT(i) { (i) } 1869f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer 1969f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer#define atomic_read(v) (*(volatile int *)&(v)->counter) 2069f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer#define atomic_set(v, i) (((v)->counter) = i) 2169f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer 2269f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer/* 2369f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer * The ColdFire parts cannot do some immediate to memory operations, 2469f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer * so for them we do not specify the "i" asm constraint. 2569f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer */ 2669f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer#ifdef CONFIG_COLDFIRE 2769f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer#define ASM_DI "d" 2849148020bcb6910ce71417bd990a5ce7017f9bd3Sam Ravnborg#else 2969f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer#define ASM_DI "di" 3049148020bcb6910ce71417bd990a5ce7017f9bd3Sam Ravnborg#endif 31b417b717093085e45867770b29b9a97692cf132aGeert Uytterhoeven 3269f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungererstatic inline void atomic_add(int i, atomic_t *v) 3369f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer{ 3469f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer __asm__ __volatile__("addl %1,%0" : "+m" (*v) : ASM_DI (i)); 3569f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer} 3669f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer 3769f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungererstatic inline void atomic_sub(int i, atomic_t *v) 3869f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer{ 3969f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer __asm__ __volatile__("subl %1,%0" : "+m" (*v) : ASM_DI (i)); 4069f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer} 4169f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer 4269f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungererstatic inline void atomic_inc(atomic_t *v) 4369f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer{ 4469f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer __asm__ __volatile__("addql #1,%0" : "+m" (*v)); 4569f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer} 4669f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer 4769f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungererstatic inline void atomic_dec(atomic_t *v) 4869f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer{ 4969f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer __asm__ __volatile__("subql #1,%0" : "+m" (*v)); 5069f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer} 5169f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer 5269f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungererstatic inline int atomic_dec_and_test(atomic_t *v) 5369f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer{ 5469f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer char c; 5569f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer __asm__ __volatile__("subql #1,%1; seq %0" : "=d" (c), "+m" (*v)); 5669f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer return c != 0; 5769f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer} 5869f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer 5983b73d6cb8301df32d9887c16c83490c4fd1f55fGreg Ungererstatic inline int atomic_dec_and_test_lt(atomic_t *v) 6083b73d6cb8301df32d9887c16c83490c4fd1f55fGreg Ungerer{ 6183b73d6cb8301df32d9887c16c83490c4fd1f55fGreg Ungerer char c; 6283b73d6cb8301df32d9887c16c83490c4fd1f55fGreg Ungerer __asm__ __volatile__( 6383b73d6cb8301df32d9887c16c83490c4fd1f55fGreg Ungerer "subql #1,%1; slt %0" 6483b73d6cb8301df32d9887c16c83490c4fd1f55fGreg Ungerer : "=d" (c), "=m" (*v) 6583b73d6cb8301df32d9887c16c83490c4fd1f55fGreg Ungerer : "m" (*v)); 6683b73d6cb8301df32d9887c16c83490c4fd1f55fGreg Ungerer return c != 0; 6783b73d6cb8301df32d9887c16c83490c4fd1f55fGreg Ungerer} 6883b73d6cb8301df32d9887c16c83490c4fd1f55fGreg Ungerer 6969f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungererstatic inline int atomic_inc_and_test(atomic_t *v) 7069f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer{ 7169f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer char c; 7269f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer __asm__ __volatile__("addql #1,%1; seq %0" : "=d" (c), "+m" (*v)); 7369f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer return c != 0; 7469f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer} 7569f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer 7669f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer#ifdef CONFIG_RMW_INSNS 7769f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer 7869f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungererstatic inline int atomic_add_return(int i, atomic_t *v) 7969f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer{ 8069f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer int t, tmp; 8169f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer 8269f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer __asm__ __volatile__( 8369f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer "1: movel %2,%1\n" 8469f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer " addl %3,%1\n" 8569f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer " casl %2,%1,%0\n" 8669f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer " jne 1b" 8769f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer : "+m" (*v), "=&d" (t), "=&d" (tmp) 8869f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer : "g" (i), "2" (atomic_read(v))); 8969f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer return t; 9069f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer} 9169f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer 9269f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungererstatic inline int atomic_sub_return(int i, atomic_t *v) 9369f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer{ 9469f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer int t, tmp; 9569f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer 9669f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer __asm__ __volatile__( 9769f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer "1: movel %2,%1\n" 9869f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer " subl %3,%1\n" 9969f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer " casl %2,%1,%0\n" 10069f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer " jne 1b" 10169f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer : "+m" (*v), "=&d" (t), "=&d" (tmp) 10269f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer : "g" (i), "2" (atomic_read(v))); 10369f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer return t; 10469f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer} 10569f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer 10669f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer#define atomic_cmpxchg(v, o, n) ((int)cmpxchg(&((v)->counter), (o), (n))) 10769f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer#define atomic_xchg(v, new) (xchg(&((v)->counter), new)) 10869f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer 10969f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer#else /* !CONFIG_RMW_INSNS */ 11069f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer 11169f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungererstatic inline int atomic_add_return(int i, atomic_t * v) 11269f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer{ 11369f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer unsigned long flags; 11469f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer int t; 11569f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer 11669f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer local_irq_save(flags); 11769f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer t = atomic_read(v); 11869f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer t += i; 11969f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer atomic_set(v, t); 12069f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer local_irq_restore(flags); 12169f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer 12269f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer return t; 12369f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer} 12469f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer 12569f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungererstatic inline int atomic_sub_return(int i, atomic_t * v) 12669f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer{ 12769f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer unsigned long flags; 12869f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer int t; 12969f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer 13069f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer local_irq_save(flags); 13169f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer t = atomic_read(v); 13269f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer t -= i; 13369f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer atomic_set(v, t); 13469f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer local_irq_restore(flags); 13569f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer 13669f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer return t; 13769f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer} 13869f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer 13969f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungererstatic inline int atomic_cmpxchg(atomic_t *v, int old, int new) 14069f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer{ 14169f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer unsigned long flags; 14269f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer int prev; 14369f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer 14469f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer local_irq_save(flags); 14569f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer prev = atomic_read(v); 14669f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer if (prev == old) 14769f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer atomic_set(v, new); 14869f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer local_irq_restore(flags); 14969f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer return prev; 15069f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer} 15169f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer 15269f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungererstatic inline int atomic_xchg(atomic_t *v, int new) 15369f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer{ 15469f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer unsigned long flags; 15569f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer int prev; 15669f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer 15769f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer local_irq_save(flags); 15869f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer prev = atomic_read(v); 15969f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer atomic_set(v, new); 16069f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer local_irq_restore(flags); 16169f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer return prev; 16269f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer} 16369f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer 16469f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer#endif /* !CONFIG_RMW_INSNS */ 16569f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer 16669f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer#define atomic_dec_return(v) atomic_sub_return(1, (v)) 16769f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer#define atomic_inc_return(v) atomic_add_return(1, (v)) 16869f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer 16969f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungererstatic inline int atomic_sub_and_test(int i, atomic_t *v) 17069f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer{ 17169f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer char c; 17269f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer __asm__ __volatile__("subl %2,%1; seq %0" 17369f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer : "=d" (c), "+m" (*v) 17469f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer : ASM_DI (i)); 17569f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer return c != 0; 17669f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer} 17769f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer 17869f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungererstatic inline int atomic_add_negative(int i, atomic_t *v) 17969f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer{ 18069f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer char c; 18169f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer __asm__ __volatile__("addl %2,%1; smi %0" 18269f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer : "=d" (c), "+m" (*v) 18335de674982aa13de98cf470c640895164017563eGreg Ungerer : ASM_DI (i)); 18469f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer return c != 0; 18569f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer} 18669f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer 18769f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungererstatic inline void atomic_clear_mask(unsigned long mask, unsigned long *v) 18869f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer{ 18935de674982aa13de98cf470c640895164017563eGreg Ungerer __asm__ __volatile__("andl %1,%0" : "+m" (*v) : ASM_DI (~(mask))); 19069f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer} 19169f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer 19269f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungererstatic inline void atomic_set_mask(unsigned long mask, unsigned long *v) 19369f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer{ 19435de674982aa13de98cf470c640895164017563eGreg Ungerer __asm__ __volatile__("orl %1,%0" : "+m" (*v) : ASM_DI (mask)); 19569f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer} 19669f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer 197f24219b4e90cf70ec4a211b17fbabc725a0ddf3cArun Sharmastatic __inline__ int __atomic_add_unless(atomic_t *v, int a, int u) 19869f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer{ 19969f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer int c, old; 20069f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer c = atomic_read(v); 20169f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer for (;;) { 20269f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer if (unlikely(c == (u))) 20369f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer break; 20469f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer old = atomic_cmpxchg((v), c, c + (a)); 20569f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer if (likely(old == c)) 20669f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer break; 20769f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer c = old; 20869f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer } 209f24219b4e90cf70ec4a211b17fbabc725a0ddf3cArun Sharma return c; 21069f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer} 21169f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer 21269f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer 21369f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer/* Atomic operations are already serializing */ 21469f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer#define smp_mb__before_atomic_dec() barrier() 21569f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer#define smp_mb__after_atomic_dec() barrier() 21669f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer#define smp_mb__before_atomic_inc() barrier() 21769f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer#define smp_mb__after_atomic_inc() barrier() 21869f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer 21969f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer#endif /* __ARCH_M68K_ATOMIC __ */ 220