1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
|
#ifndef _M68K_SEMAPHORE_HELPER_H
#define _M68K_SEMAPHORE_HELPER_H
/*
* SMP- and interrupt-safe semaphores helper functions.
*
* (C) Copyright 1996 Linus Torvalds
*
* m68k version by Andreas Schwab
*/
#include <linux/config.h>
/*
* These two _must_ execute atomically wrt each other.
*/
static inline void wake_one_more(struct semaphore * sem)
{
atomic_inc(&sem->waking);
}
#ifndef CONFIG_RMW_INSNS
extern spinlock_t semaphore_wake_lock;
#endif
static inline int waking_non_zero(struct semaphore *sem)
{
int ret;
#ifndef CONFIG_RMW_INSNS
unsigned long flags;
spin_lock_irqsave(&semaphore_wake_lock, flags);
ret = 0;
if (atomic_read(&sem->waking) > 0) {
atomic_dec(&sem->waking);
ret = 1;
}
spin_unlock_irqrestore(&semaphore_wake_lock, flags);
#else
int tmp1, tmp2;
__asm__ __volatile__
("1: movel %1,%2\n"
" jle 2f\n"
" subql #1,%2\n"
" casl %1,%2,%3\n"
" jne 1b\n"
" moveq #1,%0\n"
"2:"
: "=d" (ret), "=d" (tmp1), "=d" (tmp2)
: "m" (sem->waking), "0" (0), "1" (sem->waking));
#endif
return ret;
}
/*
* waking_non_zero_interruptible:
* 1 got the lock
* 0 go to sleep
* -EINTR interrupted
*/
static inline int waking_non_zero_interruptible(struct semaphore *sem,
struct task_struct *tsk)
{
int ret;
#ifndef CONFIG_RMW_INSNS
unsigned long flags;
spin_lock_irqsave(&semaphore_wake_lock, flags);
ret = 0;
if (atomic_read(&sem->waking) > 0) {
atomic_dec(&sem->waking);
ret = 1;
} else if (signal_pending(tsk)) {
atomic_inc(&sem->count);
ret = -EINTR;
}
spin_unlock_irqrestore(&semaphore_wake_lock, flags);
#else
int tmp1, tmp2;
__asm__ __volatile__
("1: movel %1,%2\n"
" jle 2f\n"
" subql #1,%2\n"
" casl %1,%2,%3\n"
" jne 1b\n"
" moveq #1,%0\n"
" jra %a4\n"
"2:"
: "=d" (ret), "=d" (tmp1), "=d" (tmp2)
: "m" (sem->waking), "i" (&&next), "0" (0), "1" (sem->waking));
if (signal_pending(tsk)) {
atomic_inc(&sem->count);
ret = -EINTR;
}
next:
#endif
return ret;
}
/*
* waking_non_zero_trylock:
* 1 failed to lock
* 0 got the lock
*/
static inline int waking_non_zero_trylock(struct semaphore *sem)
{
int ret;
#ifndef CONFIG_RMW_INSNS
unsigned long flags;
spin_lock_irqsave(&semaphore_wake_lock, flags);
ret = 1;
if (atomic_read(&sem->waking) > 0) {
atomic_dec(&sem->waking);
ret = 0;
} else
atomic_inc(&sem->count);
spin_unlock_irqrestore(&semaphore_wake_lock, flags);
#else
int tmp1, tmp2;
__asm__ __volatile__
("1: movel %1,%2\n"
" jle 2f\n"
" subql #1,%2\n"
" casl %1,%2,%3\n"
" jne 1b\n"
" moveq #0,%0\n"
"2:"
: "=d" (ret), "=d" (tmp1), "=d" (tmp2)
: "m" (sem->waking), "0" (1), "1" (sem->waking));
if (ret)
atomic_inc(&sem->count);
#endif
return ret;
}
#endif
|