semaphore-helper.h 2.7 KB
Newer Older
L
Linus Torvalds 已提交
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/errno.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