Re: Locks used in the FAT file system are non-atomic and in fact, don't work on SMP systems

Christer Weinigel (wingel@hog.ctrl-c.liu.se)
26 Aug 1999 19:48:24 -0000


[ouch, I managed to misspell "linux-kernel" when I sent this the last
time. Alan, please excuse me for sending it again]

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/