drivers/serial: fix race condition in multi-thread write
if multiple threads are doing serial read/write at the same time, the driver will only wake up one of the thread, which will cause other threads fail to be woken up in time and cause blocking Signed-off-by: chao an <anchao@xiaomi.com>
This commit is contained in:
parent
23ad4700a9
commit
6be363ff35
@ -128,8 +128,6 @@ static struct ez80_dev_s g_uart0priv =
|
||||
static uart_dev_t g_uart0port =
|
||||
{
|
||||
0, /* open_count */
|
||||
false, /* xmitwaiting */
|
||||
false, /* recvwaiting */
|
||||
#ifdef CONFIG_UART0_SERIAL_CONSOLE
|
||||
true, /* isconsole */
|
||||
#else
|
||||
|
@ -136,8 +136,6 @@ static const struct z180_dev_s g_scc_priv =
|
||||
static uart_dev_t g_scc_port =
|
||||
{
|
||||
0, /* open_count */
|
||||
false, /* xmitwaiting */
|
||||
false, /* recvwaiting */
|
||||
#ifdef CONFIG_Z180_SCC_SERIAL_CONSOLE
|
||||
true, /* isconsole */
|
||||
#else
|
||||
@ -182,8 +180,6 @@ static const struct z180_dev_s g_escca_priv =
|
||||
static uart_dev_t g_escca_port =
|
||||
{
|
||||
0, /* open_count */
|
||||
false, /* xmitwaiting */
|
||||
false, /* recvwaiting */
|
||||
#ifdef CONFIG_Z180_ESCCA_SERIAL_CONSOLE
|
||||
true, /* isconsole */
|
||||
#else
|
||||
@ -228,8 +224,6 @@ static const struct z180_dev_s g_esccb_priv =
|
||||
static uart_dev_t g_escca_port =
|
||||
{
|
||||
0, /* open_count */
|
||||
false, /* xmitwaiting */
|
||||
false, /* recvwaiting */
|
||||
#ifdef CONFIG_Z180_ESCCA_SERIAL_CONSOLE
|
||||
true, /* isconsole */
|
||||
#else
|
||||
|
@ -138,8 +138,6 @@ static struct z8_uart_s g_uart0priv =
|
||||
static uart_dev_t g_uart0port =
|
||||
{
|
||||
0, /* open_count */
|
||||
false, /* xmitwaiting */
|
||||
false, /* recvwaiting */
|
||||
#ifdef CONFIG_UART0_SERIAL_CONSOLE
|
||||
true, /* isconsole */
|
||||
#else
|
||||
@ -185,8 +183,6 @@ static struct z8_uart_s g_uart1priv =
|
||||
static uart_dev_t g_uart1port =
|
||||
{
|
||||
0, /* open_count */
|
||||
false, /* xmitwaiting */
|
||||
false, /* recvwaiting */
|
||||
#ifdef CONFIG_UART1_SERIAL_CONSOLE
|
||||
true, /* isconsole */
|
||||
#else
|
||||
|
@ -90,8 +90,6 @@ static char g_uarttxbuffer[CONFIG_UART_TXBUFSIZE];
|
||||
static uart_dev_t g_uartport =
|
||||
{
|
||||
0, /* open_count */
|
||||
false, /* xmitwaiting */
|
||||
false, /* recvwaiting */
|
||||
true, /* isconsole */
|
||||
{ 1 }, /* closesem */
|
||||
{ 0 }, /* xmitsem */
|
||||
|
@ -225,10 +225,6 @@ static int uart_putxmitchar(FAR uart_dev_t *dev, int ch, bool oktoblock)
|
||||
#endif
|
||||
else
|
||||
{
|
||||
/* Inform the interrupt level logic that we are waiting. */
|
||||
|
||||
dev->xmitwaiting = true;
|
||||
|
||||
/* Wait for some characters to be sent from the buffer with
|
||||
* the TX interrupt enabled. When the TX interrupt is enabled,
|
||||
* uart_xmitchars() should execute and remove some of the data
|
||||
@ -415,10 +411,6 @@ static int uart_tcdrain(FAR uart_dev_t *dev,
|
||||
ret = OK;
|
||||
while (ret >= 0 && dev->xmit.head != dev->xmit.tail)
|
||||
{
|
||||
/* Inform the interrupt level logic that we are waiting. */
|
||||
|
||||
dev->xmitwaiting = true;
|
||||
|
||||
/* Wait for some characters to be sent from the buffer with
|
||||
* the TX interrupt enabled. When the TX interrupt is
|
||||
* enabled, uart_xmitchars() should execute and remove some
|
||||
@ -1048,8 +1040,6 @@ static ssize_t uart_read(FAR struct file *filep,
|
||||
* thread goes to sleep.
|
||||
*/
|
||||
|
||||
dev->recvwaiting = true;
|
||||
|
||||
#ifdef CONFIG_SERIAL_TERMIOS
|
||||
dev->minrecv = MIN(buflen - recvd, dev->minread - recvd);
|
||||
if (dev->timeout)
|
||||
@ -1064,7 +1054,6 @@ static ssize_t uart_read(FAR struct file *filep,
|
||||
}
|
||||
}
|
||||
|
||||
dev->recvwaiting = false;
|
||||
leave_critical_section(flags);
|
||||
|
||||
/* Was a signal received while waiting for data to be
|
||||
@ -1786,6 +1775,23 @@ static void uart_launch(void)
|
||||
}
|
||||
#endif
|
||||
|
||||
static void uart_wakeup(FAR sem_t *sem)
|
||||
{
|
||||
int sval;
|
||||
|
||||
if (nxsem_get_value(sem, &sval) != OK)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* Yes... wake up all waiting threads */
|
||||
|
||||
while (sval++ < 1)
|
||||
{
|
||||
nxsem_post(sem);
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
@ -1865,13 +1871,7 @@ void uart_datareceived(FAR uart_dev_t *dev)
|
||||
|
||||
/* Is there a thread waiting for read data? */
|
||||
|
||||
if (dev->recvwaiting)
|
||||
{
|
||||
/* Yes... wake it up */
|
||||
|
||||
dev->recvwaiting = false;
|
||||
nxsem_post(&dev->recvsem);
|
||||
}
|
||||
uart_wakeup(&dev->recvsem);
|
||||
|
||||
#if defined(CONFIG_PM) && defined(CONFIG_SERIAL_CONSOLE)
|
||||
/* Call pm_activity when characters are received on the console device */
|
||||
@ -1903,13 +1903,7 @@ void uart_datasent(FAR uart_dev_t *dev)
|
||||
|
||||
/* Is there a thread waiting for space in xmit.buffer? */
|
||||
|
||||
if (dev->xmitwaiting)
|
||||
{
|
||||
/* Yes... wake it up */
|
||||
|
||||
dev->xmitwaiting = false;
|
||||
nxsem_post(&dev->xmitsem);
|
||||
}
|
||||
uart_wakeup(&dev->xmitsem);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -1957,23 +1951,11 @@ void uart_connected(FAR uart_dev_t *dev, bool connected)
|
||||
|
||||
/* Is there a thread waiting for space in xmit.buffer? */
|
||||
|
||||
if (dev->xmitwaiting)
|
||||
{
|
||||
/* Yes... wake it up */
|
||||
|
||||
dev->xmitwaiting = false;
|
||||
nxsem_post(&dev->xmitsem);
|
||||
}
|
||||
uart_wakeup(&dev->xmitsem);
|
||||
|
||||
/* Is there a thread waiting for read data? */
|
||||
|
||||
if (dev->recvwaiting)
|
||||
{
|
||||
/* Yes... wake it up */
|
||||
|
||||
dev->recvwaiting = false;
|
||||
nxsem_post(&dev->recvsem);
|
||||
}
|
||||
uart_wakeup(&dev->recvsem);
|
||||
}
|
||||
|
||||
leave_critical_section(flags);
|
||||
|
@ -272,8 +272,6 @@ struct uart_dev_s
|
||||
|
||||
uint8_t open_count; /* Number of times the device has been opened */
|
||||
uint8_t escape; /* Number of the character to be escaped */
|
||||
volatile bool xmitwaiting; /* true: User waiting for space in xmit.buffer */
|
||||
volatile bool recvwaiting; /* true: User waiting for data in recv.buffer */
|
||||
#ifdef CONFIG_SERIAL_REMOVABLE
|
||||
volatile bool disconnected; /* true: Removable device is not connected */
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user