Alan Cox wrote:
>> Lock()
>> {
>> while (lock) sleep_on(&wait);
>> lock =3D 1;
>> }
>>
>> Unlock()
>> {
>> lock =3D 0;
>> wake_up(&wait);
>> }
>>
>> Two processes can enter Lock() while lock is equal to 0, and both set =
>> it. We have seen this occur, and it seems broken. =20
>
>Really
>
> CPU 0 CPU 1
> while(lock) - its 0 while(lock) - its 0
> lock=1 lock=1
>
>am I missing something. I think you want to be using atomic test and set
>operations. (test_and_set_bit)
This brings up something I've been thinking about. Aren't the
sleep_on macros basically useless, since they almost always have a
small window for a race condition?
CPU 0 CPU 1 (or an interrupt)
lock() unlock()
{ {
while (test_and_set(&is_busy))
clear(&is_busy)
wake_up(&wq);
/* goes to sleep */
sleep_on(&wq);
} }
Putting a cli/sti around the whole thing will protect it against
interrupt races, but that still leaves SMP systems vulnerable.
Isn't the only proper way something like this?:
lock()
{
struct wait_queue wait = { current, NULL };
add_to_waitqueue(&wq);
/* set the task state to interruptible before doing the test */
current->state = TASK_INTERRUPTIBLE;
while (test_and_set(&is_busy))
{
/* if wake up is here now, schedule will return
almost immediately */
schedule();
current->state = TASK_INTERRUPTIBLE;
}
current->state = TASK_RUNNING;
remove_from_waitqueue(&wq);
}
Or am I missing something?
/Christer
-- If it's tourist season, why can't we shoot them?- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.rutgers.edu Please read the FAQ at http://www.tux.org/lkml/