1819833afSPeter Tyser /* 2819833afSPeter Tyser * linux/include/asm-arm/atomic.h 3819833afSPeter Tyser * 4819833afSPeter Tyser * Copyright (c) 1996 Russell King. 5819833afSPeter Tyser * 6819833afSPeter Tyser * This program is free software; you can redistribute it and/or modify 7819833afSPeter Tyser * it under the terms of the GNU General Public License version 2 as 8819833afSPeter Tyser * published by the Free Software Foundation. 9819833afSPeter Tyser * 10819833afSPeter Tyser * Changelog: 11819833afSPeter Tyser * 27-06-1996 RMK Created 12819833afSPeter Tyser * 13-04-1997 RMK Made functions atomic! 13819833afSPeter Tyser * 07-12-1997 RMK Upgraded for v2.1. 14819833afSPeter Tyser * 26-08-1998 PJB Added #ifdef __KERNEL__ 15819833afSPeter Tyser */ 16819833afSPeter Tyser #ifndef __ASM_ARM_ATOMIC_H 17819833afSPeter Tyser #define __ASM_ARM_ATOMIC_H 18819833afSPeter Tyser 19819833afSPeter Tyser #ifdef CONFIG_SMP 20819833afSPeter Tyser #error SMP not supported 21819833afSPeter Tyser #endif 22819833afSPeter Tyser 23819833afSPeter Tyser typedef struct { volatile int counter; } atomic_t; 24819833afSPeter Tyser 25819833afSPeter Tyser #define ATOMIC_INIT(i) { (i) } 26819833afSPeter Tyser 27819833afSPeter Tyser #ifdef __KERNEL__ 287d89982bSVasili Galka #include <asm/proc-armv/system.h> 29819833afSPeter Tyser 30819833afSPeter Tyser #define atomic_read(v) ((v)->counter) 31819833afSPeter Tyser #define atomic_set(v,i) (((v)->counter) = (i)) 32819833afSPeter Tyser 33819833afSPeter Tyser static inline void atomic_add(int i, volatile atomic_t *v) 34819833afSPeter Tyser { 35*1d48ca69SHeiko Schocher unsigned long flags = 0; 36819833afSPeter Tyser 37819833afSPeter Tyser local_irq_save(flags); 38819833afSPeter Tyser v->counter += i; 39819833afSPeter Tyser local_irq_restore(flags); 40819833afSPeter Tyser } 41819833afSPeter Tyser 42819833afSPeter Tyser static inline void atomic_sub(int i, volatile atomic_t *v) 43819833afSPeter Tyser { 44*1d48ca69SHeiko Schocher unsigned long flags = 0; 45819833afSPeter Tyser 46819833afSPeter Tyser local_irq_save(flags); 47819833afSPeter Tyser v->counter -= i; 48819833afSPeter Tyser local_irq_restore(flags); 49819833afSPeter Tyser } 50819833afSPeter Tyser 51819833afSPeter Tyser static inline void atomic_inc(volatile atomic_t *v) 52819833afSPeter Tyser { 53*1d48ca69SHeiko Schocher unsigned long flags = 0; 54819833afSPeter Tyser 55819833afSPeter Tyser local_irq_save(flags); 56819833afSPeter Tyser v->counter += 1; 57819833afSPeter Tyser local_irq_restore(flags); 58819833afSPeter Tyser } 59819833afSPeter Tyser 60819833afSPeter Tyser static inline void atomic_dec(volatile atomic_t *v) 61819833afSPeter Tyser { 62*1d48ca69SHeiko Schocher unsigned long flags = 0; 63819833afSPeter Tyser 64819833afSPeter Tyser local_irq_save(flags); 65819833afSPeter Tyser v->counter -= 1; 66819833afSPeter Tyser local_irq_restore(flags); 67819833afSPeter Tyser } 68819833afSPeter Tyser 69819833afSPeter Tyser static inline int atomic_dec_and_test(volatile atomic_t *v) 70819833afSPeter Tyser { 71*1d48ca69SHeiko Schocher unsigned long flags = 0; 72819833afSPeter Tyser int val; 73819833afSPeter Tyser 74819833afSPeter Tyser local_irq_save(flags); 75819833afSPeter Tyser val = v->counter; 76819833afSPeter Tyser v->counter = val -= 1; 77819833afSPeter Tyser local_irq_restore(flags); 78819833afSPeter Tyser 79819833afSPeter Tyser return val == 0; 80819833afSPeter Tyser } 81819833afSPeter Tyser 82819833afSPeter Tyser static inline int atomic_add_negative(int i, volatile atomic_t *v) 83819833afSPeter Tyser { 84*1d48ca69SHeiko Schocher unsigned long flags = 0; 85819833afSPeter Tyser int val; 86819833afSPeter Tyser 87819833afSPeter Tyser local_irq_save(flags); 88819833afSPeter Tyser val = v->counter; 89819833afSPeter Tyser v->counter = val += i; 90819833afSPeter Tyser local_irq_restore(flags); 91819833afSPeter Tyser 92819833afSPeter Tyser return val < 0; 93819833afSPeter Tyser } 94819833afSPeter Tyser 95819833afSPeter Tyser static inline void atomic_clear_mask(unsigned long mask, unsigned long *addr) 96819833afSPeter Tyser { 97*1d48ca69SHeiko Schocher unsigned long flags = 0; 98819833afSPeter Tyser 99819833afSPeter Tyser local_irq_save(flags); 100819833afSPeter Tyser *addr &= ~mask; 101819833afSPeter Tyser local_irq_restore(flags); 102819833afSPeter Tyser } 103819833afSPeter Tyser 104819833afSPeter Tyser /* Atomic operations are already serializing on ARM */ 105819833afSPeter Tyser #define smp_mb__before_atomic_dec() barrier() 106819833afSPeter Tyser #define smp_mb__after_atomic_dec() barrier() 107819833afSPeter Tyser #define smp_mb__before_atomic_inc() barrier() 108819833afSPeter Tyser #define smp_mb__after_atomic_inc() barrier() 109819833afSPeter Tyser 110819833afSPeter Tyser #endif 111819833afSPeter Tyser #endif 112