2 * arch/arm/include/asm/mutex.h
4 * ARM optimized mutex locking primitives
6 * Please look into asm-generic/mutex-xchg.h for a formal definition.
11 #if __LINUX_ARM_ARCH__ < 6
12 /* On pre-ARMv6 hardware the swp based implementation is the most efficient. */
13 # include <asm-generic/mutex-xchg.h>
17 * Attempting to lock a mutex on ARMv6+ can be done with a bastardized
18 * atomic decrement (it is not a reliable atomic decrement but it satisfies
19 * the defined semantics for our purpose, while being smaller and faster
20 * than a real atomic decrement or atomic swap. The idea is to attempt
21 * decrementing the lock value only once. If once decremented it isn't zero,
22 * or if its store-back fails due to a dispute on the exclusive store, we
23 * simply bail out immediately through the slow path where the lock will be
24 * reattempted until it succeeds.
27 __mutex_fastpath_lock(atomic_t
*count
, void (*fail_fn
)(atomic_t
*))
37 : "=&r" (__res
), "=&r" (__ex_flag
)
38 : "r" (&(count
)->counter
)
42 if (unlikely(__res
!= 0))
47 __mutex_fastpath_lock_retval(atomic_t
*count
, int (*fail_fn
)(atomic_t
*))
57 : "=&r" (__res
), "=&r" (__ex_flag
)
58 : "r" (&(count
)->counter
)
62 if (unlikely(__res
!= 0))
63 __res
= fail_fn(count
);
68 * Same trick is used for the unlock fast path. However the original value,
69 * rather than the result, is used to test for success in order to have
70 * better generated assembly.
73 __mutex_fastpath_unlock(atomic_t
*count
, void (*fail_fn
)(atomic_t
*))
75 int __ex_flag
, __res
, __orig
;
83 : "=&r" (__orig
), "=&r" (__res
), "=&r" (__ex_flag
)
84 : "r" (&(count
)->counter
)
88 if (unlikely(__orig
!= 0))
93 * If the unlock was done on a contended lock, or if the unlock simply fails
94 * then the mutex remains locked.
96 #define __mutex_slowpath_needs_to_unlock() 1
99 * For __mutex_fastpath_trylock we use another construct which could be
100 * described as a "single value cmpxchg".
102 * This provides the needed trylock semantics like cmpxchg would, but it is
103 * lighter and less generic than a true cmpxchg implementation.
106 __mutex_fastpath_trylock(atomic_t
*count
, int (*fail_fn
)(atomic_t
*))
108 int __ex_flag
, __res
, __orig
;
112 "1: ldrex %0, [%3] \n\t"
113 "subs %1, %0, #1 \n\t"
114 "strexeq %2, %1, [%3] \n\t"
119 : "=&r" (__orig
), "=&r" (__res
), "=&r" (__ex_flag
)
120 : "r" (&count
->counter
)