From ff28d8ce709b1137516ff67a7c398ccf3c93ab5e Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Wed, 20 Oct 1999 21:09:19 +0000 Subject: Rewrite of semaphores for MIPS64. --- include/asm-mips64/semaphore-helper.h | 116 ++++++++++++++++++++-------------- 1 file changed, 70 insertions(+), 46 deletions(-) (limited to 'include/asm-mips64/semaphore-helper.h') diff --git a/include/asm-mips64/semaphore-helper.h b/include/asm-mips64/semaphore-helper.h index d685b89e6..908d16c4b 100644 --- a/include/asm-mips64/semaphore-helper.h +++ b/include/asm-mips64/semaphore-helper.h @@ -5,6 +5,7 @@ * (C) Copyright 1996 Linus Torvalds * (C) Copyright 1999 Andrea Arcangeli * (C) Copyright 1999 Ralf Baechle + * (C) Copyright 1999 Silicon Graphics, Inc. */ #ifndef _ASM_SEMAPHORE_HELPER_H #define _ASM_SEMAPHORE_HELPER_H @@ -23,11 +24,11 @@ waking_non_zero(struct semaphore *sem) int ret, tmp; __asm__ __volatile__( - "1:\tll\t%1,%2\n\t" - "blez\t%1,2f\n\t" - "subu\t%0,%1,1\n\t" - "sc\t%0,%2\n\t" - "beqz\t%0,1b\n\t" + "1:\tll\t%1, %2\n\t" + "blez\t%1, 2f\n\t" + "subu\t%0, %1, 1\n\t" + "sc\t%0, %2\n\t" + "beqz\t%0, 1b\n\t" "2:" ".text" : "=r"(ret), "=r"(tmp), "=m"(__atomic_fool_gcc(&sem->waking)) @@ -48,78 +49,101 @@ waking_non_zero(struct semaphore *sem) * * This is accomplished by doing a 64-bit ll/sc on the 2 32-bit words. * - * This is crazy. Normally it stricly forbidden to use 64-bit operation - * in the 32-bit MIPS kernel. In this case it's however ok because if an - * interrupt has destroyed the upper half of registers sc will fail. + * Pseudocode: + * + * If(sem->waking > 0) { + * Decrement(sem->waking) + * Return(SUCCESS) + * } else If(segnal_pending(tsk)) { + * Increment(sem->count) + * Return(-EINTR) + * } else { + * Return(SLEEP) + * } */ + static inline int waking_non_zero_interruptible(struct semaphore *sem, struct task_struct *tsk) { long ret, tmp; #ifdef __MIPSEB__ + __asm__ __volatile__(" - .set mips3 .set push .set noat -0: lld %1,%2 - li %0,0 +0: lld %1, %2 + li %0, 0 + sll $1, %1, 0 + blez $1, 1f + daddiu %1, %1, -1 + li %0, 1 + b 2f +1: + beqz %3, 2f + li %0, %4 + dli $1, 0x0000000100000000 + daddu %1, %1, $1 +2: + scd %1, %2 + beqz %1, 0b + .set pop" + : "=&r"(ret), "=&r"(tmp), "=m"(*sem) + : "r"(signal_pending(tsk)), "i"(-EINTR)); + +#elif defined(__MIPSEL__) - bltz %1, 1f - dli $1, 0xffffffff00000000 - daddu %1, $1 + __asm__ __volatile__(" + .set push + .set noat +0: + lld %1, %2 + li %0, 0 + blez %1, 1f + dli $1, 0x0000000100000000 + dsubu %1, %1, $1 li %0, 1 b 2f 1: - - beqz %3, 1f - addiu $1, %1, 1 + beqz %3, 2f + li %0, %4 + /* + * It would be nice to assume that sem->count + * is != -1, but we will guard against that case + */ + daddiu $1, %1, 1 dsll32 $1, $1, 0 dsrl32 $1, $1, 0 dsrl32 %1, %1, 0 dsll32 %1, %1, 0 - or %1, $1 - li %0, %4 - b 2f -1: - scd %1, %2 + or %1, %1, $1 2: - beqz %1,0b - .set pop - .set mips0" + scd %1, %2 + beqz %1, 0b + .set pop" : "=&r"(ret), "=&r"(tmp), "=m"(*sem) : "r"(signal_pending(tsk)), "i"(-EINTR)); -#endif -#ifdef __MIPSEL__ -#error "FIXME: waking_non_zero_interruptible doesn't support little endian machines yet." +#else +#error "MIPS but neither __MIPSEL__ nor __MIPSEB__?" #endif return ret; } /* - * waking_non_zero_trylock: - * 1 failed to lock - * 0 got the lock - * - * XXX SMP ALERT + * waking_non_zero_trylock is unused. we do everything in + * down_trylock and let non-ll/sc hosts bounce around. */ -#ifdef __SMP__ -#error FIXME, waking_non_zero_trylock is broken for SMP. -#endif -static inline int waking_non_zero_trylock(struct semaphore *sem) -{ - int ret = 1; - if (atomic_read(&sem->waking) <= 0) - atomic_inc(&sem->count); - else { - atomic_dec(&sem->waking); - ret = 0; - } +static inline int +waking_non_zero_trylock(struct semaphore *sem) +{ +#if WAITQUEUE_DEBUG + CHECK_MAGIC(sem->__magic); +#endif - return ret; + return 0; } #endif /* _ASM_SEMAPHORE_HELPER_H */ -- cgit v1.2.3