From 20814acad25d5615753a8c7cbb176d0938a28ae6 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Sun, 9 Sep 2018 11:57:25 -0600 Subject: [PATCH] sched/signal: In signal notification facility, use sigqueue() to notify vs. kill(). With sigqueue, we can pass more info (but still not enough). --- include/nuttx/signal.h | 8 ++ net/netdev/netdown_notifier.c | 153 ++++++++++++++++++++++++++++++++++ net/tcp/tcp.h | 8 ++ net/tcp/tcp_notifier.c | 8 ++ net/udp/udp.h | 8 ++ net/udp/udp_notifier.c | 8 ++ sched/signal/sig_notifier.c | 21 ++++- 7 files changed, 212 insertions(+), 2 deletions(-) create mode 100644 net/netdev/netdown_notifier.c diff --git a/include/nuttx/signal.h b/include/nuttx/signal.h index befc6ab684..a1d7762bee 100644 --- a/include/nuttx/signal.h +++ b/include/nuttx/signal.h @@ -481,6 +481,10 @@ int nxsig_evthread(pid_t pid, FAR struct sigevent *event); * to block signal delivery. The signal will be delivered once the * signal is removed from the sigprocmask. * + * NOTE: If sigwaitinfo() or sigtimedwait() are used to catch the signal + * then then qualifier value may be recovered in the sival_ptr value of + * the struct siginfo instance. + * * Input Parameters: * pid - The PID to be notified. If a zero value is provided, * then the PID of the calling thread will be used. @@ -538,6 +542,10 @@ int nxsig_notifier_teardown(int key); * the highest priority thread will get the resource. Lower priority * threads will need to call nxsig_notify once again. * + * NOTE: If sigwaitinfo() or sigtimedwait() are used to catch the signal + * then then qualifier value may be obtained in the sival_ptr value of + * the struct siginfo instance. + * * Input Parameters: * evtype - The type of the event that just occurred. * qualifier - Event qualifier to distinguish different cases of the diff --git a/net/netdev/netdown_notifier.c b/net/netdev/netdown_notifier.c new file mode 100644 index 0000000000..de0c22bb20 --- /dev/null +++ b/net/netdev/netdown_notifier.c @@ -0,0 +1,153 @@ +/**************************************************************************** + * net/netdev/netdown_notifier.c + * + * Copyright (C) 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 "netdev/netdev.h" + +#ifdef CONFIG_NETDOWN_NOTIFIER + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: netdown_notifier_setup + * + * Description: + * Set up to notify the specified PID with the provided signal number. + * + * NOTE: To avoid race conditions, the caller should set the sigprocmask + * to block signal delivery. The signal will be delivered once the + * signal is removed from the sigprocmask. + * + * Input Parameters: + * pid - The PID to be notified. If a zero value is provided, then the + * PID of the calling thread will be used. + * signo - The signal number to use with the notification. + * dev - The network driver to be monitored + * + * Returned Value: + * > 0 - The signal notification is in place. The returned value is a + * key that may be used later in a call to + * netdown_notifier_teardown(). + * == 0 - The the device is already down. No signal notification will + * be provided. + * < 0 - An unexpected error occurred and no signal will be sent. The + * returned value is a negated errno value that indicates the + * nature of the failure. + * + ****************************************************************************/ + +int netdown_notifier_setup(int pid, int signo, FAR struct net_driver_s *dev) +{ + /* If network driver is already down, then return zero without setting up + * the notification. + */ + + if ((dev->d_flags & IFF_UP) == 0) + { + return 0; + } + + /* Otherwise, this is just a simple wrapper around nxsig_notifer_setup(). */ + + return nxsig_notifier_setup(pid, signo, NXSIG_NET_DOWN, dev); +} + +/**************************************************************************** + * Name: netdown_notifier_teardown + * + * Description: + * Eliminate a TCP read-ahead notification previously setup by + * netdown_notifier_setup(). This function should only be called if the + * notification should be aborted prior to the notification. The + * notification will automatically be torn down after the signal is sent. + * + * Input Parameters: + * key - The key value returned from a previous call to + * netdown_notifier_setup(). + * + * Returned Value: + * Zero (OK) is returned on success; a negated errno value is returned on + * any failure. + * + ****************************************************************************/ + +int netdown_notifier_teardown(int key) +{ + /* This is just a simple wrapper around nxsig_notifier_teardown(). */ + + return nxsig_notifier_teardown(key); +} + +/**************************************************************************** + * Name: netdown_notifier_signal + * + * Description: + * Read-ahead data has been buffered. Signal all threads waiting for + * read-ahead data to become available. + * + * When the read-ahead data becomes available, *all* of the waiters in + * this thread will be signaled. If there are multiple waiters then only + * the highest priority thread will get the data. Lower priority threads + * will need to call netdown_notifier_setup() once again. + * + * Input Parameters: + * dev - The TCP connection where read-ahead data was just buffered. + * + * Returned Value: + * None. + * + ****************************************************************************/ + +void netdown_notifier_signal(FAR struct net_driver_s *dev) +{ + /* This is just a simple wrapper around nxsig_notifier_signal(). */ + + return nxsig_notifier_signal(NXSIG_NET_DOWN, dev); +} + +#endif /* CONFIG_NETDOWN_NOTIFIER */ diff --git a/net/tcp/tcp.h b/net/tcp/tcp.h index e7539ecc22..bfc065fca7 100644 --- a/net/tcp/tcp.h +++ b/net/tcp/tcp.h @@ -1552,6 +1552,10 @@ int tcp_pollteardown(FAR struct socket *psock, FAR struct pollfd *fds); * to block signal delivery. The signal will be delivered once the * signal is removed from the sigprocmask. * + * NOTE: If sigwaitinfo() or sigtimedwait() are used to catch the signal + * then then TCP connection structure pointer may be recovered in the + * sival_ptr value of the struct siginfo instance. + * * Input Parameters: * pid - The PID to be notified. If a zero value is provided, then the * PID of the calling thread will be used. @@ -1609,6 +1613,10 @@ int tcp_notifier_teardown(int key); * the highest priority thread will get the data. Lower priority threads * will need to call tcp_notifier_setup() once again. * + * NOTE: If sigwaitinfo() or sigtimedwait() are used to catch the signal + * then then TCP connection structure pointer may be obtained in the + * sival_ptr value of the struct siginfo instance. + * * Input Parameters: * conn - The TCP connection where read-ahead data was just buffered. * diff --git a/net/tcp/tcp_notifier.c b/net/tcp/tcp_notifier.c index 905eb07f05..0491aa8397 100644 --- a/net/tcp/tcp_notifier.c +++ b/net/tcp/tcp_notifier.c @@ -62,6 +62,10 @@ * to block signal delivery. The signal will be delivered once the * signal is removed from the sigprocmask. * + * NOTE: If sigwaitinfo() or sigtimedwait() are used to catch the signal + * then then TCP connection structure pointer may be recovered in the + * sival_ptr value of the struct siginfo instance. + * * Input Parameters: * pid - The PID to be notified. If a zero value is provided, then the * PID of the calling thread will be used. @@ -134,6 +138,10 @@ int tcp_notifier_teardown(int key) * the highest priority thread will get the data. Lower priority threads * will need to call tcp_notifier_setup() once again. * + * NOTE: If sigwaitinfo() or sigtimedwait() are used to catch the signal + * then then TCP connection structure pointer may be obtained in the + * sival_ptr value of the struct siginfo instance. + * * Input Parameters: * conn - The TCP connection where read-ahead data was just buffered. * diff --git a/net/udp/udp.h b/net/udp/udp.h index 24132eaeb7..afb91ec065 100644 --- a/net/udp/udp.h +++ b/net/udp/udp.h @@ -653,6 +653,10 @@ int udp_pollteardown(FAR struct socket *psock, FAR struct pollfd *fds); * to block signal delivery. The signal will be delivered once the * signal is removed from the sigprocmask. * + * NOTE: If sigwaitinfo() or sigtimedwait() are used to catch the signal + * then then UDP connection structure pointer may be recovered in the + * sival_ptr value of the struct siginfo instance. + * * Input Parameters: * pid - The PID to be notified. If a zero value is provided, then the * PID of the calling thread will be used. @@ -710,6 +714,10 @@ int udp_notifier_teardown(int key); * the highest priority thread will get the data. Lower priority threads * will need to call udp_notifier_setup() once again. * + * NOTE: If sigwaitinfo() or sigtimedwait() are used to catch the signal + * then then UDP connection structure pointer may be obtained in the + * sival_ptr value of the struct siginfo instance. + * * Input Parameters: * conn - The UDP connection where read-ahead data was just buffered. * diff --git a/net/udp/udp_notifier.c b/net/udp/udp_notifier.c index f2a2af1cd8..31f476edc7 100644 --- a/net/udp/udp_notifier.c +++ b/net/udp/udp_notifier.c @@ -62,6 +62,10 @@ * to block signal delivery. The signal will be delivered once the * signal is removed from the sigprocmask. * + * NOTE: If sigwaitinfo() or sigtimedwait() are used to catch the signal + * then then UDP connection structure pointer may be recovered in the + * sival_ptr value of the struct siginfo instance. + * * Input Parameters: * pid - The PID to be notified. If a zero value is provided, then the * PID of the calling thread will be used. @@ -134,6 +138,10 @@ int udp_notifier_teardown(int key) * the highest priority thread will get the data. Lower priority threads * will need to call udp_notifier_setup() once again. * + * NOTE: If sigwaitinfo() or sigtimedwait() are used to catch the signal + * then then UDP connection structure pointer may be obtained in the + * sival_ptr value of the struct siginfo instance. + * * Input Parameters: * conn - The UDP connection where read-ahead data was just buffered. * diff --git a/sched/signal/sig_notifier.c b/sched/signal/sig_notifier.c index 1bbcf989ec..f9e948c61e 100644 --- a/sched/signal/sig_notifier.c +++ b/sched/signal/sig_notifier.c @@ -255,6 +255,10 @@ void nxsig_notifier_initialize(void) * to block signal delivery. The signal will be delivered once the * signal is removed from the sigprocmask. * + * NOTE: If sigwaitinfo() or sigtimedwait() are used to catch the signal + * then then qualifier value may be recovered in the sival_ptr value of + * the struct siginfo instance. + * * Input Parameters: * pid - The PID to be notified. If a zero value is provided, * then the PID of the calling thread will be used. @@ -403,6 +407,10 @@ int nxsig_notifier_teardown(int key) * the highest priority thread will get the resource. Lower priority * threads will need to call nxsig_notify once again. * + * NOTE: If sigwaitinfo() or sigtimedwait() are used to catch the signal + * then then qualifier value may be obtained in the sival_ptr value of + * the struct siginfo instance. + * * Input Parameters: * evtype - The type of the event that just occurred. * qualifier - Event qualifier to distinguish different cases of the @@ -444,6 +452,10 @@ void nxsig_notifier_signal(enum nxsig_evtype_e evtype, notifier != NULL; notifier = next) { +#ifdef CONFIG_CAN_PASS_STRUCTS + union sigval value; +#endif + /* Set up for the next time through the loop (in case the entry is * removed from the list). */ @@ -469,8 +481,13 @@ void nxsig_notifier_signal(enum nxsig_evtype_e evtype, /* Signal the waiter */ - (void)nxsig_kill(notifier->pid, notifier->signo); - +#ifdef CONFIG_CAN_PASS_STRUCTS + value.sival_ptr = notifier->qualifier; + (void)nxsig_queue(notifier->pid, notifier->signo, value); +#else + (void)nxsig_queue(notifier->pid, notifier->signo, + notifier->qualifier); +#endif /* Free the notification by returning it to the free list */ nxsig_notifier_free(notifier);