Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 182144
b: refs/heads/master
c: 500c2e1
h: refs/heads/master
v: v3
  • Loading branch information
David Daney authored and Ralf Baechle committed Feb 27, 2010
1 parent 4459327 commit 18b1367
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 82 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: e275ed5ee94b358964a0dae1c8b49f0bff260b60
refs/heads/master: 500c2e1fdbcc2b273bd4c695a9b8ac8196f61614
6 changes: 6 additions & 0 deletions trunk/arch/mips/include/asm/barrier.h
Original file line number Diff line number Diff line change
Expand Up @@ -168,8 +168,14 @@

#ifdef CONFIG_CPU_CAVIUM_OCTEON
#define smp_mb__before_llsc() smp_wmb()
/* Cause previous writes to become visible on all CPUs as soon as possible */
#define nudge_writes() __asm__ __volatile__(".set push\n\t" \
".set arch=octeon\n\t" \
"syncw\n\t" \
".set pop" : : : "memory")
#else
#define smp_mb__before_llsc() smp_llsc_mb()
#define nudge_writes() mb()
#endif

#endif /* __ASM_BARRIER_H */
118 changes: 43 additions & 75 deletions trunk/arch/mips/include/asm/spinlock.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,9 @@

static inline int arch_spin_is_locked(arch_spinlock_t *lock)
{
unsigned int counters = ACCESS_ONCE(lock->lock);
u32 counters = ACCESS_ONCE(lock->lock);

return ((counters >> 14) ^ counters) & 0x1fff;
return ((counters >> 16) ^ counters) & 0xffff;
}

#define arch_spin_lock_flags(lock, flags) arch_spin_lock(lock)
Expand All @@ -47,148 +47,116 @@ static inline int arch_spin_is_locked(arch_spinlock_t *lock)

static inline int arch_spin_is_contended(arch_spinlock_t *lock)
{
unsigned int counters = ACCESS_ONCE(lock->lock);
u32 counters = ACCESS_ONCE(lock->lock);

return (((counters >> 14) - counters) & 0x1fff) > 1;
return (((counters >> 16) - counters) & 0xffff) > 1;
}
#define arch_spin_is_contended arch_spin_is_contended

static inline void arch_spin_lock(arch_spinlock_t *lock)
{
int my_ticket;
int tmp;
int inc = 0x10000;

if (R10000_LLSC_WAR) {
__asm__ __volatile__ (
" .set push # arch_spin_lock \n"
" .set noreorder \n"
" \n"
"1: ll %[ticket], %[ticket_ptr] \n"
" addiu %[my_ticket], %[ticket], 0x4000 \n"
" addu %[my_ticket], %[ticket], %[inc] \n"
" sc %[my_ticket], %[ticket_ptr] \n"
" beqzl %[my_ticket], 1b \n"
" nop \n"
" srl %[my_ticket], %[ticket], 14 \n"
" andi %[my_ticket], %[my_ticket], 0x1fff \n"
" andi %[ticket], %[ticket], 0x1fff \n"
" srl %[my_ticket], %[ticket], 16 \n"
" andi %[ticket], %[ticket], 0xffff \n"
" andi %[my_ticket], %[my_ticket], 0xffff \n"
" bne %[ticket], %[my_ticket], 4f \n"
" subu %[ticket], %[my_ticket], %[ticket] \n"
"2: \n"
" .subsection 2 \n"
"4: andi %[ticket], %[ticket], 0x1fff \n"
"4: andi %[ticket], %[ticket], 0xffff \n"
" sll %[ticket], 5 \n"
" \n"
"6: bnez %[ticket], 6b \n"
" subu %[ticket], 1 \n"
" \n"
" lw %[ticket], %[ticket_ptr] \n"
" andi %[ticket], %[ticket], 0x1fff \n"
" lhu %[ticket], %[serving_now_ptr] \n"
" beq %[ticket], %[my_ticket], 2b \n"
" subu %[ticket], %[my_ticket], %[ticket] \n"
" b 4b \n"
" subu %[ticket], %[ticket], 1 \n"
" .previous \n"
" .set pop \n"
: [ticket_ptr] "+m" (lock->lock),
[serving_now_ptr] "+m" (lock->h.serving_now),
[ticket] "=&r" (tmp),
[my_ticket] "=&r" (my_ticket));
[my_ticket] "=&r" (my_ticket)
: [inc] "r" (inc));
} else {
__asm__ __volatile__ (
" .set push # arch_spin_lock \n"
" .set noreorder \n"
" \n"
" ll %[ticket], %[ticket_ptr] \n"
"1: addiu %[my_ticket], %[ticket], 0x4000 \n"
"1: ll %[ticket], %[ticket_ptr] \n"
" addu %[my_ticket], %[ticket], %[inc] \n"
" sc %[my_ticket], %[ticket_ptr] \n"
" beqz %[my_ticket], 3f \n"
" nop \n"
" srl %[my_ticket], %[ticket], 14 \n"
" andi %[my_ticket], %[my_ticket], 0x1fff \n"
" andi %[ticket], %[ticket], 0x1fff \n"
" beqz %[my_ticket], 1b \n"
" srl %[my_ticket], %[ticket], 16 \n"
" andi %[ticket], %[ticket], 0xffff \n"
" andi %[my_ticket], %[my_ticket], 0xffff \n"
" bne %[ticket], %[my_ticket], 4f \n"
" subu %[ticket], %[my_ticket], %[ticket] \n"
"2: \n"
" .subsection 2 \n"
"3: b 1b \n"
" ll %[ticket], %[ticket_ptr] \n"
" \n"
"4: andi %[ticket], %[ticket], 0x1fff \n"
" sll %[ticket], 5 \n"
" \n"
"6: bnez %[ticket], 6b \n"
" subu %[ticket], 1 \n"
" \n"
" lw %[ticket], %[ticket_ptr] \n"
" andi %[ticket], %[ticket], 0x1fff \n"
" lhu %[ticket], %[serving_now_ptr] \n"
" beq %[ticket], %[my_ticket], 2b \n"
" subu %[ticket], %[my_ticket], %[ticket] \n"
" b 4b \n"
" subu %[ticket], %[ticket], 1 \n"
" .previous \n"
" .set pop \n"
: [ticket_ptr] "+m" (lock->lock),
[serving_now_ptr] "+m" (lock->h.serving_now),
[ticket] "=&r" (tmp),
[my_ticket] "=&r" (my_ticket));
[my_ticket] "=&r" (my_ticket)
: [inc] "r" (inc));
}

smp_llsc_mb();
}

static inline void arch_spin_unlock(arch_spinlock_t *lock)
{
int tmp;

smp_mb__before_llsc();

if (R10000_LLSC_WAR) {
__asm__ __volatile__ (
" # arch_spin_unlock \n"
"1: ll %[ticket], %[ticket_ptr] \n"
" addiu %[ticket], %[ticket], 1 \n"
" ori %[ticket], %[ticket], 0x2000 \n"
" xori %[ticket], %[ticket], 0x2000 \n"
" sc %[ticket], %[ticket_ptr] \n"
" beqzl %[ticket], 1b \n"
: [ticket_ptr] "+m" (lock->lock),
[ticket] "=&r" (tmp));
} else {
__asm__ __volatile__ (
" .set push # arch_spin_unlock \n"
" .set noreorder \n"
" \n"
" ll %[ticket], %[ticket_ptr] \n"
"1: addiu %[ticket], %[ticket], 1 \n"
" ori %[ticket], %[ticket], 0x2000 \n"
" xori %[ticket], %[ticket], 0x2000 \n"
" sc %[ticket], %[ticket_ptr] \n"
" beqz %[ticket], 2f \n"
" nop \n"
" \n"
" .subsection 2 \n"
"2: b 1b \n"
" ll %[ticket], %[ticket_ptr] \n"
" .previous \n"
" .set pop \n"
: [ticket_ptr] "+m" (lock->lock),
[ticket] "=&r" (tmp));
}
unsigned int serving_now = lock->h.serving_now + 1;
wmb();
lock->h.serving_now = (u16)serving_now;
nudge_writes();
}

static inline unsigned int arch_spin_trylock(arch_spinlock_t *lock)
{
int tmp, tmp2, tmp3;
int inc = 0x10000;

if (R10000_LLSC_WAR) {
__asm__ __volatile__ (
" .set push # arch_spin_trylock \n"
" .set noreorder \n"
" \n"
"1: ll %[ticket], %[ticket_ptr] \n"
" srl %[my_ticket], %[ticket], 14 \n"
" andi %[my_ticket], %[my_ticket], 0x1fff \n"
" andi %[now_serving], %[ticket], 0x1fff \n"
" srl %[my_ticket], %[ticket], 16 \n"
" andi %[my_ticket], %[my_ticket], 0xffff \n"
" andi %[now_serving], %[ticket], 0xffff \n"
" bne %[my_ticket], %[now_serving], 3f \n"
" addiu %[ticket], %[ticket], 0x4000 \n"
" addu %[ticket], %[ticket], %[inc] \n"
" sc %[ticket], %[ticket_ptr] \n"
" beqzl %[ticket], 1b \n"
" li %[ticket], 1 \n"
Expand All @@ -201,33 +169,33 @@ static inline unsigned int arch_spin_trylock(arch_spinlock_t *lock)
: [ticket_ptr] "+m" (lock->lock),
[ticket] "=&r" (tmp),
[my_ticket] "=&r" (tmp2),
[now_serving] "=&r" (tmp3));
[now_serving] "=&r" (tmp3)
: [inc] "r" (inc));
} else {
__asm__ __volatile__ (
" .set push # arch_spin_trylock \n"
" .set noreorder \n"
" \n"
" ll %[ticket], %[ticket_ptr] \n"
"1: srl %[my_ticket], %[ticket], 14 \n"
" andi %[my_ticket], %[my_ticket], 0x1fff \n"
" andi %[now_serving], %[ticket], 0x1fff \n"
"1: ll %[ticket], %[ticket_ptr] \n"
" srl %[my_ticket], %[ticket], 16 \n"
" andi %[my_ticket], %[my_ticket], 0xffff \n"
" andi %[now_serving], %[ticket], 0xffff \n"
" bne %[my_ticket], %[now_serving], 3f \n"
" addiu %[ticket], %[ticket], 0x4000 \n"
" addu %[ticket], %[ticket], %[inc] \n"
" sc %[ticket], %[ticket_ptr] \n"
" beqz %[ticket], 4f \n"
" beqz %[ticket], 1b \n"
" li %[ticket], 1 \n"
"2: \n"
" .subsection 2 \n"
"3: b 2b \n"
" li %[ticket], 0 \n"
"4: b 1b \n"
" ll %[ticket], %[ticket_ptr] \n"
" .previous \n"
" .set pop \n"
: [ticket_ptr] "+m" (lock->lock),
[ticket] "=&r" (tmp),
[my_ticket] "=&r" (tmp2),
[now_serving] "=&r" (tmp3));
[now_serving] "=&r" (tmp3)
: [inc] "r" (inc));
}

smp_llsc_mb();
Expand Down
24 changes: 18 additions & 6 deletions trunk/arch/mips/include/asm/spinlock_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,28 @@
# error "please don't include this file directly"
#endif

typedef struct {
#include <linux/types.h>

#include <asm/byteorder.h>

typedef union {
/*
* bits 0..13: serving_now
* bits 14 : junk data
* bits 15..28: ticket
* bits 0..15 : serving_now
* bits 16..31 : ticket
*/
unsigned int lock;
u32 lock;
struct {
#ifdef __BIG_ENDIAN
u16 ticket;
u16 serving_now;
#else
u16 serving_now;
u16 ticket;
#endif
} h;
} arch_spinlock_t;

#define __ARCH_SPIN_LOCK_UNLOCKED { 0 }
#define __ARCH_SPIN_LOCK_UNLOCKED { .lock = 0 }

typedef struct {
volatile unsigned int lock;
Expand Down

0 comments on commit 18b1367

Please sign in to comment.