diff options
author | Michael Trimarchi <trimarchimichael@yahoo.it> | 2008-11-25 07:37:14 -0500 |
---|---|---|
committer | Paul Mundt <lethal@linux-sh.org> | 2008-12-22 04:42:55 -0500 |
commit | 0c9122323acb0c3410dfbd219cb47f4c2e9305e3 (patch) | |
tree | c5ea7c01289bf07e4ad6b5cdd4e830c9122d8e95 /arch | |
parent | 5c72f303a2b7862dbba79f4176ddc922a440b567 (diff) |
sh: Add SH-4A optimized fastpath mutex implementation.
Add fast mutex path implementation for the SH4A architecture
Signed-off-by: Michael Trimarchi <trimarchimichael@yahoo.it>
Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/sh/include/asm/mutex-llsc.h | 107 | ||||
-rw-r--r-- | arch/sh/include/asm/mutex.h | 5 |
2 files changed, 111 insertions, 1 deletions
diff --git a/arch/sh/include/asm/mutex-llsc.h b/arch/sh/include/asm/mutex-llsc.h new file mode 100644 index 000000000000..7c75af5e734b --- /dev/null +++ b/arch/sh/include/asm/mutex-llsc.h | |||
@@ -0,0 +1,107 @@ | |||
1 | /* | ||
2 | * arch/sh/include/asm/mutex-llsc.h | ||
3 | * | ||
4 | * SH-4A optimized mutex locking primitives | ||
5 | * | ||
6 | * Please look into asm-generic/mutex-xchg.h for a formal definition. | ||
7 | */ | ||
8 | #ifndef __ASM_SH_MUTEX_LLSC_H | ||
9 | #define __ASM_SH_MUTEX_LLSC_H | ||
10 | |||
11 | /* | ||
12 | * Attempting to lock a mutex on SH4A is done like in ARMv6+ architecure. | ||
13 | * with a bastardized atomic decrement (it is not a reliable atomic decrement | ||
14 | * but it satisfies the defined semantics for our purpose, while being | ||
15 | * smaller and faster than a real atomic decrement or atomic swap. | ||
16 | * The idea is to attempt decrementing the lock value only once. If once | ||
17 | * decremented it isn't zero, or if its store-back fails due to a dispute | ||
18 | * on the exclusive store, we simply bail out immediately through the slow | ||
19 | * path where the lock will be reattempted until it succeeds. | ||
20 | */ | ||
21 | static inline void | ||
22 | __mutex_fastpath_lock(atomic_t *count, void (*fail_fn)(atomic_t *)) | ||
23 | { | ||
24 | int __res; | ||
25 | |||
26 | __asm__ __volatile__ ( | ||
27 | "movli.l @%1, %0 \n" | ||
28 | "dt %0 \n" | ||
29 | "movco.l %0, @%1 \n" | ||
30 | : "=&z" (__res) | ||
31 | : "r" (&(count)->counter) | ||
32 | : "t"); | ||
33 | |||
34 | if (unlikely(__res != 0)) | ||
35 | fail_fn(count); | ||
36 | } | ||
37 | |||
38 | static inline int | ||
39 | __mutex_fastpath_lock_retval(atomic_t *count, int (*fail_fn)(atomic_t *)) | ||
40 | { | ||
41 | int __res; | ||
42 | |||
43 | __asm__ __volatile__ ( | ||
44 | "movli.l @%1, %0 \n" | ||
45 | "dt %0 \n" | ||
46 | "movco.l %0, @%1 \n" | ||
47 | : "=&z" (__res) | ||
48 | : "r" (&(count)->counter) | ||
49 | : "t"); | ||
50 | |||
51 | if (unlikely(__res != 0)) | ||
52 | __res = fail_fn(count); | ||
53 | |||
54 | return __res; | ||
55 | } | ||
56 | |||
57 | static inline void | ||
58 | __mutex_fastpath_unlock(atomic_t *count, void (*fail_fn)(atomic_t *)) | ||
59 | { | ||
60 | int __res; | ||
61 | |||
62 | __asm__ __volatile__ ( | ||
63 | "1: movli.l @%1, %0 \n\t" | ||
64 | "add #1, %0 \n\t" | ||
65 | "movco.l %0, @%1 \n\t" | ||
66 | "bf 1b\n\t" | ||
67 | : "=&z" (__res) | ||
68 | : "r" (&(count)->counter) | ||
69 | : "t"); | ||
70 | |||
71 | if (unlikely(__res <= 0)) | ||
72 | fail_fn(count); | ||
73 | } | ||
74 | |||
75 | /* | ||
76 | * If the unlock was done on a contended lock, or if the unlock simply fails | ||
77 | * then the mutex remains locked. | ||
78 | */ | ||
79 | #define __mutex_slowpath_needs_to_unlock() 1 | ||
80 | |||
81 | /* | ||
82 | * For __mutex_fastpath_trylock we do an atomic decrement and check the | ||
83 | * result and put it in the __res variable. | ||
84 | */ | ||
85 | static inline int | ||
86 | __mutex_fastpath_trylock(atomic_t *count, int (*fail_fn)(atomic_t *)) | ||
87 | { | ||
88 | int __res, __orig; | ||
89 | |||
90 | __asm__ __volatile__ ( | ||
91 | "1: movli.l @%2, %0 \n\t" | ||
92 | "dt %0 \n\t" | ||
93 | "movco.l %0,@%2 \n\t" | ||
94 | "bf 1b \n\t" | ||
95 | "cmp/eq #0,%0 \n\t" | ||
96 | "bt 2f \n\t" | ||
97 | "mov #0, %1 \n\t" | ||
98 | "bf 3f \n\t" | ||
99 | "2: mov #1, %1 \n\t" | ||
100 | "3: " | ||
101 | : "=&z" (__orig), "=&r" (__res) | ||
102 | : "r" (&count->counter) | ||
103 | : "t"); | ||
104 | |||
105 | return __res; | ||
106 | } | ||
107 | #endif /* __ASM_SH_MUTEX_LLSC_H */ | ||
diff --git a/arch/sh/include/asm/mutex.h b/arch/sh/include/asm/mutex.h index 458c1f7fbc18..d8e37716a4a0 100644 --- a/arch/sh/include/asm/mutex.h +++ b/arch/sh/include/asm/mutex.h | |||
@@ -5,5 +5,8 @@ | |||
5 | * implementation in place, or pick the atomic_xchg() based generic | 5 | * implementation in place, or pick the atomic_xchg() based generic |
6 | * implementation. (see asm-generic/mutex-xchg.h for details) | 6 | * implementation. (see asm-generic/mutex-xchg.h for details) |
7 | */ | 7 | */ |
8 | 8 | #if defined(CONFIG_CPU_SH4A) | |
9 | #include <asm/mutex-llsc.h> | ||
10 | #else | ||
9 | #include <asm-generic/mutex-dec.h> | 11 | #include <asm-generic/mutex-dec.h> |
12 | #endif | ||