From aee77f6753c14f515c61dcc86164f79783e77f32 Mon Sep 17 00:00:00 2001
From: Matthew Wilcox <matthew@wil.cx>
Date: Sun, 27 Jan 2008 19:56:43 -0500
Subject: [PATCH] powerpc: Implement down_killable

Signed-off-by: Matthew Wilcox <matthew@wil.cx>
---
 arch/powerpc/kernel/semaphore.c |   31 +++++++++++++++++++++++++++++++
 include/asm-powerpc/semaphore.h |   12 ++++++++++++
 2 files changed, 43 insertions(+), 0 deletions(-)

diff --git a/arch/powerpc/kernel/semaphore.c b/arch/powerpc/kernel/semaphore.c
index 2f8c3c9..efb6685 100644
--- a/arch/powerpc/kernel/semaphore.c
+++ b/arch/powerpc/kernel/semaphore.c
@@ -133,3 +133,34 @@ int __sched __down_interruptible(struct semaphore * sem)
 	return retval;
 }
 EXPORT_SYMBOL(__down_interruptible);
+
+int __sched __down_killable(struct semaphore * sem)
+{
+	int retval = 0;
+	struct task_struct *tsk = current;
+	DECLARE_WAITQUEUE(wait, tsk);
+
+	__set_task_state(tsk, TASK_KILLABLE);
+	add_wait_queue_exclusive(&sem->wait, &wait);
+
+	while (__sem_update_count(sem, -1) <= 0) {
+		if (fatal_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);
+			retval = -EINTR;
+			break;
+		}
+		schedule();
+		set_task_state(tsk, TASK_KILLABLE);
+	}
+	remove_wait_queue(&sem->wait, &wait);
+	__set_task_state(tsk, TASK_RUNNING);
+
+	wake_up(&sem->wait);
+	return retval;
+}
+EXPORT_SYMBOL(__down_killable);
diff --git a/include/asm-powerpc/semaphore.h b/include/asm-powerpc/semaphore.h
index 48dd32e..f2aecc3 100644
--- a/include/asm-powerpc/semaphore.h
+++ b/include/asm-powerpc/semaphore.h
@@ -54,6 +54,7 @@ static inline void init_MUTEX_LOCKED (struct semaphore *sem)
 
 extern void __down(struct semaphore * sem);
 extern int  __down_interruptible(struct semaphore * sem);
+extern int  __down_killable(struct semaphore * sem);
 extern void __up(struct semaphore * sem);
 
 static inline void down(struct semaphore * sem)
@@ -78,6 +79,17 @@ static inline int down_interruptible(struct semaphore * sem)
 	return ret;
 }
 
+static inline int down_killable(struct semaphore * sem)
+{
+	int ret = 0;
+
+	might_sleep();
+
+	if (unlikely(atomic_dec_return(&sem->count) < 0))
+		ret = __down_killable(sem);
+	return ret;
+}
+
 static inline int down_trylock(struct semaphore * sem)
 {
 	return atomic_dec_if_positive(&sem->count) < 0;
-- 
1.5.3.8


