diff options
| author | Matthew Wilcox <matthew@wil.cx> | 2008-04-11 15:23:52 -0400 |
|---|---|---|
| committer | Matthew Wilcox <willy@linux.intel.com> | 2008-04-17 10:43:01 -0400 |
| commit | 714493cd5468f42ca3c4f730a9c17c203abd5059 (patch) | |
| tree | 9d087ad3b74cb1bd6fbd9be486fc2b361c6407dd | |
| parent | b17170b2fac96705db3188f093f89e8e838418e4 (diff) | |
Improve semaphore documentation
Move documentation from semaphore.h to semaphore.c as requested by
Andrew Morton. Also reformat to kernel-doc style and add some more
notes about the implementation.
Signed-off-by: Matthew Wilcox <willy@linux.intel.com>
| -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; |
