203
204static inline int __sched __down_common(struct semaphore *sem, long state,
205 long timeout)
206{
207 struct task_struct *task = current;
208 struct semaphore_waiter waiter;
209
210 list_add_tail(&waiter.list, &sem->wait_list);
211 waiter.task = task;
212 waiter.up = 0;
213
214 for (;;) {
215 if (signal_pending_state(state, task))
216 goto interrupted;
217 if (timeout <= 0)
218 goto timed_out;
219 __set_task_state(task, state);
220 spin_unlock_irq(&sem->lock);
221 timeout = schedule_timeout(timeout);
222 spin_lock_irq(&sem->lock);
223 if (waiter.up)
224 return 0;
225 }
226
227 timed_out:
228 list_del(&waiter.list);
229 return -ETIME;
230
231 interrupted:
232 list_del(&waiter.list);
233 return -EINTR;
234}
235
236static noinline void __sched __down(struct semaphore *sem)
237{
238 __down_common(sem, TASK_UNINTERRUPTIBLE, MAX_SCHEDULE_TIMEOUT);
239}
240
241static noinline int __sched __down_interruptible(struct semaphore *sem)
242{
243 return __down_common(sem, TASK_INTERRUPTIBLE, MAX_SCHEDULE_TIMEOUT);