voron

experimental ARM OS
git clone git://git.2f30.org/voron
Log | Files | Refs | README | LICENSE

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 */