1#ifndef _ALPHA_ATOMIC_H 2#define _ALPHA_ATOMIC_H 3 4/* 5 * Atomic operations that C can't guarantee us. Useful for 6 * resource counting etc... 7 * 8 * But use these as seldom as possible since they are much slower 9 * than regular operations. 10 */ 11 12 13/* 14 * Counter is volatile to make sure gcc doesn't try to be clever 15 * and move things around on us. We need to use _exactly_ the address 16 * the user gave us, not some alias that contains the same information. 17 */ 18typedef struct { volatile int counter; } atomic_t; 19 20#define ATOMIC_INIT(i) ( (atomic_t) { (i) } ) 21 22#define atomic_read(v) ((v)->counter) 23#define atomic_set(v,i) ((v)->counter = (i)) 24 25/* 26 * To get proper branch prediction for the main line, we must branch 27 * forward to code at the end of this object's .text section, then 28 * branch back to restart the operation. 29 */ 30 31static __inline__ void atomic_add(int i, atomic_t * v) 32{ 33 unsigned long temp; 34 __asm__ __volatile__( 35 "1: ldl_l %0,%1\n" 36 " addl %0,%2,%0\n" 37 " stl_c %0,%1\n" 38 " beq %0,2f\n" 39 ".subsection 2\n" 40 "2: br 1b\n" 41 ".previous" 42 :"=&r" (temp), "=m" (v->counter) 43 :"Ir" (i), "m" (v->counter)); 44} 45 46static __inline__ void atomic_sub(int i, atomic_t * v) 47{ 48 unsigned long temp; 49 __asm__ __volatile__( 50 "1: ldl_l %0,%1\n" 51 " subl %0,%2,%0\n" 52 " stl_c %0,%1\n" 53 " beq %0,2f\n" 54 ".subsection 2\n" 55 "2: br 1b\n" 56 ".previous" 57 :"=&r" (temp), "=m" (v->counter) 58 :"Ir" (i), "m" (v->counter)); 59} 60 61/* 62 * Same as above, but return the result value 63 */ 64static __inline__ long atomic_add_return(int i, atomic_t * v) 65{ 66 long temp, result; 67 __asm__ __volatile__( 68 "1: ldl_l %0,%1\n" 69 " addl %0,%3,%2\n" 70 " addl %0,%3,%0\n" 71 " stl_c %0,%1\n" 72 " beq %0,2f\n" 73 " mb\n" 74 ".subsection 2\n" 75 "2: br 1b\n" 76 ".previous" 77 :"=&r" (temp), "=m" (v->counter), "=&r" (result) 78 :"Ir" (i), "m" (v->counter) : "memory"); 79 return result; 80} 81 82static __inline__ long atomic_sub_return(int i, atomic_t * v) 83{ 84 long temp, result; 85 __asm__ __volatile__( 86 "1: ldl_l %0,%1\n" 87 " subl %0,%3,%2\n" 88 " subl %0,%3,%0\n" 89 " stl_c %0,%1\n" 90 " beq %0,2f\n" 91 " mb\n" 92 ".subsection 2\n" 93 "2: br 1b\n" 94 ".previous" 95 :"=&r" (temp), "=m" (v->counter), "=&r" (result) 96 :"Ir" (i), "m" (v->counter) : "memory"); 97 return result; 98} 99 100#define atomic_dec_return(v) atomic_sub_return(1,(v)) 101#define atomic_inc_return(v) atomic_add_return(1,(v)) 102 103#define atomic_sub_and_test(i,v) (atomic_sub_return((i), (v)) == 0) 104#define atomic_dec_and_test(v) (atomic_sub_return(1, (v)) == 0) 105 106#define atomic_inc(v) atomic_add(1,(v)) 107#define atomic_dec(v) atomic_sub(1,(v)) 108 109#define smp_mb__before_atomic_dec() smp_mb() 110#define smp_mb__after_atomic_dec() smp_mb() 111#define smp_mb__before_atomic_inc() smp_mb() 112#define smp_mb__after_atomic_inc() smp_mb() 113 114#endif /* _ALPHA_ATOMIC_H */ 115