diff options
| author | Matthew Wilcox <matthew@wil.cx> | 2008-03-07 21:55:58 -0500 | 
|---|---|---|
| committer | Matthew Wilcox <willy@linux.intel.com> | 2008-04-17 10:42:34 -0400 | 
| commit | 64ac24e738823161693bf791f87adc802cf529ff (patch) | |
| tree | 19c0b0cf314d4394ca580c05b86cdf874ce0a167 /arch/alpha | |
| parent | e48b3deee475134585eed03e7afebe4bf9e0dba9 (diff) | |
| download | linux-64ac24e738823161693bf791f87adc802cf529ff.tar.bz2 | |
Generic semaphore implementation
Semaphores are no longer performance-critical, so a generic C
implementation is better for maintainability, debuggability and
extensibility.  Thanks to Peter Zijlstra for fixing the lockdep
warning.  Thanks to Harvey Harrison for pointing out that the
unlikely() was unnecessary.
Signed-off-by: Matthew Wilcox <willy@linux.intel.com>
Acked-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch/alpha')
| -rw-r--r-- | arch/alpha/kernel/Makefile | 2 | ||||
| -rw-r--r-- | arch/alpha/kernel/alpha_ksyms.c | 9 | ||||
| -rw-r--r-- | arch/alpha/kernel/semaphore.c | 224 | 
3 files changed, 1 insertions, 234 deletions
| diff --git a/arch/alpha/kernel/Makefile b/arch/alpha/kernel/Makefile index dccf05245d4d..ac706c1d7ada 100644 --- a/arch/alpha/kernel/Makefile +++ b/arch/alpha/kernel/Makefile @@ -7,7 +7,7 @@ EXTRA_AFLAGS	:= $(KBUILD_CFLAGS)  EXTRA_CFLAGS	:= -Werror -Wno-sign-compare  obj-y    := entry.o traps.o process.o init_task.o osf_sys.o irq.o \ -	    irq_alpha.o signal.o setup.o ptrace.o time.o semaphore.o \ +	    irq_alpha.o signal.o setup.o ptrace.o time.o \  	    alpha_ksyms.o systbls.o err_common.o io.o  obj-$(CONFIG_VGA_HOSE)	+= console.o diff --git a/arch/alpha/kernel/alpha_ksyms.c b/arch/alpha/kernel/alpha_ksyms.c index e9762a33b043..d96e742d4dc2 100644 --- a/arch/alpha/kernel/alpha_ksyms.c +++ b/arch/alpha/kernel/alpha_ksyms.c @@ -77,15 +77,6 @@ EXPORT_SYMBOL(__do_clear_user);  EXPORT_SYMBOL(__strncpy_from_user);  EXPORT_SYMBOL(__strnlen_user); -/* Semaphore helper functions.  */ -EXPORT_SYMBOL(__down_failed); -EXPORT_SYMBOL(__down_failed_interruptible); -EXPORT_SYMBOL(__up_wakeup); -EXPORT_SYMBOL(down); -EXPORT_SYMBOL(down_interruptible); -EXPORT_SYMBOL(down_trylock); -EXPORT_SYMBOL(up); -  /*    * SMP-specific symbols.   */ diff --git a/arch/alpha/kernel/semaphore.c b/arch/alpha/kernel/semaphore.c deleted file mode 100644 index 8d2982aa1b8d..000000000000 --- a/arch/alpha/kernel/semaphore.c +++ /dev/null @@ -1,224 +0,0 @@ -/* - * Alpha semaphore implementation. - * - * (C) Copyright 1996 Linus Torvalds - * (C) Copyright 1999, 2000 Richard Henderson - */ - -#include <linux/errno.h> -#include <linux/sched.h> -#include <linux/init.h> - -/* - * This is basically the PPC semaphore scheme ported to use - * the Alpha ll/sc sequences, so see the PPC code for - * credits. - */ - -/* - * Atomically update sem->count. - * This does the equivalent of the following: - * - *	old_count = sem->count; - *	tmp = MAX(old_count, 0) + incr; - *	sem->count = tmp; - *	return old_count; - */ -static inline int __sem_update_count(struct semaphore *sem, int incr) -{ -	long old_count, tmp = 0; - -	__asm__ __volatile__( -	"1:	ldl_l	%0,%2\n" -	"	cmovgt	%0,%0,%1\n" -	"	addl	%1,%3,%1\n" -	"	stl_c	%1,%2\n" -	"	beq	%1,2f\n" -	"	mb\n" -	".subsection 2\n" -	"2:	br	1b\n" -	".previous" -	: "=&r" (old_count), "=&r" (tmp), "=m" (sem->count) -	: "Ir" (incr), "1" (tmp), "m" (sem->count)); - -	return old_count; -} - -/* - * Perform the "down" function.  Return zero for semaphore acquired, - * return negative for signalled out of the function. - * - * If called from down, the return is ignored and the wait loop is - * not interruptible.  This means that a task waiting on a semaphore - * using "down()" cannot be killed until someone does an "up()" on - * the semaphore. - * - * If called from down_interruptible, the return value gets checked - * upon return.  If the return value is negative then the task continues - * with the negative value in the return register (it can be tested by - * the caller). - * - * Either form may be used in conjunction with "up()". - */ - -void __sched -__down_failed(struct semaphore *sem) -{ -	struct task_struct *tsk = current; -	DECLARE_WAITQUEUE(wait, tsk); - -#ifdef CONFIG_DEBUG_SEMAPHORE -	printk("%s(%d): down failed(%p)\n", -	       tsk->comm, task_pid_nr(tsk), sem); -#endif - -	tsk->state = TASK_UNINTERRUPTIBLE; -	wmb(); -	add_wait_queue_exclusive(&sem->wait, &wait); - -	/* -	 * Try to get the semaphore.  If the count is > 0, then we've -	 * got the semaphore; we decrement count and exit the loop. -	 * If the count is 0 or negative, we set it to -1, indicating -	 * that we are asleep, and then sleep. -	 */ -	while (__sem_update_count(sem, -1) <= 0) { -		schedule(); -		set_task_state(tsk, TASK_UNINTERRUPTIBLE); -	} -	remove_wait_queue(&sem->wait, &wait); -	tsk->state = TASK_RUNNING; - -	/* -	 * If there are any more sleepers, wake one of them up so -	 * that it can either get the semaphore, or set count to -1 -	 * indicating that there are still processes sleeping. -	 */ -	wake_up(&sem->wait); - -#ifdef CONFIG_DEBUG_SEMAPHORE -	printk("%s(%d): down acquired(%p)\n", -	       tsk->comm, task_pid_nr(tsk), sem); -#endif -} - -int __sched -__down_failed_interruptible(struct semaphore *sem) -{ -	struct task_struct *tsk = current; -	DECLARE_WAITQUEUE(wait, tsk); -	long ret = 0; - -#ifdef CONFIG_DEBUG_SEMAPHORE -	printk("%s(%d): down failed(%p)\n", -	       tsk->comm, task_pid_nr(tsk), sem); -#endif - -	tsk->state = TASK_INTERRUPTIBLE; -	wmb(); -	add_wait_queue_exclusive(&sem->wait, &wait); - -	while (__sem_update_count(sem, -1) <= 0) { -		if (signal_pending(current)) { -			/* -			 * A signal is pending - give up trying. -			 * Set sem->count to 0 if it is negative, -			 * since we are no longer sleeping. -			 */ -			__sem_update_count(sem, 0); -			ret = -EINTR; -			break; -		} -		schedule(); -		set_task_state(tsk, TASK_INTERRUPTIBLE); -	} - -	remove_wait_queue(&sem->wait, &wait); -	tsk->state = TASK_RUNNING; -	wake_up(&sem->wait); - -#ifdef CONFIG_DEBUG_SEMAPHORE -	printk("%s(%d): down %s(%p)\n", -	       current->comm, task_pid_nr(current), -	       (ret < 0 ? "interrupted" : "acquired"), sem); -#endif -	return ret; -} - -void -__up_wakeup(struct semaphore *sem) -{ -	/* -	 * Note that we incremented count in up() before we came here, -	 * but that was ineffective since the result was <= 0, and -	 * any negative value of count is equivalent to 0. -	 * This ends up setting count to 1, unless count is now > 0 -	 * (i.e. because some other cpu has called up() in the meantime), -	 * in which case we just increment count. -	 */ -	__sem_update_count(sem, 1); -	wake_up(&sem->wait); -} - -void __sched -down(struct semaphore *sem) -{ -#ifdef WAITQUEUE_DEBUG -	CHECK_MAGIC(sem->__magic); -#endif -#ifdef CONFIG_DEBUG_SEMAPHORE -	printk("%s(%d): down(%p) <count=%d> from %p\n", -	       current->comm, task_pid_nr(current), sem, -	       atomic_read(&sem->count), __builtin_return_address(0)); -#endif -	__down(sem); -} - -int __sched -down_interruptible(struct semaphore *sem) -{ -#ifdef WAITQUEUE_DEBUG -	CHECK_MAGIC(sem->__magic); -#endif -#ifdef CONFIG_DEBUG_SEMAPHORE -	printk("%s(%d): down(%p) <count=%d> from %p\n", -	       current->comm, task_pid_nr(current), sem, -	       atomic_read(&sem->count), __builtin_return_address(0)); -#endif -	return __down_interruptible(sem); -} - -int -down_trylock(struct semaphore *sem) -{ -	int ret; - -#ifdef WAITQUEUE_DEBUG -	CHECK_MAGIC(sem->__magic); -#endif - -	ret = __down_trylock(sem); - -#ifdef CONFIG_DEBUG_SEMAPHORE -	printk("%s(%d): down_trylock %s from %p\n", -	       current->comm, task_pid_nr(current), -	       ret ? "failed" : "acquired", -	       __builtin_return_address(0)); -#endif - -	return ret; -} - -void -up(struct semaphore *sem) -{ -#ifdef WAITQUEUE_DEBUG -	CHECK_MAGIC(sem->__magic); -#endif -#ifdef CONFIG_DEBUG_SEMAPHORE -	printk("%s(%d): up(%p) <count=%d> from %p\n", -	       current->comm, task_pid_nr(current), sem, -	       atomic_read(&sem->count), __builtin_return_address(0)); -#endif -	__up(sem); -} |