I am facing odd problem with spin_lock_irqsave on a uni processor machine. I have a piece of critical code/function named with rx_process which is shared by two functions rx_timeout and rx_callback. This is located under a Linux kernel driver omap-serial.c
rx_process ( uartNum)
{
//critical section
}
rx_timeout (uartNum)//this is called from softIrq context upon timer expiry
{
rx_process (uartNum);
}
rx_callback(uartNum)//this is called when interrupt handler registers upon interrupt and when 4k buf is full in rx_process function which invokes start_rx_dma which results in this call back function.
{
rx_process (uartNum);
}
I found that the race condition was happening between these two functions, hence I decided to introduce spin_lock_irqsave in the rx_process at the beginning of the function and at the end of the function, but it still result in race condition and from time to time, I observe data loss and kernel panic.
rx_process ( uartNum)
{ spin_lock_irqsave(&lock, flags);
//critical section
spin_unlock_irqrestore(&lock, flags);
}
rx_timeout (uartNum)//this is called from softIrq context upon timer expiry
{
rx_process (uartNum);
}
rx_callback(uartNum)//this is called when interrupt handler registers upon interrupt and when 4k buf is full in rx_process function which invokes start_rx_dma which results in this call back function
{
rx_process (uartNum);
}
Now, I moved spin_lock_irqsave to rx_timeout as well as to rx_callback function and I don't see race condition.
rx_process ( uartNum)
{
//critical section
spin_unlock_irqrestore(&lock, flags);
}
rx_timeout (uartNum)//this is called from softIrq context upon timer expiry
{
spin_lock_irqsave(&lock, flags);
rx_process (uartNum);
spin_unlock_irqrestore(&lock, flags);
}
rx_callback(uartNum)//this is called when interrupt handler registers upon interrupt and when 4k buf is full in rx_process function which invokes start_rx_dma which results in this call back function
{
spin_lock_irqsave(&lock, flags);
rx_process (uartNum);
spin_unlock_irqrestore(&lock, flags);
}
I would really appreciate if someone could explain the reason why the spin_lock_irqsave used inside the rx_process is failing and not preventing race conditions?