diff --git a/drivers/input/ajoystick.c b/drivers/input/ajoystick.c index 400c7b0abcd..bc83f0d2260 100644 --- a/drivers/input/ajoystick.c +++ b/drivers/input/ajoystick.c @@ -105,6 +105,7 @@ struct ajoy_open_s pid_t ao_pid; struct ajoy_notify_s ao_notify; + struct sigwork_s ao_work; #endif #ifndef CONFIG_DISABLE_POLL @@ -376,7 +377,7 @@ static void ajoy_sample(FAR struct ajoy_upperhalf_s *priv) opriv->ao_notify.an_event.sigev_value.sival_int = sample; nxsig_notification(opriv->ao_pid, &opriv->ao_notify.an_event, - SI_QUEUE); + SI_QUEUE, &opriv->ao_work); } #endif } @@ -532,6 +533,10 @@ static int ajoy_close(FAR struct file *filep) priv->au_open = opriv->ao_flink; } + /* Cancel any pending notification */ + + nxsig_cancel_notification(&opriv->ao_work); + /* And free the open structure */ kmm_free(opriv); diff --git a/drivers/input/button_upper.c b/drivers/input/button_upper.c index dd86a4be282..6e293fdac67 100644 --- a/drivers/input/button_upper.c +++ b/drivers/input/button_upper.c @@ -101,6 +101,7 @@ struct btn_open_s pid_t bo_pid; struct btn_notify_s bo_notify; + struct sigwork_s bo_work; #endif #ifndef CONFIG_DISABLE_POLL @@ -358,8 +359,8 @@ static void btn_sample(FAR struct btn_upperhalf_s *priv) opriv->bo_notify.bn_event.sigev_value.sival_int = sample; nxsig_notification(opriv->bo_pid, &opriv->bo_notify.bn_event, - SI_QUEUE); - } + SI_QUEUE, &opriv->bo_work); + } #endif } @@ -518,6 +519,10 @@ static int btn_close(FAR struct file *filep) priv->bu_open = opriv->bo_flink; } + /* Cancel any pending notification */ + + nxsig_cancel_notification(&opriv->bo_work); + /* And free the open structure */ kmm_free(opriv); diff --git a/drivers/input/djoystick.c b/drivers/input/djoystick.c index fba7c434f29..7955fff5110 100644 --- a/drivers/input/djoystick.c +++ b/drivers/input/djoystick.c @@ -105,6 +105,7 @@ struct djoy_open_s pid_t do_pid; struct djoy_notify_s do_notify; + struct sigwork_s do_work; #endif #ifndef CONFIG_DISABLE_POLL @@ -376,7 +377,7 @@ static void djoy_sample(FAR struct djoy_upperhalf_s *priv) opriv->do_notify.dn_event.sigev_value.sival_int = sample; nxsig_notification(opriv->do_pid, &opriv->do_notify.dn_event, - SI_QUEUE); + SI_QUEUE, &opriv->do_work); } #endif } @@ -532,6 +533,10 @@ static int djoy_close(FAR struct file *filep) priv->du_open = opriv->do_flink; } + /* Cancel any pending notification */ + + nxsig_cancel_notification(&opriv->do_work); + /* And free the open structure */ kmm_free(opriv); diff --git a/drivers/ioexpander/gpio.c b/drivers/ioexpander/gpio.c index 76193c81a49..2ada128d375 100644 --- a/drivers/ioexpander/gpio.c +++ b/drivers/ioexpander/gpio.c @@ -46,7 +46,6 @@ #include #include -#include #include #include @@ -113,7 +112,8 @@ static int gpio_handler(FAR struct gpio_dev_s *dev, uint8_t pin) break; } - nxsig_notification(signal->gp_pid, &signal->gp_event, SI_QUEUE); + nxsig_notification(signal->gp_pid, &signal->gp_event, + SI_QUEUE, &signal->gp_work); } return OK; @@ -329,6 +329,7 @@ static int gpio_ioctl(FAR struct file *filep, int cmd, unsigned long arg) } dev->gp_signals[j].gp_pid = 0; + nxsig_cancel_notification(&dev->gp_signals[j].gp_work); ret = OK; break; } diff --git a/drivers/lcd/ft80x.c b/drivers/lcd/ft80x.c index 01f83c36991..337b1a4de7c 100644 --- a/drivers/lcd/ft80x.c +++ b/drivers/lcd/ft80x.c @@ -58,7 +58,6 @@ #include #include -#include #include #include #include @@ -276,7 +275,7 @@ static void ft80x_notify(FAR struct ft80x_dev_s *priv, /* Yes.. Signal the client */ info->event.sigev_value.sival_int = value; - nxsig_notification(info->pid, &info->event, SI_QUEUE); + nxsig_notification(info->pid, &info->event, SI_QUEUE, &info->work); } } @@ -1055,6 +1054,10 @@ static int ft80x_ioctl(FAR struct file *filep, int cmd, unsigned long arg) regval = ft80x_read_word(priv, FT80X_REG_INT_MASK); regval &= ~(1 << notify->id); ft80x_write_word(priv, FT80X_REG_INT_MASK, regval); + + /* Cancel any pending notification */ + + nxsig_cancel_notification(&info->work); ret = OK; } } diff --git a/drivers/lcd/ft80x.h b/drivers/lcd/ft80x.h index 7bf0725b901..75ac395621c 100644 --- a/drivers/lcd/ft80x.h +++ b/drivers/lcd/ft80x.h @@ -49,10 +49,9 @@ *******************************************************************************************/ #include +#include #include -#include - /******************************************************************************************* * Public Types *******************************************************************************************/ @@ -160,6 +159,7 @@ struct ft80x_i2cwrite_s struct ft80x_eventinfo_s { struct sigevent event; /* Describe the way a task is to be notified */ + struct sigwork_s work; /* Work for SIGEV_THREAD */ bool enable; /* True: enable notification; false: disable */ int16_t pid; /* Send the notification to this task */ }; diff --git a/drivers/net/phy_notify.c b/drivers/net/phy_notify.c index 19ece2e7db6..1a2c3404fbb 100644 --- a/drivers/net/phy_notify.c +++ b/drivers/net/phy_notify.c @@ -104,6 +104,7 @@ struct phy_notify_s char intf[CONFIG_PHY_NOTIFICATION_MAXINTFLEN+1]; pid_t pid; struct sigevent event; + struct sigwork_s work; phy_enable_t enable; }; @@ -243,7 +244,8 @@ static int phy_handler(int irq, FAR void *context, FAR void *arg) /* Signal the client that the PHY has something interesting to say to us */ - ret = nxsig_notification(client->pid, &client->event, SI_QUEUE); + ret = nxsig_notification(client->pid, &client->event, + SI_QUEUE, &client->work); if (ret < 0) { phyerr("ERROR: nxsig_notification failed: %d\n", ret); @@ -380,6 +382,10 @@ int phy_notify_unsubscribe(FAR const char *intf, pid_t pid) phy_semtake(); (void)arch_phy_irq(intf, NULL, NULL, NULL); + /* Cancel any pending notification */ + + nxsig_cancel_notification(&client->work); + /* Un-initialize the client entry */ client->assigned = false; diff --git a/drivers/sensors/zerocross.c b/drivers/sensors/zerocross.c index 33d83cf940e..6ed06c35d04 100644 --- a/drivers/sensors/zerocross.c +++ b/drivers/sensors/zerocross.c @@ -104,6 +104,7 @@ struct zc_open_s pid_t do_pid; struct sigevent do_event; + struct sigwork_s do_work; }; /**************************************************************************** @@ -205,7 +206,8 @@ static void zerocross_interrupt(FAR const struct zc_lowerhalf_s *lower, /* Signal the waiter */ opriv->do_event.sigev_value.sival_int = sample; - nxsig_notification(opriv->do_pid, &opriv->do_event, SI_QUEUE); + nxsig_notification(opriv->do_pid, &opriv->do_event, + SI_QUEUE, &opriv->do_work); } leave_critical_section(flags); @@ -346,6 +348,10 @@ static int zc_close(FAR struct file *filep) priv->zu_open = opriv->do_flink; } + /* Cancel any pending notification */ + + nxsig_cancel_notification(&opriv->do_work); + /* And free the open structure */ kmm_free(opriv); diff --git a/drivers/timers/oneshot.c b/drivers/timers/oneshot.c index f28d310a07e..2772013afd4 100644 --- a/drivers/timers/oneshot.c +++ b/drivers/timers/oneshot.c @@ -76,6 +76,7 @@ struct oneshot_dev_s /* Oneshot timer expiration notification information */ struct sigevent od_event; /* Signal info */ + struct sigwork_s od_work; /* Signal work */ pid_t od_pid; /* PID to be notified */ }; @@ -132,7 +133,8 @@ static void oneshot_callback(FAR struct oneshot_lowerhalf_s *lower, /* Signal the waiter.. if there is one */ - nxsig_notification(priv->od_pid, &priv->od_event, SI_QUEUE); + nxsig_notification(priv->od_pid, &priv->od_event, + SI_QUEUE, &priv->od_work); } /**************************************************************************** @@ -292,6 +294,7 @@ static int oneshot_ioctl(FAR struct file *filep, int cmd, unsigned long arg) /* Cancel the oneshot timer */ ret = ONESHOT_CANCEL(priv->od_lower, ts); + nxsig_cancel_notification(&priv->od_work); } break; diff --git a/drivers/timers/rtc.c b/drivers/timers/rtc.c index b17746bc80c..93f702deeef 100644 --- a/drivers/timers/rtc.c +++ b/drivers/timers/rtc.c @@ -60,6 +60,7 @@ struct rtc_alarminfo_s bool active; /* True: alarm is active */ pid_t pid; /* Identifies task to be notified */ struct sigevent event; /* Describe the way a task is to be notified */ + struct sigwork_s work; /* Signal work */ }; #endif @@ -196,7 +197,8 @@ static void rtc_alarm_callback(FAR void *priv, int alarmid) { /* Yes.. signal the alarm expiration */ - nxsig_notification(alarminfo->pid, &alarminfo->event, SI_QUEUE); + nxsig_notification(alarminfo->pid, &alarminfo->event, + SI_QUEUE, &alarminfo->work); } /* The alarm is no longer active */ @@ -227,7 +229,8 @@ static void rtc_periodic_callback(FAR void *priv, int alarmid) { /* Yes.. signal the alarm expiration */ - nxsig_notification(alarminfo->pid, &alarminfo->event, SI_QUEUE); + nxsig_notification(alarminfo->pid, &alarminfo->event, + SI_QUEUE, &alarminfo->work); } /* The alarm is no longer active */ @@ -566,6 +569,7 @@ static int rtc_ioctl(FAR struct file *filep, int cmd, unsigned long arg) if (ret == OK) { upperinfo->active = false; + nxsig_cancel_notification(&upperinfo->work); } } } @@ -698,6 +702,7 @@ static int rtc_ioctl(FAR struct file *filep, int cmd, unsigned long arg) if (ret == OK) { upperinfo->active = false; + nxsig_cancel_notification(&upperinfo->work); } } } diff --git a/drivers/wireless/ieee802154/xbee/xbee_netdev.c b/drivers/wireless/ieee802154/xbee/xbee_netdev.c index 3451b69d7d3..f6406218741 100644 --- a/drivers/wireless/ieee802154/xbee/xbee_netdev.c +++ b/drivers/wireless/ieee802154/xbee/xbee_netdev.c @@ -165,6 +165,7 @@ struct xbeenet_driver_s bool xd_notify_registered; pid_t xd_notify_pid; struct sigevent xd_notify_event; + struct sigwork_s xd_notify_work; #endif }; @@ -446,7 +447,7 @@ static int xbeenet_notify(FAR struct xbee_maccb_s *maccb, { priv->xd_notify_event.sigev_value.sival_int = primitive->type; nxsig_notification(priv->xd_notify_pid, &priv->xd_notify_event, - SI_QUEUE); + SI_QUEUE, &priv->xd_notify_work); } #endif diff --git a/fs/aio/aio_fsync.c b/fs/aio/aio_fsync.c index 86f67bdd343..9053172bb1d 100644 --- a/fs/aio/aio_fsync.c +++ b/fs/aio/aio_fsync.c @@ -210,6 +210,7 @@ int aio_fsync(int op, FAR struct aiocb *aiocbp) /* The result -EINPROGRESS means that the transfer has not yet completed */ + sigwork_init(&aiocbp->aio_sigwork); aiocbp->aio_result = -EINPROGRESS; aiocbp->aio_priv = NULL; diff --git a/fs/aio/aio_read.c b/fs/aio/aio_read.c index 6cb446fe3f3..af41e14bf84 100644 --- a/fs/aio/aio_read.c +++ b/fs/aio/aio_read.c @@ -259,6 +259,7 @@ int aio_read(FAR struct aiocb *aiocbp) /* The result -EINPROGRESS means that the transfer has not yet completed */ + sigwork_init(&aiocbp->aio_sigwork); aiocbp->aio_result = -EINPROGRESS; aiocbp->aio_priv = NULL; diff --git a/fs/aio/aio_signal.c b/fs/aio/aio_signal.c index 2fe002cd643..85e058a6a51 100644 --- a/fs/aio/aio_signal.c +++ b/fs/aio/aio_signal.c @@ -91,7 +91,8 @@ int aio_signal(pid_t pid, FAR struct aiocb *aiocbp) /* Signal the client */ - ret = nxsig_notification(pid, &aiocbp->aio_sigevent, SI_ASYNCIO); + ret = nxsig_notification(pid, &aiocbp->aio_sigevent, + SI_ASYNCIO, &aiocbp->aio_sigwork); if (ret < 0) { ferr("ERROR: nxsig_notification failed: %d\n", ret); diff --git a/fs/aio/aio_write.c b/fs/aio/aio_write.c index 93bbec7a6a0..0eeef18e906 100644 --- a/fs/aio/aio_write.c +++ b/fs/aio/aio_write.c @@ -309,6 +309,7 @@ int aio_write(FAR struct aiocb *aiocbp) /* The result -EINPROGRESS means that the transfer has not yet completed */ + sigwork_init(&aiocbp->aio_sigwork); aiocbp->aio_result = -EINPROGRESS; aiocbp->aio_priv = NULL; diff --git a/include/aio.h b/include/aio.h index 183caec06b1..b139d2ed825 100644 --- a/include/aio.h +++ b/include/aio.h @@ -43,9 +43,9 @@ #include #include -#include #include +#include #include /**************************************************************************** @@ -137,6 +137,7 @@ struct aiocb * application code should never reference these elements. */ + struct sigwork_s aio_sigwork; /* Signal work */ volatile ssize_t aio_result; /* Support for aio_error() and aio_return() */ FAR void *aio_priv; /* Used by signal handlers */ }; diff --git a/include/nuttx/ioexpander/gpio.h b/include/nuttx/ioexpander/gpio.h index 026e13f1190..30dde6f96ee 100644 --- a/include/nuttx/ioexpander/gpio.h +++ b/include/nuttx/ioexpander/gpio.h @@ -45,8 +45,8 @@ #include #include #include -#include +#include #include /**************************************************************************** @@ -144,6 +144,7 @@ struct gpio_operations_s struct gpio_signal_s { struct sigevent gp_event; + struct sigwork_s gp_work; pid_t gp_pid; /* The task to be signaled */ }; diff --git a/include/nuttx/mqueue.h b/include/nuttx/mqueue.h index c33f1768aa5..f1c0f9f713e 100644 --- a/include/nuttx/mqueue.h +++ b/include/nuttx/mqueue.h @@ -43,13 +43,13 @@ #include #include +#include #include #include #include #include #include -#include #if CONFIG_MQ_MAXMSGSIZE > 0 @@ -117,6 +117,7 @@ struct mqueue_inode_s FAR struct mq_des *ntmqdes; /* Notification: Owning mqdes (NULL if none) */ pid_t ntpid; /* Notification: Receiving Task's PID */ struct sigevent ntevent; /* Notification description */ + struct sigwork_s ntwork; /* Notification work */ #endif }; diff --git a/include/nuttx/signal.h b/include/nuttx/signal.h index 7480858bd3d..be6841abb3e 100644 --- a/include/nuttx/signal.h +++ b/include/nuttx/signal.h @@ -41,11 +41,35 @@ ****************************************************************************/ #include +#include #include #include #include +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#ifdef CONFIG_SIG_EVTHREAD + #define sigwork_init(work) memset(work, 0, sizeof(*work)); +#else + #define sigwork_init(work) (void)(work) +#endif + +/**************************************************************************** + * Public Type Definitions + ****************************************************************************/ + +struct sigwork_s +{ +#ifdef CONFIG_SIG_EVTHREAD + struct work_s work; /* Work queue structure */ + union sigval value; /* Data passed with notification */ + sigev_notify_function_t func; /* Notification function */ +#endif +}; + /**************************************************************************** * Public Function Prototypes ****************************************************************************/ @@ -445,6 +469,7 @@ int nxsig_usleep(useconds_t usec); * event - The instance of struct sigevent that describes how to signal * the client. * code - Source: SI_USER, SI_QUEUE, SI_TIMER, SI_ASYNCIO, or SI_MESGQ + * work - The work structure to queue * * Returned Value: * This is an internal OS interface and should not be used by applications. @@ -453,6 +478,27 @@ int nxsig_usleep(useconds_t usec); * ****************************************************************************/ -int nxsig_notification(pid_t pid, FAR struct sigevent *event, int code); +int nxsig_notification(pid_t pid, FAR struct sigevent *event, + int code, FAR struct sigwork_s *work); + +/**************************************************************************** + * Name: nxsig_cancel_notification + * + * Description: + * Cancel the notification if it doesn't send yet. + * + * Input Parameters: + * work - The work structure to cancel + * + * Returned Value: + * None + * + ****************************************************************************/ + +#ifdef CONFIG_SIG_EVTHREAD +void nxsig_cancel_notification(FAR struct sigwork_s *work); +#else + #define nxsig_cancel_notification(work) (void)(work) +#endif #endif /* __INCLUDE_NUTTX_SIGNAL_H */ diff --git a/libs/libc/aio/lio_listio.c b/libs/libc/aio/lio_listio.c index d194a45f5a2..d6e42a76bb9 100644 --- a/libs/libc/aio/lio_listio.c +++ b/libs/libc/aio/lio_listio.c @@ -192,7 +192,7 @@ static void lio_sighandler(int signo, siginfo_t *info, void *ucontext) /* Signal the client */ DEBUGVERIFY(nxsig_notification(sighand->pid, &sighand->sig, - SI_ASYNCIO)); + SI_ASYNCIO, &aiocbp->aio_sigwork)); /* And free the container */ @@ -676,7 +676,8 @@ int lio_listio(int mode, FAR struct aiocb *const list[], int nent, } else { - status = nxsig_notification(getpid(), sig, SI_ASYNCIO); + status = nxsig_notification(getpid(), sig, + SI_ASYNCIO, &aiocbp->aio_sigwork); if (status < 0 && ret == OK) { /* Something bad happened while performing the notification diff --git a/sched/mqueue/mq_desclose.c b/sched/mqueue/mq_desclose.c index 87de025352e..d49b3c0b48e 100644 --- a/sched/mqueue/mq_desclose.c +++ b/sched/mqueue/mq_desclose.c @@ -116,6 +116,7 @@ void nxmq_desclose_group(mqd_t mqdes, FAR struct task_group_s *group) memset(&msgq->ntevent, 0, sizeof(struct sigevent)); msgq->ntpid = INVALID_PROCESS_ID; msgq->ntmqdes = NULL; + nxsig_cancel_notification(&msgq->ntwork); } #endif diff --git a/sched/mqueue/mq_descreate.c b/sched/mqueue/mq_descreate.c index 47dad5bd3bc..f4e66101cf4 100644 --- a/sched/mqueue/mq_descreate.c +++ b/sched/mqueue/mq_descreate.c @@ -53,8 +53,6 @@ #include #include -#include "signal/signal.h" - #include "mqueue/mqueue.h" /**************************************************************************** diff --git a/sched/mqueue/mq_notify.c b/sched/mqueue/mq_notify.c index a6abf3d92ce..2e7a8c17dd9 100644 --- a/sched/mqueue/mq_notify.c +++ b/sched/mqueue/mq_notify.c @@ -39,7 +39,6 @@ #include -#include #include #include #include @@ -182,6 +181,7 @@ int mq_notify(mqd_t mqdes, FAR const struct sigevent *notification) memset(&msgq->ntevent, 0, sizeof(struct sigevent)); msgq->ntpid = INVALID_PROCESS_ID; msgq->ntmqdes = NULL; + nxsig_cancel_notification(&msgq->ntwork); } sched_unlock(); diff --git a/sched/mqueue/mq_sndinternal.c b/sched/mqueue/mq_sndinternal.c index 072248a6822..4873d2d9599 100644 --- a/sched/mqueue/mq_sndinternal.c +++ b/sched/mqueue/mq_sndinternal.c @@ -52,7 +52,6 @@ #include #include #include -#include #include #include "sched/sched.h" @@ -414,7 +413,8 @@ int nxmq_do_send(mqd_t mqdes, FAR struct mqueue_msg_s *mqmsg, /* Notification the client */ - DEBUGVERIFY(nxsig_notification(pid, &event, SI_MESGQ)); + DEBUGVERIFY(nxsig_notification(pid, &event, + SI_MESGQ, &msgq->ntwork)); } #endif diff --git a/sched/mqueue/mqueue.h b/sched/mqueue/mqueue.h index 60401de4042..0602601b536 100644 --- a/sched/mqueue/mqueue.h +++ b/sched/mqueue/mqueue.h @@ -49,7 +49,6 @@ #include #include #include -#include #include diff --git a/sched/signal/Make.defs b/sched/signal/Make.defs index 8028be5e013..7993d58e133 100644 --- a/sched/signal/Make.defs +++ b/sched/signal/Make.defs @@ -48,10 +48,6 @@ ifeq ($(CONFIG_SIG_DEFAULT),y) CSRCS += sig_default.c endif -ifeq ($(CONFIG_SIG_EVTHREAD),y) -CSRCS += sig_evthread.c -endif - ifneq ($(CONFIG_DISABLE_POLL),y) CSRCS += sig_ppoll.c sig_pselect.c endif diff --git a/sched/signal/sig_evthread.c b/sched/signal/sig_evthread.c deleted file mode 100644 index 66fbaffc93c..00000000000 --- a/sched/signal/sig_evthread.c +++ /dev/null @@ -1,175 +0,0 @@ -/**************************************************************************** - * sched/signal/sig_evthread.c - * - * Copyright (C) 2015, 2017-2018 Gregory Nutt. All rights reserved. - * Author: Gregory Nutt - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * 3. Neither the name NuttX nor the names of its contributors may be - * used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS - * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED - * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - ****************************************************************************/ - -/**************************************************************************** - * Included Files - ****************************************************************************/ - -#include - -#include -#include -#include -#include - -#include -#include - -#ifdef CONFIG_SIG_EVTHREAD - -/**************************************************************************** - * Pre-processor Definitions - ****************************************************************************/ - -/* Use the low-prioriry work queue is it is available */ - -#if defined(CONFIG_SCHED_LPWORK) -# define NTWORK LPWORK -#elif defined(CONFIG_SCHED_HPWORK) -# define NTWORK HPWORK -#else -# error Work queue is not enabled -#endif - -/**************************************************************************** - * Private Type Definitions - ****************************************************************************/ - -/* This structure retains all that is necessary to perform the notification */ - -struct sig_evthread_s -{ - struct work_s nt_work; /* Work queue structure */ - union sigval nt_value; /* Data passed with notification */ - sigev_notify_function_t nt_func; /* Notification function */ -}; - -/**************************************************************************** - * Private Functions - ****************************************************************************/ - -/**************************************************************************** - * Name: nxsig_evthread_worker - * - * Description: - * Perform the callback from the context of the worker thread. - * - * Input Parameters: - * arg - Work argument. - * - * Returned Value: - * None. - * - ****************************************************************************/ - -static void nxsig_evthread_worker(FAR void *arg) -{ - FAR struct sig_evthread_s *notify = (FAR struct sig_evthread_s *)arg; - - DEBUGASSERT(notify != NULL); - - /* Perform the callback */ - -#ifdef CONFIG_CAN_PASS_STRUCTS - notify->nt_func(notify->nt_value); -#else - notify->nt_func(notify->nt_value.sival_ptr); -#endif - - /* Free the alloated notification parameters */ - - kmm_free(notify); -} - -/**************************************************************************** - * Public Functions - ****************************************************************************/ - -/**************************************************************************** - * Name: nxsig_evthread - * - * Description: - * Notify a client a signal event via a function call. This function is - * an internal OS interface that implements the common logic for signal - * event notification for the case of SIGEV_THREAD. - * - * Input Parameters: - * pid - The task/thread ID a the client thread to be signaled. - * event - The instance of struct sigevent that describes how to signal - * the client. - * - * Returned Value: - * This is an internal OS interface and should not be used by applications. - * It follows the NuttX internal error return policy: Zero (OK) is - * returned on success. A negated errno value is returned on failure. - * - ****************************************************************************/ - -int nxsig_evthread(pid_t pid, FAR struct sigevent *event) -{ - FAR struct sig_evthread_s *notify; - DEBUGASSERT(event != NULL && event->sigev_notify_function != NULL); - int ret; - - /* Allocate a structure to hold the notification information */ - - notify = kmm_zalloc(sizeof(struct sig_evthread_s)); - if (notify == NULL) - { - return -ENOMEM; - } - - /* Initialize the notification information */ - -#ifdef CONFIG_CAN_PASS_STRUCTS - notify->nt_value = event->sigev_value; -#else - notify->nt_value.sival_ptr = event->sigev_value.sival_ptr; -#endif - notify->nt_func = event->sigev_notify_function; - - /* Then queue the work */ - - ret = work_queue(NTWORK, ¬ify->nt_work, nxsig_evthread_worker, - notify, 0); - if (ret < 0) - { - kmm_free(notify); - } - - return ret; -} - -#endif /* CONFIG_SIG_EVTHREAD */ diff --git a/sched/signal/sig_notification.c b/sched/signal/sig_notification.c index 0634e93a3e4..5cb6fc62ed6 100644 --- a/sched/signal/sig_notification.c +++ b/sched/signal/sig_notification.c @@ -50,6 +50,38 @@ #include "sched/sched.h" #include "signal/signal.h" +/**************************************************************************** + * Name: nxsig_notification_worker + * + * Description: + * Perform the callback from the context of the worker thread. + * + * Input Parameters: + * arg - Work argument. + * + * Returned Value: + * None. + * + ****************************************************************************/ + +#ifdef CONFIG_SIG_EVTHREAD +static void nxsig_notification_worker(FAR void *arg) +{ + FAR struct sigwork_s *work = (FAR struct sigwork_s *)arg; + + DEBUGASSERT(work != NULL); + + /* Perform the callback */ + +#ifdef CONFIG_CAN_PASS_STRUCTS + work->func(work->value); +#else + work->func(work->value.sival_ptr); +#endif +} + +#endif /* CONFIG_SIG_EVTHREAD */ + /**************************************************************************** * Public Functions ****************************************************************************/ @@ -66,6 +98,7 @@ * event - The instance of struct sigevent that describes how to signal * the client. * code - Source: SI_USER, SI_QUEUE, SI_TIMER, SI_ASYNCIO, or SI_MESGQ + * work - The work structure to queue * * Returned Value: * This is an internal OS interface and should not be used by applications. @@ -74,7 +107,8 @@ * ****************************************************************************/ -int nxsig_notification(pid_t pid, FAR struct sigevent *event, int code) +int nxsig_notification(pid_t pid, FAR struct sigevent *event, + int code, FAR struct sigwork_s *work) { sinfo("pid=%p signo=%d code=%d sival_ptr=%p\n", pid, event->sigev_signo, code, event->sigev_value.sival_ptr); @@ -109,10 +143,42 @@ int nxsig_notification(pid_t pid, FAR struct sigevent *event, int code) else if (event->sigev_notify == SIGEV_THREAD) { - return nxsig_evthread(pid, event); + /* Initialize the work information */ + +#ifdef CONFIG_CAN_PASS_STRUCTS + work->value = event->sigev_value; +#else + work->value.sival_ptr = event->sigev_value.sival_ptr; +#endif + work->func = event->sigev_notify_function; + + /* Then queue the work */ + + return work_queue(LPWORK, &work->work, + nxsig_notification_worker, work, 0); } #endif return event->sigev_notify == SIGEV_NONE ? OK : -ENOSYS; } +/**************************************************************************** + * Name: nxsig_cancel_notification + * + * Description: + * Cancel the notification if it doesn't send yet. + * + * Input Parameters: + * work - The work structure to cancel + * + * Returned Value: + * None + * + ****************************************************************************/ + +#ifdef CONFIG_SIG_EVTHREAD +void nxsig_cancel_notification(FAR struct sigwork_s *work) +{ + work_cancel(LPWORK, &work->work); +} +#endif diff --git a/sched/signal/signal.h b/sched/signal/signal.h index 56289efad81..87710bd6877 100644 --- a/sched/signal/signal.h +++ b/sched/signal/signal.h @@ -207,9 +207,6 @@ FAR sigq_t *nxsig_alloc_pendingsigaction(void); void nxsig_deliver(FAR struct tcb_s *stcb); FAR sigactq_t *nxsig_find_action(FAR struct task_group_s *group, int signo); int nxsig_lowest(FAR sigset_t *set); -#if defined(CONFIG_SIG_EVTHREAD) && defined(CONFIG_BUILD_FLAT) -int nxsig_evthread(pid_t pid, FAR struct sigevent *event); -#endif void nxsig_release_pendingsigaction(FAR sigq_t *sigq); void nxsig_release_pendingsignal(FAR sigpendq_t *sigpend); FAR sigpendq_t *nxsig_remove_pendingsignal(FAR struct tcb_s *stcb, int signo); diff --git a/sched/timer/timer.h b/sched/timer/timer.h index a700320a390..5a8aaf0f1fb 100644 --- a/sched/timer/timer.h +++ b/sched/timer/timer.h @@ -44,9 +44,9 @@ #include #include -#include #include +#include #include /**************************************************************************** @@ -65,13 +65,14 @@ struct posix_timer_s { FAR struct posix_timer_s *flink; - uint8_t pt_flags; /* See PT_FLAGS_* definitions */ - uint8_t pt_crefs; /* Reference count */ - pid_t pt_owner; /* Creator of timer */ - int pt_delay; /* If non-zero, used to reset repetitive timers */ - int pt_last; /* Last value used to set watchdog */ - WDOG_ID pt_wdog; /* The watchdog that provides the timing */ - struct sigevent pt_event; /* Notification information */ + uint8_t pt_flags; /* See PT_FLAGS_* definitions */ + uint8_t pt_crefs; /* Reference count */ + pid_t pt_owner; /* Creator of timer */ + int pt_delay; /* If non-zero, used to reset repetitive timers */ + int pt_last; /* Last value used to set watchdog */ + WDOG_ID pt_wdog; /* The watchdog that provides the timing */ + struct sigevent pt_event; /* Notification information */ + struct sigwork_s pt_work; }; /**************************************************************************** diff --git a/sched/timer/timer_release.c b/sched/timer/timer_release.c index 2132152fe10..5d2c8d7c14f 100644 --- a/sched/timer/timer_release.c +++ b/sched/timer/timer_release.c @@ -140,6 +140,10 @@ int timer_release(FAR struct posix_timer_s *timer) (void)wd_delete(timer->pt_wdog); + /* Cancel any pending notification */ + + nxsig_cancel_notification(&timer->pt_work); + /* Release the timer structure */ timer_free(timer); diff --git a/sched/timer/timer_settime.c b/sched/timer/timer_settime.c index 99aa89029ed..bb89d466d86 100644 --- a/sched/timer/timer_settime.c +++ b/sched/timer/timer_settime.c @@ -46,7 +46,6 @@ #include #include -#include #include "clock/clock.h" #include "timer/timer.h" @@ -86,7 +85,8 @@ static void timer_timeout(int argc, wdparm_t itimer); static inline void timer_signotify(FAR struct posix_timer_s *timer) { - DEBUGVERIFY(nxsig_notification(timer->pt_owner, &timer->pt_event, SI_TIMER)); + DEBUGVERIFY(nxsig_notification(timer->pt_owner, &timer->pt_event, + SI_TIMER, &timer->pt_work)); } /**************************************************************************** @@ -288,6 +288,10 @@ int timer_settime(timer_t timerid, int flags, (void)wd_cancel(timer->pt_wdog); + /* Cancel any pending notification */ + + nxsig_cancel_notification(&timer->pt_work); + /* If the it_value member of value is zero, the timer will not be re-armed */ if (value->it_value.tv_sec <= 0 && value->it_value.tv_nsec <= 0) diff --git a/wireless/ieee802154/mac802154_device.c b/wireless/ieee802154/mac802154_device.c index dd8f8824167..929f24ca036 100644 --- a/wireless/ieee802154/mac802154_device.c +++ b/wireless/ieee802154/mac802154_device.c @@ -122,6 +122,7 @@ struct mac802154_chardevice_s bool md_notify_registered; pid_t md_notify_pid; struct sigevent md_notify_event; + struct sigwork_s md_notify_work; #endif }; @@ -768,7 +769,7 @@ static int mac802154dev_notify(FAR struct mac802154_maccb_s *maccb, { dev->md_notify_event.sigev_value.sival_int = primitive->type; nxsig_notification(dev->md_notify_pid, &dev->md_notify_event, - SI_QUEUE); + SI_QUEUE, &dev->md_notify_work); } #endif diff --git a/wireless/ieee802154/mac802154_netdev.c b/wireless/ieee802154/mac802154_netdev.c index 6f40d8dd181..eb95af7d165 100644 --- a/wireless/ieee802154/mac802154_netdev.c +++ b/wireless/ieee802154/mac802154_netdev.c @@ -165,6 +165,7 @@ struct macnet_driver_s bool md_notify_registered; pid_t md_notify_pid; struct sigevent md_notify_event; + struct sigwork_s md_notify_work; #endif }; @@ -446,7 +447,7 @@ static int macnet_notify(FAR struct mac802154_maccb_s *maccb, { priv->md_notify_event.sigev_value.sival_int = primitive->type; nxsig_notification(priv->md_notify_pid, &priv->md_notify_event, - SI_QUEUE); + SI_QUEUE, &priv->md_notify_work); } #endif