Re: race condition in down_interruptible

Ulrich Schmid (uschmid@mail.hh.provi.de)
Sat, 13 Feb 1999 19:31:26 +0100


On Sat, 13 Feb 1999, Andrea Arcangeli wrote:

>>> > sem->count sem->waking
>>> >No process holds the semaphore 1 0
>>> >Process A acquires the semaphore 0 0
>>> >Process B calls down_interruptible() -1 0
>>> >Process B is interrupted and passes
>>> > waking_non_zero() -1 0
>>> >Process A calls up() (on another CPU) 0 1
>>>
>>> B get wakenup and runs waking_non_zero that sees sem->waking == 1 and so
>>> do sem->waking-- and then B has no way to runs atomic_inc() because
>>> waking_non_zero returned 1 (owned the semaphore).
>>
>>If B runs waking_non_zero before A calls up, it will see sem->waking == 0.
>
>So? If B runs waking_non_zero (called by __down_interruptible()) at the
>time sem->waking is 0, it will go to sleep in schedule() and will do
>nothing.
>
>If insted __down_interruptible() will se a signal pending it will simply
>undo the decl() done inside __inline__ down().

I should have said "Process B gets a signal" instead of "Process B is
interrupted". I was just misleaded by the name down_interruptible.

The situation I am looking at is:
1. A signal is pending for Process B
2. Process B runs waking_non_zero before A calls up
3. Process A calls up before B calls atomic_inc

The point is that the test of sem->waking and the atomic_inc(&sem->count) are
not done in one atomic operation.

In single steps:
Process B is woken up by a signal
Process B runs waking_non_zero (sem->waking is still == 0)
Process B does not break the loop
Process A calls up and branches to call __up, which will do sem->waking++
This happnes because sem->count was still < 0
Process B tests signal_pending(tsk)
Process B leaves the loop
Process B calls atomic_inc(sem->count)

I know that this is a very unlikly situation, so it shouldn't take too much
attention.

Ulrich Schmid

-
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/