From a497aebcfa95aa20044e5ab3b57614c0f4383b6b Mon Sep 17 00:00:00 2001 From: Xiang Xiao Date: Sun, 27 Jan 2019 10:08:07 -0600 Subject: [PATCH] drivers/timers/rtc.c: Protect the RTC state with a semaphore. --- drivers/timers/rtc.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/drivers/timers/rtc.c b/drivers/timers/rtc.c index 93f702deee..e6338aae4e 100644 --- a/drivers/timers/rtc.c +++ b/drivers/timers/rtc.c @@ -40,6 +40,7 @@ #include #include +#include #include #include #include @@ -67,6 +68,7 @@ struct rtc_alarminfo_s struct rtc_upperhalf_s { FAR struct rtc_lowerhalf_s *lower; /* Contained lower half driver */ + sem_t exclsem; /* Supports mutual exclusion */ #ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS uint8_t crefs; /* Number of open references */ @@ -171,6 +173,7 @@ static void rtc_destroy(FAR struct rtc_upperhalf_s *upper) /* And free our container */ + nxsem_destroy(&upper->exclsem); kmm_free(upper); } #endif @@ -248,6 +251,7 @@ static int rtc_open(FAR struct file *filep) { FAR struct inode *inode; FAR struct rtc_upperhalf_s *upper; + int ret; /* Get the reference to our internal state structure from the inode * structure. @@ -258,10 +262,19 @@ static int rtc_open(FAR struct file *filep) DEBUGASSERT(inode && inode->i_private); upper = inode->i_private; + /* Get exclusive access to the device structures */ + + ret = nxsem_wait(&upper->exclsem); + if (ret < 0) + { + return ret; + } + /* Increment the count of open references on the RTC driver */ upper->crefs++; DEBUGASSERT(upper->crefs > 0); + nxsem_post(&upper->exclsem); return OK; } #endif @@ -275,6 +288,7 @@ static int rtc_close(FAR struct file *filep) { FAR struct inode *inode; FAR struct rtc_upperhalf_s *upper; + int ret; /* Get the reference to our internal state structure from the inode * structure. @@ -285,10 +299,19 @@ static int rtc_close(FAR struct file *filep) DEBUGASSERT(inode && inode->i_private); upper = inode->i_private; + /* Get exclusive access to the device structures */ + + ret = nxsem_wait(&upper->exclsem); + if (ret < 0) + { + return ret; + } + /* Decrement the count of open references on the RTC driver */ DEBUGASSERT(upper->crefs > 0); upper->crefs--; + nxsem_post(&upper->exclsem); /* If the count has decremented to zero and the driver has been unlinked, * then commit Hara-Kiri now. @@ -343,6 +366,14 @@ static int rtc_ioctl(FAR struct file *filep, int cmd, unsigned long arg) upper = inode->i_private; DEBUGASSERT(upper->lower && upper->lower->ops); + /* Get exclusive access to the device structures */ + + ret = nxsem_wait(&upper->exclsem); + if (ret < 0) + { + return ret; + } + /* We simply forward all ioctl() commands to the lower half. The upper * half is nothing more than a thin driver shell over the lower level * RTC implementation. @@ -726,6 +757,7 @@ static int rtc_ioctl(FAR struct file *filep, int cmd, unsigned long arg) break; } + nxsem_post(&upper->exclsem); return ret; } @@ -737,6 +769,7 @@ static int rtc_ioctl(FAR struct file *filep, int cmd, unsigned long arg) static int rtc_unlink(FAR struct inode *inode) { FAR struct rtc_upperhalf_s *upper; + int ret; /* Get the reference to our internal state structure from the inode * structure. @@ -745,9 +778,18 @@ static int rtc_unlink(FAR struct inode *inode) DEBUGASSERT(inode && inode->i_private); upper = inode->i_private; + /* Get exclusive access to the device structures */ + + ret = nxsem_wait(&upper->exclsem); + if (ret < 0) + { + return ret; + } + /* Indicate that the driver has been unlinked */ upper->unlinked = true; + nxsem_post(&upper->exclsem); /* If there are no further open references to the driver, then commit * Hara-Kiri now. @@ -804,6 +846,7 @@ int rtc_initialize(int minor, FAR struct rtc_lowerhalf_s *lower) /* Initialize the upper half container */ upper->lower = lower; /* Contain lower half driver */ + nxsem_init(&upper->exclsem, 0, 1); #ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS upper->crefs = 0; /* No open references */ @@ -821,6 +864,7 @@ int rtc_initialize(int minor, FAR struct rtc_lowerhalf_s *lower) ret = register_driver(devpath, &rtc_fops, 0666, upper); if (ret < 0) { + nxsem_destroy(&upper->exclsem); kmm_free(upper); return ret; }