- count = atomic_dec_return(&sem->count);
- if (unlikely(count < 0))
- return __down_failed_interruptible(sem);
-
- return 0;
-}
-
-#ifdef CONFIG_CPU_HAS_LLDSCD
-
-/*
- * down_trylock returns 0 on success, 1 if we failed to get the lock.
- *
- * We must manipulate count and waking simultaneously and atomically.
- * Here, we do this by using lld/scd on the pair of 32-bit words.
- *
- * Pseudocode:
- *
- * Decrement(sem->count)
- * If(sem->count >=0) {
- * Return(SUCCESS) // resource is free
- * } else {
- * If(sem->waking <= 0) { // if no wakeup pending
- * Increment(sem->count) // undo decrement
- * Return(FAILURE)
- * } else {
- * Decrement(sem->waking) // otherwise "steal" wakeup
- * Return(SUCCESS)
- * }
- * }
- */
-static inline int down_trylock(struct semaphore * sem)
-{
- long ret, tmp, tmp2, sub;
-
-#if WAITQUEUE_DEBUG
- CHECK_MAGIC(sem->__magic);
-#endif
-
- __asm__ __volatile__(
- " .set mips3 # down_trylock \n"
- "0: lld %1, %4 \n"
- " dli %3, 0x0000000100000000 # count -= 1 \n"
- " dsubu %1, %3 \n"
- " li %0, 0 # ret = 0 \n"
- " bgez %1, 2f # if count >= 0 \n"
- " sll %2, %1, 0 # extract waking \n"
- " blez %2, 1f # if waking < 0 -> 1f \n"
- " daddiu %1, %1, -1 # waking -= 1 \n"
- " b 2f \n"
- "1: daddu %1, %1, %3 # count += 1 \n"
- " li %0, 1 # ret = 1 \n"
- "2: scd %1, %4 \n"
- " beqz %1, 0b \n"
- " sync \n"
- " .set mips0 \n"
- : "=&r"(ret), "=&r"(tmp), "=&r"(tmp2), "=&r"(sub)
- : "m"(*sem)
- : "memory");