From 5a0f514615e05fe7e42932ed702b731a90c2cb74 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Mon, 28 Jan 2019 06:32:27 -0600 Subject: [PATCH] drivers/timers/timer.c: Support the signal notification through SIGEV_THREAD --- drivers/timers/timer.c | 47 ++++++++++++------------------------ include/nuttx/timers/timer.h | 6 ++--- 2 files changed, 19 insertions(+), 34 deletions(-) diff --git a/drivers/timers/timer.c b/drivers/timers/timer.c index 4e5a19b93a..fc61075ab3 100644 --- a/drivers/timers/timer.c +++ b/drivers/timers/timer.c @@ -46,7 +46,6 @@ #include #include #include -#include #include #include #include @@ -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, ¬ify->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 */ diff --git a/include/nuttx/timers/timer.h b/include/nuttx/timers/timer.h index 420e8dfbb2..ede6669f3f 100644 --- a/include/nuttx/timers/timer.h +++ b/include/nuttx/timers/timer.h @@ -45,6 +45,7 @@ #include #include #include +#include #include #include @@ -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