atomic.h (1538B)
1 #ifndef __ATOMIC_H 2 #define __ATOMIC_H 3 4 #include <inttypes.h> 5 6 typedef struct { 7 u32 counter; 8 } uatomic_t; 9 10 #define UATOMIC_INIT(i) { (i) } 11 #define uatomic_read(v) (__uatomic_read(v).counter) 12 #define uatomic_add_return(i, v) (__uatomic_add_return(i, v).counter) 13 14 static inline uatomic_t 15 __uatomic_read(uatomic_t *v) 16 { 17 uatomic_t r; 18 asm volatile ( 19 "1: \n\t" 20 "ldrex %0, [%1] \n\t" 21 "strex v1, %0, [%1] \n\t" 22 "teq v1, #0 \n\t" 23 "bne 1b \n\t" 24 /* '&' guarantees that 'r' variable will have its own 25 * register so GCC will not produce assembly code 26 * like this one: ldrex r5, [r5] */ 27 : "=&r" (r) 28 : "r" (&v->counter) 29 : "v1", "memory", "cc" 30 ); 31 return r; 32 } 33 34 static inline void 35 uatomic_set(uatomic_t *v, u32 i) 36 { 37 asm volatile ( 38 "1: \n\t" 39 "ldrex v1, [%1] \n\t" 40 "strex v1, %0, [%1] \n\t" 41 "teq v1, #0 \n\t" 42 "bne 1b \n\t" 43 : 44 : "r" (i), "r" (&v->counter) 45 : "v1", "memory", "cc" 46 ); 47 } 48 49 static inline void 50 uatomic_add(u32 i, uatomic_t *v) 51 { 52 asm volatile ( 53 "1: \n\t" 54 "ldrex v1, [%1] \n\t" 55 "add v1, v1, %0 \n\t" 56 "strex v2, v1, [%1] \n\t" 57 "teq v2, #0 \n\t" 58 "bne 1b \n\t" 59 : 60 : "r" (i), "r" (&v->counter) 61 : "v1", "v2", "memory", "cc" 62 ); 63 } 64 65 static inline uatomic_t 66 __uatomic_add_return(u32 i, uatomic_t *v) 67 { 68 uatomic_t r; 69 asm volatile ( 70 "1: \n\t" 71 "ldrex %0, [%2] \n\t" 72 "add %0, %0, %1 \n\t" 73 "strex v1, %0, [%2] \n\t" 74 "teq v1, #0 \n\t" 75 "bne 1b \n\t" 76 : "=&r" (r) 77 : "r" (i), "r" (&v->counter) 78 : "v1", "memory", "cc" 79 ); 80 return r; 81 } 82 83 #endif /* __ATOMIC_H */