semaphore: fix
[linux-2.6.git] / kernel / semaphore.c
1 /*
2  * Copyright (c) 2008 Intel Corporation
3  * Author: Matthew Wilcox <willy@linux.intel.com>
4  *
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.
26  */
27
28 #include <linux/compiler.h>
29 #include <linux/kernel.h>
30 #include <linux/module.h>
31 #include <linux/sched.h>
32 #include <linux/semaphore.h>
33 #include <linux/spinlock.h>
34
35 static noinline void __down(struct semaphore *sem);
36 static noinline int __down_interruptible(struct semaphore *sem);
37 static noinline int __down_killable(struct semaphore *sem);
38 static noinline int __down_timeout(struct semaphore *sem, long jiffies);
39 static noinline void __up(struct semaphore *sem);
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  */
52 void down(struct semaphore *sem)
53 {
54         unsigned long flags;
55
56         spin_lock_irqsave(&sem->lock, flags);
57         if (unlikely(!sem->count))
58                 __down(sem);
59         sem->count--;
60         spin_unlock_irqrestore(&sem->lock, flags);
61 }
62 EXPORT_SYMBOL(down);
63
64 /**
65  * down_interruptible - acquire the semaphore unless interrupted
66  * @sem: the semaphore to be acquired
67  *
68  * Attempts to acquire the semaphore.  If no more tasks are allowed to
69  * acquire the semaphore, calling this function will put the task to sleep.
70  * If the sleep is interrupted by a signal, this function will return -EINTR.
71  * If the semaphore is successfully acquired, this function returns 0.
72  */
73 int down_interruptible(struct semaphore *sem)
74 {
75         unsigned long flags;
76         int result = 0;
77
78         spin_lock_irqsave(&sem->lock, flags);
79         if (unlikely(!sem->count))
80                 result = __down_interruptible(sem);
81         if (!result)
82                 sem->count--;
83         spin_unlock_irqrestore(&sem->lock, flags);
84
85         return result;
86 }
87 EXPORT_SYMBOL(down_interruptible);
88
89 /**
90  * down_killable - acquire the semaphore unless killed
91  * @sem: the semaphore to be acquired
92  *
93  * Attempts to acquire the semaphore.  If no more tasks are allowed to
94  * acquire the semaphore, calling this function will put the task to sleep.
95  * If the sleep is interrupted by a fatal signal, this function will return
96  * -EINTR.  If the semaphore is successfully acquired, this function returns
97  * 0.
98  */
99 int down_killable(struct semaphore *sem)
100 {
101         unsigned long flags;
102         int result = 0;
103
104         spin_lock_irqsave(&sem->lock, flags);
105         if (unlikely(!sem->count))
106                 result = __down_killable(sem);
107         if (!result)
108                 sem->count--;
109         spin_unlock_irqrestore(&sem->lock, flags);
110
111         return result;
112 }
113 EXPORT_SYMBOL(down_killable);
114
115 /**
116  * down_trylock - try to acquire the semaphore, without waiting
117  * @sem: the semaphore to be acquired
118  *
119  * Try to acquire the semaphore atomically.  Returns 0 if the mutex has
120  * been acquired successfully or 1 if it it cannot be acquired.
121  *
122  * NOTE: This return value is inverted from both spin_trylock and
123  * mutex_trylock!  Be careful about this when converting code.
124  *
125  * Unlike mutex_trylock, this function can be used from interrupt context,
126  * and the semaphore can be released by any task or interrupt.
127  */
128 int down_trylock(struct semaphore *sem)
129 {
130         unsigned long flags;
131         int count;
132
133         spin_lock_irqsave(&sem->lock, flags);
134         count = sem->count - 1;
135         if (likely(count >= 0))
136                 sem->count = count;
137         spin_unlock_irqrestore(&sem->lock, flags);
138
139         return (count < 0);
140 }
141 EXPORT_SYMBOL(down_trylock);
142
143 /**
144  * down_timeout - acquire the semaphore within a specified time
145  * @sem: the semaphore to be acquired
146  * @jiffies: how long to wait before failing
147  *
148  * Attempts to acquire the semaphore.  If no more tasks are allowed to
149  * acquire the semaphore, calling this function will put the task to sleep.
150  * If the semaphore is not released within the specified number of jiffies,
151  * this function returns -ETIME.  It returns 0 if the semaphore was acquired.
152  */
153 int down_timeout(struct semaphore *sem, long jiffies)
154 {
155         unsigned long flags;
156         int result = 0;
157
158         spin_lock_irqsave(&sem->lock, flags);
159         if (unlikely(!sem->count))
160                 result = __down_timeout(sem, jiffies);
161         if (!result)
162                 sem->count--;
163         spin_unlock_irqrestore(&sem->lock, flags);
164
165         return result;
166 }
167 EXPORT_SYMBOL(down_timeout);
168
169 /**
170  * up - release the semaphore
171  * @sem: the semaphore to release
172  *
173  * Release the semaphore.  Unlike mutexes, up() may be called from any
174  * context and even by tasks which have never called down().
175  */
176 void up(struct semaphore *sem)
177 {
178         unsigned long flags;
179
180         spin_lock_irqsave(&sem->lock, flags);
181         sem->count++;
182         if (unlikely(!list_empty(&sem->wait_list)))
183                 __up(sem);
184         spin_unlock_irqrestore(&sem->lock, flags);
185 }
186 EXPORT_SYMBOL(up);
187
188 /* Functions for the contended case */
189
190 struct semaphore_waiter {
191         struct list_head list;
192         struct task_struct *task;
193 };
194
195 /*
196  * Because this function is inlined, the 'state' parameter will be
197  * constant, and thus optimised away by the compiler.  Likewise the
198  * 'timeout' parameter for the cases without timeouts.
199  */
200 static inline int __sched __down_common(struct semaphore *sem, long state,
201                                                                 long timeout)
202 {
203         struct task_struct *task = current;
204         struct semaphore_waiter waiter;
205         int ret = 0;
206
207         waiter.task = task;
208         list_add_tail(&waiter.list, &sem->wait_list);
209
210         for (;;) {
211                 if (state == TASK_INTERRUPTIBLE && signal_pending(task)) {
212                         ret = -EINTR;
213                         break;
214                 }
215                 if (state == TASK_KILLABLE && fatal_signal_pending(task)) {
216                         ret = -EINTR;
217                         break;
218                 }
219                 if (timeout <= 0) {
220                         ret = -ETIME;
221                         break;
222                 }
223                 __set_task_state(task, state);
224                 spin_unlock_irq(&sem->lock);
225                 timeout = schedule_timeout(timeout);
226                 spin_lock_irq(&sem->lock);
227                 if (sem->count > 0)
228                         break;
229         }
230
231         list_del(&waiter.list);
232         return ret;
233 }
234
235 static noinline void __sched __down(struct semaphore *sem)
236 {
237         __down_common(sem, TASK_UNINTERRUPTIBLE, MAX_SCHEDULE_TIMEOUT);
238 }
239
240 static noinline int __sched __down_interruptible(struct semaphore *sem)
241 {
242         return __down_common(sem, TASK_INTERRUPTIBLE, MAX_SCHEDULE_TIMEOUT);
243 }
244
245 static noinline int __sched __down_killable(struct semaphore *sem)
246 {
247         return __down_common(sem, TASK_KILLABLE, MAX_SCHEDULE_TIMEOUT);
248 }
249
250 static noinline int __sched __down_timeout(struct semaphore *sem, long jiffies)
251 {
252         return __down_common(sem, TASK_UNINTERRUPTIBLE, jiffies);
253 }
254
255 static noinline void __sched __up(struct semaphore *sem)
256 {
257         struct semaphore_waiter *waiter = list_first_entry(&sem->wait_list,
258                                                 struct semaphore_waiter, list);
259         wake_up_process(waiter->task);
260 }