|
@@ -34,6 +34,7 @@
|
|
|
|
|
|
static noinline void __down(struct semaphore *sem);
|
|
|
static noinline int __down_interruptible(struct semaphore *sem);
|
|
|
+static noinline int __down_killable(struct semaphore *sem);
|
|
|
static noinline void __up(struct semaphore *sem);
|
|
|
|
|
|
void down(struct semaphore *sem)
|
|
@@ -61,6 +62,20 @@ int down_interruptible(struct semaphore *sem)
|
|
|
}
|
|
|
EXPORT_SYMBOL(down_interruptible);
|
|
|
|
|
|
+int down_killable(struct semaphore *sem)
|
|
|
+{
|
|
|
+ unsigned long flags;
|
|
|
+ int result = 0;
|
|
|
+
|
|
|
+ spin_lock_irqsave(&sem->lock, flags);
|
|
|
+ if (unlikely(sem->count-- <= 0))
|
|
|
+ result = __down_killable(sem);
|
|
|
+ spin_unlock_irqrestore(&sem->lock, flags);
|
|
|
+
|
|
|
+ return result;
|
|
|
+}
|
|
|
+EXPORT_SYMBOL(down_killable);
|
|
|
+
|
|
|
/**
|
|
|
* down_trylock - try to acquire the semaphore, without waiting
|
|
|
* @sem: the semaphore to be acquired
|
|
@@ -143,6 +158,8 @@ static inline int __sched __down_common(struct semaphore *sem, long state)
|
|
|
for (;;) {
|
|
|
if (state == TASK_INTERRUPTIBLE && signal_pending(task))
|
|
|
goto interrupted;
|
|
|
+ if (state == TASK_KILLABLE && fatal_signal_pending(task))
|
|
|
+ goto interrupted;
|
|
|
__set_task_state(task, state);
|
|
|
spin_unlock_irq(&sem->lock);
|
|
|
schedule();
|
|
@@ -178,6 +195,11 @@ static noinline int __sched __down_interruptible(struct semaphore *sem)
|
|
|
return __down_common(sem, TASK_INTERRUPTIBLE);
|
|
|
}
|
|
|
|
|
|
+static noinline int __sched __down_killable(struct semaphore *sem)
|
|
|
+{
|
|
|
+ return __down_common(sem, TASK_KILLABLE);
|
|
|
+}
|
|
|
+
|
|
|
static noinline void __sched __up(struct semaphore *sem)
|
|
|
{
|
|
|
if (unlikely(list_empty(&sem->wait_list)))
|