aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/semaphore.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/semaphore.c')
-rw-r--r--kernel/semaphore.c79
1 files changed, 68 insertions, 11 deletions
diff --git a/kernel/semaphore.c b/kernel/semaphore.c
index bef977b16966..5c2942e768cd 100644
--- a/kernel/semaphore.c
+++ b/kernel/semaphore.c
@@ -3,6 +3,26 @@
3 * Author: Matthew Wilcox <willy@linux.intel.com> 3 * Author: Matthew Wilcox <willy@linux.intel.com>
4 * 4 *
5 * Distributed under the terms of the GNU GPL, version 2 5 * Distributed under the terms of the GNU GPL, version 2
6 *
7 * This file implements counting semaphores.
8 * A counting semaphore may be acquired 'n' times before sleeping.
9 * See mutex.c for single-acquisition sleeping locks which enforce
10 * rules which allow code to be debugged more easily.
11 */
12
13/*
14 * Some notes on the implementation:
15 *
16 * The spinlock controls access to the other members of the semaphore.
17 * down_trylock() and up() can be called from interrupt context, so we
18 * have to disable interrupts when taking the lock. It turns out various
19 * parts of the kernel expect to be able to use down() on a semaphore in
20 * interrupt context when they know it will succeed, so we have to use
21 * irqsave variants for down(), down_interruptible() and down_killable()
22 * too.
23 *
24 * The ->count variable represents how many more tasks can acquire this
25 * semaphore. If it's zero, there may be tasks waiting on the wait_list.
6 */ 26 */
7 27
8#include <linux/compiler.h> 28#include <linux/compiler.h>
@@ -12,22 +32,23 @@
12#include <linux/semaphore.h> 32#include <linux/semaphore.h>
13#include <linux/spinlock.h> 33#include <linux/spinlock.h>
14 34
15/*
16 * Some notes on the implementation:
17 *
18 * down_trylock() and up() can be called from interrupt context.
19 * So we have to disable interrupts when taking the lock.
20 *
21 * The ->count variable defines how many more tasks can acquire the
22 * semaphore. If it's zero, there may be tasks waiting on the list.
23 */
24
25static noinline void __down(struct semaphore *sem); 35static noinline void __down(struct semaphore *sem);
26static noinline int __down_interruptible(struct semaphore *sem); 36static noinline int __down_interruptible(struct semaphore *sem);
27static noinline int __down_killable(struct semaphore *sem); 37static noinline int __down_killable(struct semaphore *sem);
28static noinline int __down_timeout(struct semaphore *sem, long jiffies); 38static noinline int __down_timeout(struct semaphore *sem, long jiffies);
29static noinline void __up(struct semaphore *sem); 39static noinline void __up(struct semaphore *sem);
30 40
41/**
42 * down - acquire the semaphore
43 * @sem: the semaphore to be acquired
44 *
45 * Acquires the semaphore. If no more tasks are allowed to acquire the
46 * semaphore, calling this function will put the task to sleep until the
47 * semaphore is released.
48 *
49 * Use of this function is deprecated, please use down_interruptible() or
50 * down_killable() instead.
51 */
31void down(struct semaphore *sem) 52void down(struct semaphore *sem)
32{ 53{
33 unsigned long flags; 54 unsigned long flags;
@@ -41,6 +62,15 @@ void down(struct semaphore *sem)
41} 62}
42EXPORT_SYMBOL(down); 63EXPORT_SYMBOL(down);
43 64
65/**
66 * down_interruptible - acquire the semaphore unless interrupted
67 * @sem: the semaphore to be acquired
68 *
69 * Attempts to acquire the semaphore. If no more tasks are allowed to
70 * acquire the semaphore, calling this function will put the task to sleep.
71 * If the sleep is interrupted by a signal, this function will return -EINTR.
72 * If the semaphore is successfully acquired, this function returns 0.
73 */
44int down_interruptible(struct semaphore *sem) 74int down_interruptible(struct semaphore *sem)
45{ 75{
46 unsigned long flags; 76 unsigned long flags;
@@ -57,6 +87,16 @@ int down_interruptible(struct semaphore *sem)
57} 87}
58EXPORT_SYMBOL(down_interruptible); 88EXPORT_SYMBOL(down_interruptible);
59 89
90/**
91 * down_killable - acquire the semaphore unless killed
92 * @sem: the semaphore to be acquired
93 *
94 * Attempts to acquire the semaphore. If no more tasks are allowed to
95 * acquire the semaphore, calling this function will put the task to sleep.
96 * If the sleep is interrupted by a fatal signal, this function will return
97 * -EINTR. If the semaphore is successfully acquired, this function returns
98 * 0.
99 */
60int down_killable(struct semaphore *sem) 100int down_killable(struct semaphore *sem)
61{ 101{
62 unsigned long flags; 102 unsigned long flags;
@@ -78,7 +118,7 @@ EXPORT_SYMBOL(down_killable);
78 * @sem: the semaphore to be acquired 118 * @sem: the semaphore to be acquired
79 * 119 *
80 * Try to acquire the semaphore atomically. Returns 0 if the mutex has 120 * Try to acquire the semaphore atomically. Returns 0 if the mutex has
81 * been acquired successfully and 1 if it is contended. 121 * been acquired successfully or 1 if it it cannot be acquired.
82 * 122 *
83 * NOTE: This return value is inverted from both spin_trylock and 123 * NOTE: This return value is inverted from both spin_trylock and
84 * mutex_trylock! Be careful about this when converting code. 124 * mutex_trylock! Be careful about this when converting code.
@@ -101,6 +141,16 @@ int down_trylock(struct semaphore *sem)
101} 141}
102EXPORT_SYMBOL(down_trylock); 142EXPORT_SYMBOL(down_trylock);
103 143
144/**
145 * down_timeout - acquire the semaphore within a specified time
146 * @sem: the semaphore to be acquired
147 * @jiffies: how long to wait before failing
148 *
149 * Attempts to acquire the semaphore. If no more tasks are allowed to
150 * acquire the semaphore, calling this function will put the task to sleep.
151 * If the semaphore is not released within the specified number of jiffies,
152 * this function returns -ETIME. It returns 0 if the semaphore was acquired.
153 */
104int down_timeout(struct semaphore *sem, long jiffies) 154int down_timeout(struct semaphore *sem, long jiffies)
105{ 155{
106 unsigned long flags; 156 unsigned long flags;
@@ -117,6 +167,13 @@ int down_timeout(struct semaphore *sem, long jiffies)
117} 167}
118EXPORT_SYMBOL(down_timeout); 168EXPORT_SYMBOL(down_timeout);
119 169
170/**
171 * up - release the semaphore
172 * @sem: the semaphore to release
173 *
174 * Release the semaphore. Unlike mutexes, up() may be called from any
175 * context and even by tasks which have never called down().
176 */
120void up(struct semaphore *sem) 177void up(struct semaphore *sem)
121{ 178{
122 unsigned long flags; 179 unsigned long flags;