In case a thread is doing a blocking operation (e.g. read()) on a serial

device, while it is being terminated by pthread_cancel(), then
uart_close() gets called, but the semaphore (dev->recv.sem in the above
example) is still blocked.

This means that once the serial device is opened next time, data will
arrive on the serial port (and driver interrupts handled as normal), but
the received characters never arrive in the reader thread.

This patch addresses the problem by re-initializing the semaphores on the
last uart_close() on the device.
This commit is contained in:
Gregory Nutt 2014-12-13 08:07:21 -06:00
parent 93bde18bd0
commit d09bb13833
1 changed files with 23 additions and 0 deletions

View File

@ -109,6 +109,16 @@ static const struct file_operations g_serialops =
* Private Functions
************************************************************************************/
/************************************************************************************
* Name: sem_reinit
************************************************************************************/
static int sem_reinit(FAR sem_t *sem, int pshared, unsigned int value)
{
sem_destroy(sem);
return sem_init(sem, pshared, value);
}
/************************************************************************************
* Name: uart_takesem
************************************************************************************/
@ -1109,6 +1119,19 @@ static int uart_close(FAR struct file *filep)
irqrestore(flags);
/* We need to re-initialize the semaphores if this is the last close
* of the device, as the close might be caused by pthread_cancel() of
* a thread currently blocking on any of them
*/
sem_reinit(&dev->xmitsem, 0, 0);
sem_reinit(&dev->recvsem, 0, 0);
sem_reinit(&dev->xmit.sem, 0, 1);
sem_reinit(&dev->recv.sem, 0, 1);
#ifndef CONFIG_DISABLE_POLL
sem_reinit(&dev->pollsem, 0, 1);
#endif
uart_givesem(&dev->closesem);
return OK;
}