aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/semaphore.h6
-rw-r--r--kernel/semaphore.c22
2 files changed, 28 insertions, 0 deletions
diff --git a/include/linux/semaphore.h b/include/linux/semaphore.h
index b3c691b089b2..88f2a28cc0f1 100644
--- a/include/linux/semaphore.h
+++ b/include/linux/semaphore.h
@@ -62,6 +62,12 @@ extern void down(struct semaphore *sem);
62extern int __must_check down_interruptible(struct semaphore *sem); 62extern int __must_check down_interruptible(struct semaphore *sem);
63 63
64/* 64/*
65 * As down_interruptible(), except the sleep may only be interrupted by
66 * signals which are fatal to this process.
67 */
68extern int __must_check down_killable(struct semaphore *sem);
69
70/*
65 * As down(), except this function will not sleep. It will return 0 if it 71 * As down(), except this function will not sleep. It will return 0 if it
66 * acquired the semaphore and 1 if the semaphore was contended. This 72 * acquired the semaphore and 1 if the semaphore was contended. This
67 * function may be called from any context, including interrupt and softirq. 73 * function may be called from any context, including interrupt and softirq.
diff --git a/kernel/semaphore.c b/kernel/semaphore.c
index d5a72702f261..2da2aed950f3 100644
--- a/kernel/semaphore.c
+++ b/kernel/semaphore.c
@@ -34,6 +34,7 @@
34 34
35static noinline void __down(struct semaphore *sem); 35static noinline void __down(struct semaphore *sem);
36static noinline int __down_interruptible(struct semaphore *sem); 36static noinline int __down_interruptible(struct semaphore *sem);
37static noinline int __down_killable(struct semaphore *sem);
37static noinline void __up(struct semaphore *sem); 38static noinline void __up(struct semaphore *sem);
38 39
39void down(struct semaphore *sem) 40void down(struct semaphore *sem)
@@ -61,6 +62,20 @@ int down_interruptible(struct semaphore *sem)
61} 62}
62EXPORT_SYMBOL(down_interruptible); 63EXPORT_SYMBOL(down_interruptible);
63 64
65int down_killable(struct semaphore *sem)
66{
67 unsigned long flags;
68 int result = 0;
69
70 spin_lock_irqsave(&sem->lock, flags);
71 if (unlikely(sem->count-- <= 0))
72 result = __down_killable(sem);
73 spin_unlock_irqrestore(&sem->lock, flags);
74
75 return result;
76}
77EXPORT_SYMBOL(down_killable);
78
64/** 79/**
65 * down_trylock - try to acquire the semaphore, without waiting 80 * down_trylock - try to acquire the semaphore, without waiting
66 * @sem: the semaphore to be acquired 81 * @sem: the semaphore to be acquired
@@ -143,6 +158,8 @@ static inline int __sched __down_common(struct semaphore *sem, long state)
143 for (;;) { 158 for (;;) {
144 if (state == TASK_INTERRUPTIBLE && signal_pending(task)) 159 if (state == TASK_INTERRUPTIBLE && signal_pending(task))
145 goto interrupted; 160 goto interrupted;
161 if (state == TASK_KILLABLE && fatal_signal_pending(task))
162 goto interrupted;
146 __set_task_state(task, state); 163 __set_task_state(task, state);
147 spin_unlock_irq(&sem->lock); 164 spin_unlock_irq(&sem->lock);
148 schedule(); 165 schedule();
@@ -178,6 +195,11 @@ static noinline int __sched __down_interruptible(struct semaphore *sem)
178 return __down_common(sem, TASK_INTERRUPTIBLE); 195 return __down_common(sem, TASK_INTERRUPTIBLE);
179} 196}
180 197
198static noinline int __sched __down_killable(struct semaphore *sem)
199{
200 return __down_common(sem, TASK_KILLABLE);
201}
202
181static noinline void __sched __up(struct semaphore *sem) 203static noinline void __sched __up(struct semaphore *sem)
182{ 204{
183 if (unlikely(list_empty(&sem->wait_list))) 205 if (unlikely(list_empty(&sem->wait_list)))