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

Signed-off-by: Matthew Wilcox <matthew@wil.cx>
---
 arch/parisc/kernel/parisc_ksyms.c |    1 +
 arch/parisc/kernel/semaphore.c    |   26 ++++++++++++++++++++++++++
 include/asm-parisc/semaphore.h    |   15 +++++++++++++++
 3 files changed, 42 insertions(+)

diff --git a/arch/parisc/kernel/semaphore.c b/arch/parisc/kernel/semaphore.c
index ee806bc..8ec7a96 100644
--- a/arch/parisc/kernel/semaphore.c
+++ b/arch/parisc/kernel/semaphore.c
@@ -100,3 +100,29 @@ int __sched __down_interruptible(struct semaphore * sem)
 
 	return ret;
 }
+
+int __sched __down_killable(struct semaphore * sem)
+{
+	DOWN_HEAD
+
+	for(;;) {
+		set_task_state(current, TASK_KILLABLE);
+		/* we can _read_ this without the sentry */
+		if (sem->count != -1)
+			break;
+
+		if (fatal_signal_pending(current)) {
+			ret = -EINTR;
+			break;
+		}
+		schedule();
+	}
+
+	DOWN_TAIL
+
+	if (!ret) {
+		UPDATE_COUNT
+	}
+
+	return ret;
+}
diff --git a/include/asm-parisc/semaphore.h b/include/asm-parisc/semaphore.h
index a16271c..d8d0f1c 100644
--- a/include/asm-parisc/semaphore.h
+++ b/include/asm-parisc/semaphore.h
@@ -76,6 +76,7 @@ static inline int sem_getcount(struct semaphore *sem)
 
 asmlinkage void __down(struct semaphore * sem);
 asmlinkage int  __down_interruptible(struct semaphore * sem);
+asmlinkage int  __down_killable(struct semaphore * sem);
 asmlinkage void __up(struct semaphore * sem);
 
 /* Semaphores can be `tried' from irq context.  So we have to disable
@@ -108,6 +109,20 @@ static inline int down_interruptible(struct semaphore * sem)
 	return ret;
 }
 
+static inline int down_killable(struct semaphore * sem)
+{
+	int ret = 0;
+	might_sleep();
+	spin_lock_irq(&sem->sentry);
+	if (sem->count > 0) {
+		sem->count--;
+	} else {
+		ret = __down_killable(sem);
+	}
+	spin_unlock_irq(&sem->sentry);
+	return ret;
+}
+
 /*
  * down_trylock returns 0 on success, 1 if we failed to get the lock.
  * May not sleep, but must preserve irq state
diff --git a/arch/parisc/kernel/parisc_ksyms.c b/arch/parisc/kernel/parisc_ksyms.c
index 7aca704..b566200 100644
--- a/arch/parisc/kernel/parisc_ksyms.c
+++ b/arch/parisc/kernel/parisc_ksyms.c
@@ -72,6 +72,7 @@ EXPORT_SYMBOL(memset_io);
 #include <asm/semaphore.h>
 EXPORT_SYMBOL(__up);
 EXPORT_SYMBOL(__down_interruptible);
+EXPORT_SYMBOL(__down_killable);
 EXPORT_SYMBOL(__down);
 
 extern void $$divI(void);
-- 
1.5.3.8


