1*819833afSPeter Tyser /* 2*819833afSPeter Tyser * linux/include/asm-arm/atomic.h 3*819833afSPeter Tyser * 4*819833afSPeter Tyser * Copyright (c) 1996 Russell King. 5*819833afSPeter Tyser * 6*819833afSPeter Tyser * This program is free software; you can redistribute it and/or modify 7*819833afSPeter Tyser * it under the terms of the GNU General Public License version 2 as 8*819833afSPeter Tyser * published by the Free Software Foundation. 9*819833afSPeter Tyser * 10*819833afSPeter Tyser * Changelog: 11*819833afSPeter Tyser * 27-06-1996 RMK Created 12*819833afSPeter Tyser * 13-04-1997 RMK Made functions atomic! 13*819833afSPeter Tyser * 07-12-1997 RMK Upgraded for v2.1. 14*819833afSPeter Tyser * 26-08-1998 PJB Added #ifdef __KERNEL__ 15*819833afSPeter Tyser */ 16*819833afSPeter Tyser #ifndef __ASM_ARM_ATOMIC_H 17*819833afSPeter Tyser #define __ASM_ARM_ATOMIC_H 18*819833afSPeter Tyser 19*819833afSPeter Tyser #include <linux/config.h> 20*819833afSPeter Tyser 21*819833afSPeter Tyser #ifdef CONFIG_SMP 22*819833afSPeter Tyser #error SMP not supported 23*819833afSPeter Tyser #endif 24*819833afSPeter Tyser 25*819833afSPeter Tyser typedef struct { volatile int counter; } atomic_t; 26*819833afSPeter Tyser 27*819833afSPeter Tyser #define ATOMIC_INIT(i) { (i) } 28*819833afSPeter Tyser 29*819833afSPeter Tyser #ifdef __KERNEL__ 30*819833afSPeter Tyser #include <asm/proc/system.h> 31*819833afSPeter Tyser 32*819833afSPeter Tyser #define atomic_read(v) ((v)->counter) 33*819833afSPeter Tyser #define atomic_set(v,i) (((v)->counter) = (i)) 34*819833afSPeter Tyser 35*819833afSPeter Tyser static inline void atomic_add(int i, volatile atomic_t *v) 36*819833afSPeter Tyser { 37*819833afSPeter Tyser unsigned long flags; 38*819833afSPeter Tyser 39*819833afSPeter Tyser local_irq_save(flags); 40*819833afSPeter Tyser v->counter += i; 41*819833afSPeter Tyser local_irq_restore(flags); 42*819833afSPeter Tyser } 43*819833afSPeter Tyser 44*819833afSPeter Tyser static inline void atomic_sub(int i, volatile atomic_t *v) 45*819833afSPeter Tyser { 46*819833afSPeter Tyser unsigned long flags; 47*819833afSPeter Tyser 48*819833afSPeter Tyser local_irq_save(flags); 49*819833afSPeter Tyser v->counter -= i; 50*819833afSPeter Tyser local_irq_restore(flags); 51*819833afSPeter Tyser } 52*819833afSPeter Tyser 53*819833afSPeter Tyser static inline void atomic_inc(volatile atomic_t *v) 54*819833afSPeter Tyser { 55*819833afSPeter Tyser unsigned long flags; 56*819833afSPeter Tyser 57*819833afSPeter Tyser local_irq_save(flags); 58*819833afSPeter Tyser v->counter += 1; 59*819833afSPeter Tyser local_irq_restore(flags); 60*819833afSPeter Tyser } 61*819833afSPeter Tyser 62*819833afSPeter Tyser static inline void atomic_dec(volatile atomic_t *v) 63*819833afSPeter Tyser { 64*819833afSPeter Tyser unsigned long flags; 65*819833afSPeter Tyser 66*819833afSPeter Tyser local_irq_save(flags); 67*819833afSPeter Tyser v->counter -= 1; 68*819833afSPeter Tyser local_irq_restore(flags); 69*819833afSPeter Tyser } 70*819833afSPeter Tyser 71*819833afSPeter Tyser static inline int atomic_dec_and_test(volatile atomic_t *v) 72*819833afSPeter Tyser { 73*819833afSPeter Tyser unsigned long flags; 74*819833afSPeter Tyser int val; 75*819833afSPeter Tyser 76*819833afSPeter Tyser local_irq_save(flags); 77*819833afSPeter Tyser val = v->counter; 78*819833afSPeter Tyser v->counter = val -= 1; 79*819833afSPeter Tyser local_irq_restore(flags); 80*819833afSPeter Tyser 81*819833afSPeter Tyser return val == 0; 82*819833afSPeter Tyser } 83*819833afSPeter Tyser 84*819833afSPeter Tyser static inline int atomic_add_negative(int i, volatile atomic_t *v) 85*819833afSPeter Tyser { 86*819833afSPeter Tyser unsigned long flags; 87*819833afSPeter Tyser int val; 88*819833afSPeter Tyser 89*819833afSPeter Tyser local_irq_save(flags); 90*819833afSPeter Tyser val = v->counter; 91*819833afSPeter Tyser v->counter = val += i; 92*819833afSPeter Tyser local_irq_restore(flags); 93*819833afSPeter Tyser 94*819833afSPeter Tyser return val < 0; 95*819833afSPeter Tyser } 96*819833afSPeter Tyser 97*819833afSPeter Tyser static inline void atomic_clear_mask(unsigned long mask, unsigned long *addr) 98*819833afSPeter Tyser { 99*819833afSPeter Tyser unsigned long flags; 100*819833afSPeter Tyser 101*819833afSPeter Tyser local_irq_save(flags); 102*819833afSPeter Tyser *addr &= ~mask; 103*819833afSPeter Tyser local_irq_restore(flags); 104*819833afSPeter Tyser } 105*819833afSPeter Tyser 106*819833afSPeter Tyser /* Atomic operations are already serializing on ARM */ 107*819833afSPeter Tyser #define smp_mb__before_atomic_dec() barrier() 108*819833afSPeter Tyser #define smp_mb__after_atomic_dec() barrier() 109*819833afSPeter Tyser #define smp_mb__before_atomic_inc() barrier() 110*819833afSPeter Tyser #define smp_mb__after_atomic_inc() barrier() 111*819833afSPeter Tyser 112*819833afSPeter Tyser #endif 113*819833afSPeter Tyser #endif 114