1 /* SPDX-License-Identifier: GPL-2.0 */ 2 #ifndef __ASM_SH_ATOMIC_IRQ_H 3 #define __ASM_SH_ATOMIC_IRQ_H 4 5 #include <linux/irqflags.h> 6 7 /* 8 * To get proper branch prediction for the main line, we must branch 9 * forward to code at the end of this object's .text section, then 10 * branch back to restart the operation. 11 */ 12 13 #define ATOMIC_OP(op, c_op) \ 14 static inline void atomic_##op(int i, atomic_t *v) \ 15 { \ 16 unsigned long flags; \ 17 \ 18 raw_local_irq_save(flags); \ 19 v->counter c_op i; \ 20 raw_local_irq_restore(flags); \ 21 } 22 23 #define ATOMIC_OP_RETURN(op, c_op) \ 24 static inline int atomic_##op##_return(int i, atomic_t *v) \ 25 { \ 26 unsigned long temp, flags; \ 27 \ 28 raw_local_irq_save(flags); \ 29 temp = v->counter; \ 30 temp c_op i; \ 31 v->counter = temp; \ 32 raw_local_irq_restore(flags); \ 33 \ 34 return temp; \ 35 } 36 37 #define ATOMIC_FETCH_OP(op, c_op) \ 38 static inline int atomic_fetch_##op(int i, atomic_t *v) \ 39 { \ 40 unsigned long temp, flags; \ 41 \ 42 raw_local_irq_save(flags); \ 43 temp = v->counter; \ 44 v->counter c_op i; \ 45 raw_local_irq_restore(flags); \ 46 \ 47 return temp; \ 48 } 49 50 #define ATOMIC_OPS(op, c_op) \ 51 ATOMIC_OP(op, c_op) \ 52 ATOMIC_OP_RETURN(op, c_op) \ 53 ATOMIC_FETCH_OP(op, c_op) 54 55 ATOMIC_OPS(add, +=) 56 ATOMIC_OPS(sub, -=) 57 58 #undef ATOMIC_OPS 59 #define ATOMIC_OPS(op, c_op) \ 60 ATOMIC_OP(op, c_op) \ 61 ATOMIC_FETCH_OP(op, c_op) 62 63 ATOMIC_OPS(and, &=) 64 ATOMIC_OPS(or, |=) 65 ATOMIC_OPS(xor, ^=) 66 67 #undef ATOMIC_OPS 68 #undef ATOMIC_FETCH_OP 69 #undef ATOMIC_OP_RETURN 70 #undef ATOMIC_OP 71 72 #endif /* __ASM_SH_ATOMIC_IRQ_H */ 73