From b2f3e916efc0c3b6a5e2131aca5c59024e87cd72 Mon Sep 17 00:00:00 2001 From: patacongo Date: Thu, 18 Aug 2011 14:07:52 +0000 Subject: [PATCH] Fix a semphore overflow problem in the CAN driver git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@3890 42af7a65-404d-4744-a932-0658087f49c3 --- ChangeLog | 3 +++ drivers/can.c | 12 ++++++++++-- include/nuttx/can.h | 1 + 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index e3e1ab5661..604590f7d5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -2002,3 +2002,6 @@ and bit fields within all Kinetis registers. * configs/twr-k60n512: Add support for the Kinetis K60 Tower board (TWR-K60N512). + * drivers/can.c: Fixe a semaphore overflow problem in the CAN driver + (reported by Li Zhouy (Lzzy)). + diff --git a/drivers/can.c b/drivers/can.c index accafce3c1..fc70678a7d 100644 --- a/drivers/can.c +++ b/drivers/can.c @@ -50,6 +50,7 @@ #include #include #include +#include #include #include @@ -443,7 +444,11 @@ static ssize_t can_write(FAR struct file *filep, FAR const char *buffer, size_t do { + DEBUGASSERT(dev->cd_ntxwaiters < 255); + dev->cd_ntxwaiters++; ret = sem_wait(&fifo->cf_sem); + dev->cd_ntxwaiters--; + if (ret < 0 && errno != EINTR) { ret = -errno; @@ -750,9 +755,12 @@ int can_txdone(FAR struct can_dev_s *dev) /* Send the next message in the FIFO */ ret = can_xmit(dev); - if (ret == OK) + + /* Are there any threads waiting for space in the TX FIFO? */ + + if (ret == OK && dev->cd_ntxwaiters > 0) { - /* Inform any waiting threads that new xmit space is available */ + /* Yes.. Inform them that new xmit space is available */ ret = sem_post(&dev->cd_xmit.cf_sem); } diff --git a/include/nuttx/can.h b/include/nuttx/can.h index 5841aff7a8..8b438ffdae 100644 --- a/include/nuttx/can.h +++ b/include/nuttx/can.h @@ -219,6 +219,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 */ 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_fifo_s cd_xmit; /* Describes transmit FIFO */