diff options
Diffstat (limited to 'kernel/semaphore.c')
-rw-r--r-- | kernel/semaphore.c | 79 |
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 | |||
25 | static noinline void __down(struct semaphore *sem); | 35 | static noinline void __down(struct semaphore *sem); |
26 | static noinline int __down_interruptible(struct semaphore *sem); | 36 | static noinline int __down_interruptible(struct semaphore *sem); |
27 | static noinline int __down_killable(struct semaphore *sem); | 37 | static noinline int __down_killable(struct semaphore *sem); |
28 | static noinline int __down_timeout(struct semaphore *sem, long jiffies); | 38 | static noinline int __down_timeout(struct semaphore *sem, long jiffies); |
29 | static noinline void __up(struct semaphore *sem); | 39 | static 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 | */ | ||
31 | void down(struct semaphore *sem) | 52 | void 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 | } |
42 | EXPORT_SYMBOL(down); | 63 | EXPORT_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 | */ | ||
44 | int down_interruptible(struct semaphore *sem) | 74 | int 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 | } |
58 | EXPORT_SYMBOL(down_interruptible); | 88 | EXPORT_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 | */ | ||
60 | int down_killable(struct semaphore *sem) | 100 | int 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 | } |
102 | EXPORT_SYMBOL(down_trylock); | 142 | EXPORT_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 | */ | ||
104 | int down_timeout(struct semaphore *sem, long jiffies) | 154 | int 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 | } |
118 | EXPORT_SYMBOL(down_timeout); | 168 | EXPORT_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 | */ | ||
120 | void up(struct semaphore *sem) | 177 | void up(struct semaphore *sem) |
121 | { | 178 | { |
122 | unsigned long flags; | 179 | unsigned long flags; |