|
@@ -33,7 +33,6 @@
|
|
* @v: pointer of type atomic_t
|
|
* @v: pointer of type atomic_t
|
|
*
|
|
*
|
|
* Atomically reads the value of @v. Note that the guaranteed
|
|
* Atomically reads the value of @v. Note that the guaranteed
|
|
- * useful range of an atomic_t is only 24 bits.
|
|
|
|
*/
|
|
*/
|
|
#define atomic_read(v) (ACCESS_ONCE((v)->counter))
|
|
#define atomic_read(v) (ACCESS_ONCE((v)->counter))
|
|
|
|
|
|
@@ -43,102 +42,62 @@
|
|
* @i: required value
|
|
* @i: required value
|
|
*
|
|
*
|
|
* Atomically sets the value of @v to @i. Note that the guaranteed
|
|
* Atomically sets the value of @v to @i. Note that the guaranteed
|
|
- * useful range of an atomic_t is only 24 bits.
|
|
|
|
*/
|
|
*/
|
|
#define atomic_set(v, i) (((v)->counter) = (i))
|
|
#define atomic_set(v, i) (((v)->counter) = (i))
|
|
|
|
|
|
-/**
|
|
|
|
- * atomic_add_return - add integer to atomic variable
|
|
|
|
- * @i: integer value to add
|
|
|
|
- * @v: pointer of type atomic_t
|
|
|
|
- *
|
|
|
|
- * Atomically adds @i to @v and returns the result
|
|
|
|
- * Note that the guaranteed useful range of an atomic_t is only 24 bits.
|
|
|
|
- */
|
|
|
|
-static inline int atomic_add_return(int i, atomic_t *v)
|
|
|
|
-{
|
|
|
|
- int retval;
|
|
|
|
-#ifdef CONFIG_SMP
|
|
|
|
- int status;
|
|
|
|
-
|
|
|
|
- asm volatile(
|
|
|
|
- "1: mov %4,(_AAR,%3) \n"
|
|
|
|
- " mov (_ADR,%3),%1 \n"
|
|
|
|
- " add %5,%1 \n"
|
|
|
|
- " mov %1,(_ADR,%3) \n"
|
|
|
|
- " mov (_ADR,%3),%0 \n" /* flush */
|
|
|
|
- " mov (_ASR,%3),%0 \n"
|
|
|
|
- " or %0,%0 \n"
|
|
|
|
- " bne 1b \n"
|
|
|
|
- : "=&r"(status), "=&r"(retval), "=m"(v->counter)
|
|
|
|
- : "a"(ATOMIC_OPS_BASE_ADDR), "r"(&v->counter), "r"(i)
|
|
|
|
- : "memory", "cc");
|
|
|
|
-
|
|
|
|
-#else
|
|
|
|
- unsigned long flags;
|
|
|
|
|
|
+#define ATOMIC_OP(op) \
|
|
|
|
+static inline void atomic_##op(int i, atomic_t *v) \
|
|
|
|
+{ \
|
|
|
|
+ int retval, status; \
|
|
|
|
+ \
|
|
|
|
+ asm volatile( \
|
|
|
|
+ "1: mov %4,(_AAR,%3) \n" \
|
|
|
|
+ " mov (_ADR,%3),%1 \n" \
|
|
|
|
+ " " #op " %5,%1 \n" \
|
|
|
|
+ " mov %1,(_ADR,%3) \n" \
|
|
|
|
+ " mov (_ADR,%3),%0 \n" /* flush */ \
|
|
|
|
+ " mov (_ASR,%3),%0 \n" \
|
|
|
|
+ " or %0,%0 \n" \
|
|
|
|
+ " bne 1b \n" \
|
|
|
|
+ : "=&r"(status), "=&r"(retval), "=m"(v->counter) \
|
|
|
|
+ : "a"(ATOMIC_OPS_BASE_ADDR), "r"(&v->counter), "r"(i) \
|
|
|
|
+ : "memory", "cc"); \
|
|
|
|
+}
|
|
|
|
|
|
- flags = arch_local_cli_save();
|
|
|
|
- retval = v->counter;
|
|
|
|
- retval += i;
|
|
|
|
- v->counter = retval;
|
|
|
|
- arch_local_irq_restore(flags);
|
|
|
|
-#endif
|
|
|
|
- return retval;
|
|
|
|
|
|
+#define ATOMIC_OP_RETURN(op) \
|
|
|
|
+static inline int atomic_##op##_return(int i, atomic_t *v) \
|
|
|
|
+{ \
|
|
|
|
+ int retval, status; \
|
|
|
|
+ \
|
|
|
|
+ asm volatile( \
|
|
|
|
+ "1: mov %4,(_AAR,%3) \n" \
|
|
|
|
+ " mov (_ADR,%3),%1 \n" \
|
|
|
|
+ " " #op " %5,%1 \n" \
|
|
|
|
+ " mov %1,(_ADR,%3) \n" \
|
|
|
|
+ " mov (_ADR,%3),%0 \n" /* flush */ \
|
|
|
|
+ " mov (_ASR,%3),%0 \n" \
|
|
|
|
+ " or %0,%0 \n" \
|
|
|
|
+ " bne 1b \n" \
|
|
|
|
+ : "=&r"(status), "=&r"(retval), "=m"(v->counter) \
|
|
|
|
+ : "a"(ATOMIC_OPS_BASE_ADDR), "r"(&v->counter), "r"(i) \
|
|
|
|
+ : "memory", "cc"); \
|
|
|
|
+ return retval; \
|
|
}
|
|
}
|
|
|
|
|
|
-/**
|
|
|
|
- * atomic_sub_return - subtract integer from atomic variable
|
|
|
|
- * @i: integer value to subtract
|
|
|
|
- * @v: pointer of type atomic_t
|
|
|
|
- *
|
|
|
|
- * Atomically subtracts @i from @v and returns the result
|
|
|
|
- * Note that the guaranteed useful range of an atomic_t is only 24 bits.
|
|
|
|
- */
|
|
|
|
-static inline int atomic_sub_return(int i, atomic_t *v)
|
|
|
|
-{
|
|
|
|
- int retval;
|
|
|
|
-#ifdef CONFIG_SMP
|
|
|
|
- int status;
|
|
|
|
|
|
+#define ATOMIC_OPS(op) ATOMIC_OP(op) ATOMIC_OP_RETURN(op)
|
|
|
|
|
|
- asm volatile(
|
|
|
|
- "1: mov %4,(_AAR,%3) \n"
|
|
|
|
- " mov (_ADR,%3),%1 \n"
|
|
|
|
- " sub %5,%1 \n"
|
|
|
|
- " mov %1,(_ADR,%3) \n"
|
|
|
|
- " mov (_ADR,%3),%0 \n" /* flush */
|
|
|
|
- " mov (_ASR,%3),%0 \n"
|
|
|
|
- " or %0,%0 \n"
|
|
|
|
- " bne 1b \n"
|
|
|
|
- : "=&r"(status), "=&r"(retval), "=m"(v->counter)
|
|
|
|
- : "a"(ATOMIC_OPS_BASE_ADDR), "r"(&v->counter), "r"(i)
|
|
|
|
- : "memory", "cc");
|
|
|
|
|
|
+ATOMIC_OPS(add)
|
|
|
|
+ATOMIC_OPS(sub)
|
|
|
|
|
|
-#else
|
|
|
|
- unsigned long flags;
|
|
|
|
- flags = arch_local_cli_save();
|
|
|
|
- retval = v->counter;
|
|
|
|
- retval -= i;
|
|
|
|
- v->counter = retval;
|
|
|
|
- arch_local_irq_restore(flags);
|
|
|
|
-#endif
|
|
|
|
- return retval;
|
|
|
|
-}
|
|
|
|
|
|
+#undef ATOMIC_OPS
|
|
|
|
+#undef ATOMIC_OP_RETURN
|
|
|
|
+#undef ATOMIC_OP
|
|
|
|
|
|
static inline int atomic_add_negative(int i, atomic_t *v)
|
|
static inline int atomic_add_negative(int i, atomic_t *v)
|
|
{
|
|
{
|
|
return atomic_add_return(i, v) < 0;
|
|
return atomic_add_return(i, v) < 0;
|
|
}
|
|
}
|
|
|
|
|
|
-static inline void atomic_add(int i, atomic_t *v)
|
|
|
|
-{
|
|
|
|
- atomic_add_return(i, v);
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-static inline void atomic_sub(int i, atomic_t *v)
|
|
|
|
-{
|
|
|
|
- atomic_sub_return(i, v);
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
static inline void atomic_inc(atomic_t *v)
|
|
static inline void atomic_inc(atomic_t *v)
|
|
{
|
|
{
|
|
atomic_add_return(1, v);
|
|
atomic_add_return(1, v);
|