drivers/timers/rtc.c: Protect the RTC state with a semaphore.

This commit is contained in:
Xiang Xiao 2019-01-27 10:08:07 -06:00 committed by Gregory Nutt
parent dfee842074
commit a497aebcfa

View File

@ -40,6 +40,7 @@
#include <nuttx/config.h>
#include <sys/types.h>
#include <semaphore.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
@ -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;
}