atomic.h (3609B)
1/* 2 * Copyright (C) 2014 Stefan Kristiansson <stefan.kristiansson@saunalahti.fi> 3 * 4 * This file is licensed under the terms of the GNU General Public License 5 * version 2. This program is licensed "as is" without any warranty of any 6 * kind, whether express or implied. 7 */ 8 9#ifndef __ASM_OPENRISC_ATOMIC_H 10#define __ASM_OPENRISC_ATOMIC_H 11 12#include <linux/types.h> 13 14/* Atomically perform op with v->counter and i */ 15#define ATOMIC_OP(op) \ 16static inline void arch_atomic_##op(int i, atomic_t *v) \ 17{ \ 18 int tmp; \ 19 \ 20 __asm__ __volatile__( \ 21 "1: l.lwa %0,0(%1) \n" \ 22 " l." #op " %0,%0,%2 \n" \ 23 " l.swa 0(%1),%0 \n" \ 24 " l.bnf 1b \n" \ 25 " l.nop \n" \ 26 : "=&r"(tmp) \ 27 : "r"(&v->counter), "r"(i) \ 28 : "cc", "memory"); \ 29} 30 31/* Atomically perform op with v->counter and i, return the result */ 32#define ATOMIC_OP_RETURN(op) \ 33static inline int arch_atomic_##op##_return(int i, atomic_t *v) \ 34{ \ 35 int tmp; \ 36 \ 37 __asm__ __volatile__( \ 38 "1: l.lwa %0,0(%1) \n" \ 39 " l." #op " %0,%0,%2 \n" \ 40 " l.swa 0(%1),%0 \n" \ 41 " l.bnf 1b \n" \ 42 " l.nop \n" \ 43 : "=&r"(tmp) \ 44 : "r"(&v->counter), "r"(i) \ 45 : "cc", "memory"); \ 46 \ 47 return tmp; \ 48} 49 50/* Atomically perform op with v->counter and i, return orig v->counter */ 51#define ATOMIC_FETCH_OP(op) \ 52static inline int arch_atomic_fetch_##op(int i, atomic_t *v) \ 53{ \ 54 int tmp, old; \ 55 \ 56 __asm__ __volatile__( \ 57 "1: l.lwa %0,0(%2) \n" \ 58 " l." #op " %1,%0,%3 \n" \ 59 " l.swa 0(%2),%1 \n" \ 60 " l.bnf 1b \n" \ 61 " l.nop \n" \ 62 : "=&r"(old), "=&r"(tmp) \ 63 : "r"(&v->counter), "r"(i) \ 64 : "cc", "memory"); \ 65 \ 66 return old; \ 67} 68 69ATOMIC_OP_RETURN(add) 70ATOMIC_OP_RETURN(sub) 71 72ATOMIC_FETCH_OP(add) 73ATOMIC_FETCH_OP(sub) 74ATOMIC_FETCH_OP(and) 75ATOMIC_FETCH_OP(or) 76ATOMIC_FETCH_OP(xor) 77 78ATOMIC_OP(add) 79ATOMIC_OP(sub) 80ATOMIC_OP(and) 81ATOMIC_OP(or) 82ATOMIC_OP(xor) 83 84#undef ATOMIC_FETCH_OP 85#undef ATOMIC_OP_RETURN 86#undef ATOMIC_OP 87 88#define arch_atomic_add_return arch_atomic_add_return 89#define arch_atomic_sub_return arch_atomic_sub_return 90#define arch_atomic_fetch_add arch_atomic_fetch_add 91#define arch_atomic_fetch_sub arch_atomic_fetch_sub 92#define arch_atomic_fetch_and arch_atomic_fetch_and 93#define arch_atomic_fetch_or arch_atomic_fetch_or 94#define arch_atomic_fetch_xor arch_atomic_fetch_xor 95#define arch_atomic_add arch_atomic_add 96#define arch_atomic_sub arch_atomic_sub 97#define arch_atomic_and arch_atomic_and 98#define arch_atomic_or arch_atomic_or 99#define arch_atomic_xor arch_atomic_xor 100 101/* 102 * Atomically add a to v->counter as long as v is not already u. 103 * Returns the original value at v->counter. 104 * 105 * This is often used through atomic_inc_not_zero() 106 */ 107static inline int arch_atomic_fetch_add_unless(atomic_t *v, int a, int u) 108{ 109 int old, tmp; 110 111 __asm__ __volatile__( 112 "1: l.lwa %0, 0(%2) \n" 113 " l.sfeq %0, %4 \n" 114 " l.bf 2f \n" 115 " l.add %1, %0, %3 \n" 116 " l.swa 0(%2), %1 \n" 117 " l.bnf 1b \n" 118 " l.nop \n" 119 "2: \n" 120 : "=&r"(old), "=&r" (tmp) 121 : "r"(&v->counter), "r"(a), "r"(u) 122 : "cc", "memory"); 123 124 return old; 125} 126#define arch_atomic_fetch_add_unless arch_atomic_fetch_add_unless 127 128#define arch_atomic_read(v) READ_ONCE((v)->counter) 129#define arch_atomic_set(v,i) WRITE_ONCE((v)->counter, (i)) 130 131#include <asm/cmpxchg.h> 132 133#define arch_atomic_xchg(ptr, v) (arch_xchg(&(ptr)->counter, (v))) 134#define arch_atomic_cmpxchg(v, old, new) (arch_cmpxchg(&((v)->counter), (old), (new))) 135 136#endif /* __ASM_OPENRISC_ATOMIC_H */