diff options
-rw-r--r-- | include/linux/semaphore.h | 39 | ||||
-rw-r--r-- | kernel/semaphore.c | 79 |
2 files changed, 70 insertions, 48 deletions
diff --git a/include/linux/semaphore.h b/include/linux/semaphore.h index a7125daaff90..9cae64b00d6b 100644 --- a/include/linux/semaphore.h +++ b/include/linux/semaphore.h | |||
@@ -4,8 +4,7 @@ | |||
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 | * | 6 | * |
7 | * Counting semaphores allow up to <n> tasks to acquire the semaphore | 7 | * Please see kernel/semaphore.c for documentation of these functions |
8 | * simultaneously. | ||
9 | */ | 8 | */ |
10 | #ifndef __LINUX_SEMAPHORE_H | 9 | #ifndef __LINUX_SEMAPHORE_H |
11 | #define __LINUX_SEMAPHORE_H | 10 | #define __LINUX_SEMAPHORE_H |
@@ -13,11 +12,7 @@ | |||
13 | #include <linux/list.h> | 12 | #include <linux/list.h> |
14 | #include <linux/spinlock.h> | 13 | #include <linux/spinlock.h> |
15 | 14 | ||
16 | /* | 15 | /* Please don't access any members of this structure directly */ |
17 | * The spinlock controls access to the other members of the semaphore. | ||
18 | * 'count' represents how many more tasks can acquire this semaphore. | ||
19 | * Tasks waiting for the lock are kept on the wait_list. | ||
20 | */ | ||
21 | struct semaphore { | 16 | struct semaphore { |
22 | spinlock_t lock; | 17 | spinlock_t lock; |
23 | unsigned int count; | 18 | unsigned int count; |
@@ -46,41 +41,11 @@ static inline void sema_init(struct semaphore *sem, int val) | |||
46 | #define init_MUTEX(sem) sema_init(sem, 1) | 41 | #define init_MUTEX(sem) sema_init(sem, 1) |
47 | #define init_MUTEX_LOCKED(sem) sema_init(sem, 0) | 42 | #define init_MUTEX_LOCKED(sem) sema_init(sem, 0) |
48 | 43 | ||
49 | /* | ||
50 | * Attempt to acquire the semaphore. If another task is already holding the | ||
51 | * semaphore, sleep until the semaphore is released. | ||
52 | */ | ||
53 | extern void down(struct semaphore *sem); | 44 | extern void down(struct semaphore *sem); |
54 | |||
55 | /* | ||
56 | * As down(), except the sleep may be interrupted by a signal. If it is, | ||
57 | * this function will return -EINTR. | ||
58 | */ | ||
59 | extern int __must_check down_interruptible(struct semaphore *sem); | 45 | extern int __must_check down_interruptible(struct semaphore *sem); |
60 | |||
61 | /* | ||
62 | * As down_interruptible(), except the sleep may only be interrupted by | ||
63 | * signals which are fatal to this process. | ||
64 | */ | ||
65 | extern int __must_check down_killable(struct semaphore *sem); | 46 | extern int __must_check down_killable(struct semaphore *sem); |
66 | |||
67 | /* | ||
68 | * As down(), except this function will not sleep. It will return 0 if it | ||
69 | * acquired the semaphore and 1 if the semaphore was contended. This | ||
70 | * function may be called from any context, including interrupt and softirq. | ||
71 | */ | ||
72 | extern int __must_check down_trylock(struct semaphore *sem); | 47 | extern int __must_check down_trylock(struct semaphore *sem); |
73 | |||
74 | /* | ||
75 | * As down(), except this function will return -ETIME if it fails to | ||
76 | * acquire the semaphore within the specified number of jiffies. | ||
77 | */ | ||
78 | extern int __must_check down_timeout(struct semaphore *sem, long jiffies); | 48 | extern int __must_check down_timeout(struct semaphore *sem, long jiffies); |
79 | |||
80 | /* | ||
81 | * Release the semaphore. Unlike mutexes, up() may be called from any | ||
82 | * context and even by tasks which have never called down(). | ||
83 | */ | ||
84 | extern void up(struct semaphore *sem); | 49 | extern void up(struct semaphore *sem); |
85 | 50 | ||
86 | #endif /* __LINUX_SEMAPHORE_H */ | 51 | #endif /* __LINUX_SEMAPHORE_H */ |
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; |