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

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

View File

@ -67,6 +67,7 @@
struct timer_upperhalf_s struct timer_upperhalf_s
{ {
sem_t exclsem; /* Supports mutual exclusion */
uint8_t crefs; /* The number of times the device has been opened */ uint8_t crefs; /* The number of times the device has been opened */
uint8_t signo; /* The signal number to use in the notification */ uint8_t signo; /* The signal number to use in the notification */
pid_t pid; /* The ID of the task/thread to receive the signal */ pid_t pid; /* The ID of the task/thread to receive the signal */
@ -164,6 +165,14 @@ static int timer_open(FAR struct file *filep)
tmrinfo("crefs: %d\n", upper->crefs); tmrinfo("crefs: %d\n", upper->crefs);
/* Get exclusive access to the device structures */
ret = nxsem_wait(&upper->exclsem);
if (ret < 0)
{
goto errout;
}
/* Increment the count of references to the device. If this the first /* Increment the count of references to the device. If this the first
* time that the driver has been opened for this device, then initialize * time that the driver has been opened for this device, then initialize
* the device. * the device.
@ -175,7 +184,7 @@ static int timer_open(FAR struct file *filep)
/* More than 255 opens; uint8_t overflows to zero */ /* More than 255 opens; uint8_t overflows to zero */
ret = -EMFILE; ret = -EMFILE;
goto errout; goto errout_with_sem;
} }
/* Save the new open count */ /* Save the new open count */
@ -183,6 +192,9 @@ static int timer_open(FAR struct file *filep)
upper->crefs = tmp; upper->crefs = tmp;
ret = OK; ret = OK;
errout_with_sem:
nxsem_post(&upper->exclsem);
errout: errout:
return ret; return ret;
} }
@ -199,9 +211,18 @@ static int timer_close(FAR struct file *filep)
{ {
FAR struct inode *inode = filep->f_inode; FAR struct inode *inode = filep->f_inode;
FAR struct timer_upperhalf_s *upper = inode->i_private; FAR struct timer_upperhalf_s *upper = inode->i_private;
int ret;
tmrinfo("crefs: %d\n", upper->crefs); tmrinfo("crefs: %d\n", upper->crefs);
/* Get exclusive access to the device structures */
ret = nxsem_wait(&upper->exclsem);
if (ret < 0)
{
return ret;
}
/* Decrement the references to the driver. If the reference count will /* Decrement the references to the driver. If the reference count will
* decrement to 0, then uninitialize the driver. * decrement to 0, then uninitialize the driver.
*/ */
@ -211,6 +232,7 @@ static int timer_close(FAR struct file *filep)
upper->crefs--; upper->crefs--;
} }
nxsem_post(&upper->exclsem);
return OK; return OK;
} }
@ -265,6 +287,14 @@ static int timer_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
lower = upper->lower; lower = upper->lower;
DEBUGASSERT(lower != NULL); DEBUGASSERT(lower != NULL);
/* Get exclusive access to the device structures */
ret = nxsem_wait(&upper->exclsem);
if (ret < 0)
{
return ret;
}
/* Handle built-in ioctl commands */ /* Handle built-in ioctl commands */
switch (cmd) switch (cmd)
@ -433,6 +463,7 @@ static int timer_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
break; break;
} }
nxsem_post(&upper->exclsem);
return ret; return ret;
} }
@ -490,6 +521,7 @@ FAR void *timer_register(FAR const char *path,
*/ */
upper->lower = lower; upper->lower = lower;
nxsem_init(&upper->exclsem, 0, 1);
/* Copy the registration path */ /* Copy the registration path */
@ -515,6 +547,7 @@ errout_with_path:
kmm_free(upper->path); kmm_free(upper->path);
errout_with_upper: errout_with_upper:
nxsem_destroy(&upper->exclsem);
kmm_free(upper); kmm_free(upper);
errout: errout:
@ -560,6 +593,7 @@ void timer_unregister(FAR void *handle)
/* Then free all of the driver resources */ /* Then free all of the driver resources */
nxsem_destroy(&upper->exclsem);
kmm_free(upper->path); kmm_free(upper->path);
kmm_free(upper); kmm_free(upper);
} }