Has anyone tried it on SMP? I get fairly repeatable instances of immortal
`D'-state processes with this patch.
The patch isn't right - it allows `sleepers' to increase without bound.
But it's a boolean!
If you cut out the unnecessary code and the incorrect comments from
__down() it looks like this:
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);
spin_lock_irq(&semaphore_lock);
for (;;) {
/*
* Effectively:
*
* if (sem->sleepers)
* sem->count++
* if (sem->count >= 0)
* sem->sleepers = 0;
* break;
*/
if (!atomic_add_negative(sem->sleepers, &sem->count)) {
sem->sleepers = 0;
break;
}
sem->sleepers = 1;
spin_unlock_irq(&semaphore_lock);
schedule();
tsk->state = TASK_UNINTERRUPTIBLE;
spin_lock_irq(&semaphore_lock);
}
spin_unlock_irq(&semaphore_lock);
remove_wait_queue(&sem->wait, &wait);
tsk->state = TASK_RUNNING;
wake_up(&sem->wait);
}
I spent a couple of hours trying to get "fairness" working right
and have not been able to come up with a non-racy solution. That
semaphore algorithm is amazing. I'm really impressed.
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
Please read the FAQ at http://www.tux.org/lkml/