drivers/timers/timer.c: Support the signal notification through SIGEV_THREAD

This commit is contained in:
Gregory Nutt 2019-01-28 06:32:27 -06:00
parent b9c7a9a18f
commit 5a0f514615
2 changed files with 19 additions and 34 deletions

View File

@ -46,7 +46,6 @@
#include <string.h>
#include <semaphore.h>
#include <fcntl.h>
#include <signal.h>
#include <assert.h>
#include <errno.h>
#include <debug.h>
@ -67,13 +66,15 @@
struct timer_upperhalf_s
{
sem_t exclsem; /* Supports mutual exclusion */
uint8_t crefs; /* The number of times the device has been opened */
uint8_t signo; /* The signal number to use in the notification */
pid_t pid; /* The ID of the task/thread to receive the signal */
FAR void *arg; /* An argument to pass with the signal */
sem_t exclsem; /* Supports mutual exclusion */
uint8_t crefs; /* The number of times the device has been opened */
FAR char *path; /* Registration path */
/* The contained signal info */
struct timer_notify_s notify;
struct sigwork_s work;
/* The contained lower-half driver */
FAR struct timer_lowerhalf_s *lower;
@ -130,20 +131,14 @@ static const struct file_operations g_timerops =
static bool timer_notifier(FAR uint32_t *next_interval_us, FAR void *arg)
{
FAR struct timer_upperhalf_s *upper = (FAR struct timer_upperhalf_s *)arg;
#ifdef CONFIG_CAN_PASS_STRUCTS
union sigval value;
#endif
FAR struct timer_notify_s *notify = &upper->notify;
DEBUGASSERT(upper != NULL);
/* Signal the waiter.. if there is one */
#ifdef CONFIG_CAN_PASS_STRUCTS
value.sival_ptr = upper->arg;
(void)nxsig_queue(upper->pid, upper->signo, value);
#else
(void)nxsig_queue(upper->pid, upper->signo, upper->arg);
#endif
nxsig_notification(notify->pid, &notify->event,
SI_QUEUE, &upper->work);
return true;
}
@ -328,14 +323,9 @@ static int timer_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
{
/* Stop the timer */
if (lower->ops->stop)
{
ret = lower->ops->stop(lower);
}
else
{
ret = -ENOSYS;
}
DEBUGASSERT(lower->ops->stop != NULL); /* Required */
ret = lower->ops->stop(lower);
nxsig_cancel_notification(&upper->work);
}
break;
@ -394,10 +384,7 @@ static int timer_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
/* cmd: TCIOC_NOTIFICATION
* Description: Notify application via a signal when the timer expires.
* Argument: signal number
*
* NOTE: This ioctl cannot be support in the kernel build mode. In that
* case direct callbacks from kernel space into user space is forbidden.
* Argument: signal information
*/
case TCIOC_NOTIFICATION:
@ -407,10 +394,7 @@ static int timer_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
if (notify != NULL)
{
upper->signo = notify->signo;
upper->pid = notify->pid;
upper->arg = notify->arg;
memcpy(&upper->notify, notify, sizeof(*notify));
ret = timer_setcallback((FAR void *)upper, timer_notifier, upper);
}
else
@ -586,6 +570,7 @@ void timer_unregister(FAR void *handle)
DEBUGASSERT(lower->ops->stop); /* Required */
(void)lower->ops->stop(lower);
nxsig_cancel_notification(&upper->work);
/* Unregister the timer device */

View File

@ -45,6 +45,7 @@
#include <nuttx/compiler.h>
#include <nuttx/irq.h>
#include <nuttx/fs/ioctl.h>
#include <signal.h>
#include <stdbool.h>
#include <sys/types.h>
@ -130,9 +131,8 @@ struct timer_status_s
struct timer_notify_s
{
FAR void *arg; /* An argument to pass with the signal */
pid_t pid; /* The ID of the task/thread to receive the signal */
uint8_t signo; /* The signal number to use in the notification */
struct sigevent event; /* Describe the way a task is to be notified */
pid_t pid; /* The ID of the task/thread to receive the signal */
};
/* This structure provides the "lower-half" driver operations available to