From e92eae1ba9a66da9be574b9dcb0d16957e001476 Mon Sep 17 00:00:00 2001
From: Matthew Wilcox <matthew@wil.cx>
Date: Sun, 27 Jan 2008 22:36:36 -0500
Subject: [PATCH] s390: Implement down_killable

Signed-off-by: Matthew Wilcox <matthew@wil.cx>
---
 arch/s390/kernel/s390_ksyms.c |    1 +
 arch/s390/kernel/semaphore.c  |   23 +++++++++++++++++++++++
 include/asm-s390/semaphore.h  |   11 +++++++++++
 3 files changed, 35 insertions(+), 0 deletions(-)

diff --git a/arch/s390/kernel/s390_ksyms.c b/arch/s390/kernel/s390_ksyms.c
index 7234c73..770191d 100644
--- a/arch/s390/kernel/s390_ksyms.c
+++ b/arch/s390/kernel/s390_ksyms.c
@@ -32,6 +32,7 @@ EXPORT_SYMBOL(_sb_findmap);
 EXPORT_SYMBOL(__up);
 EXPORT_SYMBOL(__down);
 EXPORT_SYMBOL(__down_interruptible);
+EXPORT_SYMBOL(__down_killable);
 
 /*
  * binfmt_elf loader 
diff --git a/arch/s390/kernel/semaphore.c b/arch/s390/kernel/semaphore.c
index 191303f..25800fe 100644
--- a/arch/s390/kernel/semaphore.c
+++ b/arch/s390/kernel/semaphore.c
@@ -106,3 +106,26 @@ int __sched __down_interruptible(struct semaphore * sem)
 	return retval;
 }
 
+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)) {
+			__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;
+}
+
diff --git a/include/asm-s390/semaphore.h b/include/asm-s390/semaphore.h
index 0e7001a..7c7e81f 100644
--- a/include/asm-s390/semaphore.h
+++ b/include/asm-s390/semaphore.h
@@ -52,6 +52,7 @@ static inline void init_MUTEX_LOCKED (struct semaphore *sem)
 
 asmlinkage void __down(struct semaphore * sem);
 asmlinkage int  __down_interruptible(struct semaphore * sem);
+asmlinkage int  __down_killable(struct semaphore * sem);
 asmlinkage int  __down_trylock(struct semaphore * sem);
 asmlinkage void __up(struct semaphore * sem);
 
@@ -72,6 +73,16 @@ static inline int down_interruptible(struct semaphore * sem)
 	return ret;
 }
 
+static inline int down_killable(struct semaphore * sem)
+{
+	int ret = 0;
+
+	might_sleep();
+	if (atomic_dec_return(&sem->count) < 0)
+		ret = __down_killable(sem);
+	return ret;
+}
+
 static inline int down_trylock(struct semaphore * sem)
 {
 	int old_val, new_val;
-- 
1.5.3.8


