diff --git a/ChangeLog b/ChangeLog index b9de4a30547..63cefce45b8 100755 --- a/ChangeLog +++ b/ChangeLog @@ -10725,3 +10725,6 @@ * drivers/lcd/ and include/nuttx/lcd: Modify the SSD1306 LCD driver to support either the SPI or I2C interface. From Alan Carvalho de Assis (2015-07-15). + * drivers/can.c: Fix an issue in the CAN driver hwere the rx_sem + count can grow beyond bounds (2015-07-15). + diff --git a/drivers/can.c b/drivers/can.c index f1a57925eb6..f79958bb464 100644 --- a/drivers/can.c +++ b/drivers/can.c @@ -326,7 +326,14 @@ static ssize_t can_read(FAR struct file *filep, FAR char *buffer, /* Wait for a message to be received */ - ret = sem_wait(&dev->cd_recv.rx_sem); + dev->cd_nrxwaiters++; + do + { + ret = sem_wait(&dev->cd_recv.rx_sem); + } + while (dev->cd_recv.rx_head == dev->cd_recv.rx_tail); + dev->cd_nrxwaiters--; + if (ret < 0) { ret = -get_errno(); @@ -818,7 +825,11 @@ int can_receive(FAR struct can_dev_s *dev, FAR struct can_hdr_s *hdr, * message buffer. */ - sem_post(&fifo->rx_sem); + if (dev->cd_nrxwaiters > 0) + { + sem_post(&fifo->rx_sem); + } + err = OK; } diff --git a/include/nuttx/can.h b/include/nuttx/can.h index b10dedaeaa2..dc6c2db27d8 100644 --- a/include/nuttx/can.h +++ b/include/nuttx/can.h @@ -206,10 +206,10 @@ struct can_rtrwait_s { sem_t cr_sem; /* Wait for RTR response */ uint16_t cr_id; /* The ID that is waited for */ - FAR struct can_msg_s *cr_msg; /* This is where the RTR reponse goes */ + FAR struct can_msg_s *cr_msg; /* This is where the RTR response goes */ }; -/* This structure defines all of the operations providd by the architecture specific +/* This structure defines all of the operations provided by the architecture specific * logic. All fields must be provided with non-NULL function pointers by the * caller of can_register(). */ @@ -284,6 +284,7 @@ struct can_dev_s uint8_t cd_ocount; /* The number of times the device has been opened */ uint8_t cd_npendrtr; /* Number of pending RTR messages */ uint8_t cd_ntxwaiters; /* Number of threads waiting to enqueue a message */ + volatile uint8_t cd_nrxwaiters; /* Number of threads waiting to receive a message */ sem_t cd_closesem; /* Locks out new opens while close is in progress */ sem_t cd_recvsem; /* Used to wakeup user waiting for space in cd_recv.buffer */ struct can_txfifo_s cd_xmit; /* Describes transmit FIFO */