int __sched __down_interruptible(struct semaphore * sem) { int retval = 0; struct task_struct *tsk = current; DECLARE_WAITQUEUE(wait, tsk); __set_task_state(tsk, TASK_INTERRUPTIBLE); add_wait_queue_exclusive(&sem->wait, &wait); while (__sem_update_count(sem, -1) <= 0) { if (signal_pending(current)) { /* * A signal is pending - give up trying. * Set sem->count to 0 if it is negative, * since we are no longer sleeping. */ __sem_update_count(sem, 0); retval = -EINTR; break; } schedule(); set_task_state(tsk, TASK_INTERRUPTIBLE); } remove_wait_queue(&sem->wait, &wait); __set_task_state(tsk, TASK_RUNNING); wake_up(&sem->wait); return retval; }
/* * Note that when we come in to __down or __down_interruptible, * we have already decremented count, but that decrement was * ineffective since the result was < 0, and any negative value * of count is equivalent to 0. * Thus it is only when we decrement count from some value > 0 * that we have actually got the semaphore. */ void __sched __down(struct semaphore *sem) { struct task_struct *tsk = current; DECLARE_WAITQUEUE(wait, tsk); __set_task_state(tsk, TASK_UNINTERRUPTIBLE); add_wait_queue_exclusive(&sem->wait, &wait); /* * Try to get the semaphore. If the count is > 0, then we've * got the semaphore; we decrement count and exit the loop. * If the count is 0 or negative, we set it to -1, indicating * that we are asleep, and then sleep. */ while (__sem_update_count(sem, -1) <= 0) { schedule(); set_task_state(tsk, TASK_UNINTERRUPTIBLE); } remove_wait_queue(&sem->wait, &wait); __set_task_state(tsk, TASK_RUNNING); /* * If there are any more sleepers, wake one of them up so * that it can either get the semaphore, or set count to -1 * indicating that there are still processes sleeping. */ wake_up(&sem->wait); }
int __sched __down_failed_interruptible(struct semaphore *sem) { struct task_struct *tsk = current; DECLARE_WAITQUEUE(wait, tsk); long ret = 0; #ifdef CONFIG_DEBUG_SEMAPHORE printk("%s(%d): down failed(%p)\n", tsk->comm, tsk->pid, sem); #endif tsk->state = TASK_INTERRUPTIBLE; wmb(); add_wait_queue_exclusive(&sem->wait, &wait); while (__sem_update_count(sem, -1) <= 0) { if (signal_pending(current)) { /* * A signal is pending - give up trying. * Set sem->count to 0 if it is negative, * since we are no longer sleeping. */ __sem_update_count(sem, 0); ret = -EINTR; break; } schedule(); set_task_state(tsk, TASK_INTERRUPTIBLE); } remove_wait_queue(&sem->wait, &wait); tsk->state = TASK_RUNNING; wake_up(&sem->wait); #ifdef CONFIG_DEBUG_SEMAPHORE printk("%s(%d): down %s(%p)\n", current->comm, current->pid, (ret < 0 ? "interrupted" : "acquired"), sem); #endif return ret; }
void __up(struct semaphore *sem) { /* * Note that we incremented count in up() before we came here, * but that was ineffective since the result was <= 0, and * any negative value of count is equivalent to 0. * This ends up setting count to 1, unless count is now > 0 * (i.e. because some other cpu has called up() in the meantime), * in which case we just increment count. */ __sem_update_count(sem, 1); wake_up(&sem->wait); }
int __down_interruptible(struct semaphore * sem) { int retval = 0; struct task_struct *tsk = current; DECLARE_WAITQUEUE(wait, tsk); tsk->state = TASK_INTERRUPTIBLE; add_wait_queue_exclusive(&sem->wait, &wait); while (__sem_update_count(sem, -1) <= 0) { if (signal_pending(current)) { __sem_update_count(sem, 0); retval = -EINTR; break; } schedule(); tsk->state = TASK_INTERRUPTIBLE; } tsk->state = TASK_RUNNING; remove_wait_queue(&sem->wait, &wait); wake_up(&sem->wait); return retval; }
void __down(struct semaphore * sem) { struct task_struct *tsk = current; DECLARE_WAITQUEUE(wait, tsk); tsk->state = TASK_UNINTERRUPTIBLE; add_wait_queue_exclusive(&sem->wait, &wait); while (__sem_update_count(sem, -1) <= 0) { schedule(); tsk->state = TASK_UNINTERRUPTIBLE; } remove_wait_queue(&sem->wait, &wait); tsk->state = TASK_RUNNING; wake_up(&sem->wait); }
void __sched __down_failed(struct semaphore *sem) { struct task_struct *tsk = current; DECLARE_WAITQUEUE(wait, tsk); #ifdef CONFIG_DEBUG_SEMAPHORE printk("%s(%d): down failed(%p)\n", tsk->comm, tsk->pid, sem); #endif tsk->state = TASK_UNINTERRUPTIBLE; wmb(); add_wait_queue_exclusive(&sem->wait, &wait); /* * Try to get the semaphore. If the count is > 0, then we've * got the semaphore; we decrement count and exit the loop. * If the count is 0 or negative, we set it to -1, indicating * that we are asleep, and then sleep. */ while (__sem_update_count(sem, -1) <= 0) { schedule(); set_task_state(tsk, TASK_UNINTERRUPTIBLE); } remove_wait_queue(&sem->wait, &wait); tsk->state = TASK_RUNNING; /* * If there are any more sleepers, wake one of them up so * that it can either get the semaphore, or set count to -1 * indicating that there are still processes sleeping. */ wake_up(&sem->wait); #ifdef CONFIG_DEBUG_SEMAPHORE printk("%s(%d): down acquired(%p)\n", tsk->comm, tsk->pid, sem); #endif }
static void __up(struct semaphore *sem) { __sem_update_count(sem, 1); wake_up(&sem->wait); }