Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
mutex-xchg.h
Go to the documentation of this file.
1 /*
2  * include/asm-generic/mutex-xchg.h
3  *
4  * Generic implementation of the mutex fastpath, based on xchg().
5  *
6  * NOTE: An xchg based implementation might be less optimal than an atomic
7  * decrement/increment based implementation. If your architecture
8  * has a reasonable atomic dec/inc then you should probably use
9  * asm-generic/mutex-dec.h instead, or you could open-code an
10  * optimized version in asm/mutex.h.
11  */
12 #ifndef _ASM_GENERIC_MUTEX_XCHG_H
13 #define _ASM_GENERIC_MUTEX_XCHG_H
14 
25 static inline void
26 __mutex_fastpath_lock(atomic_t *count, void (*fail_fn)(atomic_t *))
27 {
28  if (unlikely(atomic_xchg(count, 0) != 1))
29  /*
30  * We failed to acquire the lock, so mark it contended
31  * to ensure that any waiting tasks are woken up by the
32  * unlock slow path.
33  */
34  if (likely(atomic_xchg(count, -1) != 1))
35  fail_fn(count);
36 }
37 
48 static inline int
49 __mutex_fastpath_lock_retval(atomic_t *count, int (*fail_fn)(atomic_t *))
50 {
51  if (unlikely(atomic_xchg(count, 0) != 1))
52  if (likely(atomic_xchg(count, -1) != 1))
53  return fail_fn(count);
54  return 0;
55 }
56 
69 static inline void
70 __mutex_fastpath_unlock(atomic_t *count, void (*fail_fn)(atomic_t *))
71 {
72  if (unlikely(atomic_xchg(count, 1) != 0))
73  fail_fn(count);
74 }
75 
76 #define __mutex_slowpath_needs_to_unlock() 0
77 
93 static inline int
94 __mutex_fastpath_trylock(atomic_t *count, int (*fail_fn)(atomic_t *))
95 {
96  int prev = atomic_xchg(count, 0);
97 
98  if (unlikely(prev < 0)) {
99  /*
100  * The lock was marked contended so we must restore that
101  * state. If while doing so we get back a prev value of 1
102  * then we just own it.
103  *
104  * [ In the rare case of the mutex going to 1, to 0, to -1
105  * and then back to 0 in this few-instructions window,
106  * this has the potential to trigger the slowpath for the
107  * owner's unlock path needlessly, but that's not a problem
108  * in practice. ]
109  */
110  prev = atomic_xchg(count, prev);
111  if (prev < 0)
112  prev = 0;
113  }
114 
115  return prev;
116 }
117 
118 #endif