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