diff options
author | Christopher Kenna <cjk@cs.unc.edu> | 2012-05-03 14:27:17 -0400 |
---|---|---|
committer | Christopher Kenna <cjk@cs.unc.edu> | 2012-05-03 14:27:17 -0400 |
commit | e0e02579c34b9920781b3ce3fc9d6d7bcafb4d5b (patch) | |
tree | fb8db7a1214699daf669f0d5a7cf3ee27d8afb17 | |
parent | e6460461137ce256d65696eb88ecbbe4fa017330 (diff) |
Ticket spinlocks for flare based on Bjoern's old code.
-rw-r--r-- | arch/sparc/include/asm/spinlock_64.h | 92 | ||||
-rw-r--r-- | arch/sparc/include/asm/spinlock_types.h | 5 |
2 files changed, 44 insertions, 53 deletions
diff --git a/arch/sparc/include/asm/spinlock_64.h b/arch/sparc/include/asm/spinlock_64.h index 073936a8b275..0415e1867e92 100644 --- a/arch/sparc/include/asm/spinlock_64.h +++ b/arch/sparc/include/asm/spinlock_64.h | |||
@@ -13,82 +13,72 @@ | |||
13 | * and rebuild your kernel. | 13 | * and rebuild your kernel. |
14 | */ | 14 | */ |
15 | 15 | ||
16 | /* Because we play games to save cycles in the non-contention case, we | 16 | #define arch_spin_is_locked(lp) ((lp)->tail != (lp)->head) |
17 | * need to be extra careful about branch targets into the "spinning" | ||
18 | * code. They live in their own section, but the newer V9 branches | ||
19 | * have a shorter range than the traditional 32-bit sparc branch | ||
20 | * variants. The rule is that the branches that go into and out of | ||
21 | * the spinner sections must be pre-V9 branches. | ||
22 | */ | ||
23 | |||
24 | #define arch_spin_is_locked(lp) ((lp)->lock != 0) | ||
25 | 17 | ||
26 | #define arch_spin_unlock_wait(lp) \ | 18 | #define arch_spin_unlock_wait(lp) \ |
27 | do { rmb(); \ | 19 | do { rmb(); \ |
28 | } while((lp)->lock) | 20 | } while((lp)->tail != (lp)->head) |
29 | 21 | ||
30 | static inline void arch_spin_lock(arch_spinlock_t *lock) | 22 | static inline void arch_spin_lock(arch_spinlock_t *lock) |
31 | { | 23 | { |
32 | unsigned long tmp; | 24 | int ticket, tmp; |
33 | 25 | ||
34 | __asm__ __volatile__( | 26 | __asm__ __volatile__( |
35 | "1: ldstub [%1], %0\n" | 27 | "1: lduw [%2], %0 \n" /* read ticket */ |
36 | " brnz,pn %0, 2f\n" | 28 | " add %0, 1, %1 \n" |
37 | " nop\n" | 29 | " cas [%2], %0, %1 \n" |
38 | " .subsection 2\n" | 30 | " cmp %0, %1 \n" |
39 | "2: ldub [%1], %0\n" | 31 | " be,a,pt %%icc, 2f \n" |
40 | " brnz,pt %0, 2b\n" | 32 | " nop \n" |
41 | " nop\n" | 33 | " ba 1b\n" |
42 | " ba,a,pt %%xcc, 1b\n" | 34 | " nop \n" |
43 | " .previous" | 35 | "2: lduw [%3], %1 \n" |
44 | : "=&r" (tmp) | 36 | " cmp %0, %1 \n" |
45 | : "r" (lock) | 37 | " be,a,pt %%icc, 3f \n" |
38 | " nop \n" | ||
39 | " ba 2b\n" | ||
40 | "3: nop" | ||
41 | : "=&r" (ticket), "=&r" (tmp) | ||
42 | : "r" (&lock->tail), "r" (&lock->head) | ||
46 | : "memory"); | 43 | : "memory"); |
47 | } | 44 | } |
48 | 45 | ||
49 | static inline int arch_spin_trylock(arch_spinlock_t *lock) | 46 | static inline int arch_spin_trylock(arch_spinlock_t *lock) |
50 | { | 47 | { |
51 | unsigned long result; | 48 | int tail, head; |
52 | |||
53 | __asm__ __volatile__( | 49 | __asm__ __volatile__( |
54 | " ldstub [%1], %0\n" | 50 | " lduw [%2], %0 \n" /* read tail */ |
55 | : "=r" (result) | 51 | " lduw [%3], %1 \n" /* read head */ |
56 | : "r" (lock) | 52 | " cmp %0, %1 \n" |
53 | " bne,a,pn %%icc, 1f \n" | ||
54 | " nop \n" | ||
55 | " inc %1 \n" | ||
56 | " cas [%2], %0, %1 \n" /* try to inc ticket */ | ||
57 | "1: " | ||
58 | : "=&r" (tail), "=&r" (head) | ||
59 | : "r" (&lock->tail), "r" (&lock->head) | ||
57 | : "memory"); | 60 | : "memory"); |
58 | 61 | ||
59 | return (result == 0UL); | 62 | return (tail == head); |
60 | } | 63 | } |
61 | 64 | ||
62 | static inline void arch_spin_unlock(arch_spinlock_t *lock) | 65 | static inline void arch_spin_unlock(arch_spinlock_t *lock) |
63 | { | 66 | { |
67 | int tmp; | ||
64 | __asm__ __volatile__( | 68 | __asm__ __volatile__( |
65 | " stb %%g0, [%0]" | 69 | " lduw [%1], %0 \n" |
66 | : /* No outputs */ | 70 | " inc %0 \n" |
67 | : "r" (lock) | 71 | " st %0, [%1] \n" |
72 | : "=&r" (tmp) | ||
73 | : "r" (&lock->head) | ||
68 | : "memory"); | 74 | : "memory"); |
69 | } | 75 | } |
70 | 76 | ||
71 | static inline void arch_spin_lock_flags(arch_spinlock_t *lock, unsigned long flags) | 77 | /* We don't handle this yet, but it looks like not re-enabling the interrupts |
72 | { | 78 | * works fine, too. For example, lockdep also does it like this. |
73 | unsigned long tmp1, tmp2; | 79 | */ |
80 | #define arch_spin_lock_flags(l, f) arch_spin_lock(l) | ||
74 | 81 | ||
75 | __asm__ __volatile__( | ||
76 | "1: ldstub [%2], %0\n" | ||
77 | " brnz,pn %0, 2f\n" | ||
78 | " nop\n" | ||
79 | " .subsection 2\n" | ||
80 | "2: rdpr %%pil, %1\n" | ||
81 | " wrpr %3, %%pil\n" | ||
82 | "3: ldub [%2], %0\n" | ||
83 | " brnz,pt %0, 3b\n" | ||
84 | " nop\n" | ||
85 | " ba,pt %%xcc, 1b\n" | ||
86 | " wrpr %1, %%pil\n" | ||
87 | " .previous" | ||
88 | : "=&r" (tmp1), "=&r" (tmp2) | ||
89 | : "r"(lock), "r"(flags) | ||
90 | : "memory"); | ||
91 | } | ||
92 | 82 | ||
93 | /* Multi-reader locks, these are much saner than the 32-bit Sparc ones... */ | 83 | /* Multi-reader locks, these are much saner than the 32-bit Sparc ones... */ |
94 | 84 | ||
diff --git a/arch/sparc/include/asm/spinlock_types.h b/arch/sparc/include/asm/spinlock_types.h index 9c454fdeaad8..49b89fe2ccfc 100644 --- a/arch/sparc/include/asm/spinlock_types.h +++ b/arch/sparc/include/asm/spinlock_types.h | |||
@@ -6,10 +6,11 @@ | |||
6 | #endif | 6 | #endif |
7 | 7 | ||
8 | typedef struct { | 8 | typedef struct { |
9 | volatile unsigned char lock; | 9 | volatile int tail; |
10 | volatile int head; | ||
10 | } arch_spinlock_t; | 11 | } arch_spinlock_t; |
11 | 12 | ||
12 | #define __ARCH_SPIN_LOCK_UNLOCKED { 0 } | 13 | #define __ARCH_SPIN_LOCK_UNLOCKED { 0, 0 } |
13 | 14 | ||
14 | typedef struct { | 15 | typedef struct { |
15 | volatile unsigned int lock; | 16 | volatile unsigned int lock; |