sched/signal: Add a generic signal notification facility. Modify the custom IOB available notifier so that it is now just a wrapper around this generic signal notification. This generic signal notification faility will, eventually, be used to support network polling.
Squashed commit of the following: mm/iob: The IOB available notifier is now just a wrapper around the common signal notifier. sched/signal: Add a generic signal notification facility. sched/signal/sig_evthread.c: More trivial naming changes. sched/signal: Rename nxsig_notification() to nxsig_evthread() to make forthcoming naming additions more consistent.
This commit is contained in:
parent
0eb1beee63
commit
fc127fd297
@ -111,10 +111,10 @@ int aio_signal(pid_t pid, FAR struct aiocb *aiocbp)
|
|||||||
|
|
||||||
else if (aiocbp->aio_sigevent.sigev_notify == SIGEV_THREAD)
|
else if (aiocbp->aio_sigevent.sigev_notify == SIGEV_THREAD)
|
||||||
{
|
{
|
||||||
ret = nxsig_notification(pid, &aiocbp->aio_sigevent);
|
ret = nxsig_evthread(pid, &aiocbp->aio_sigevent);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
ferr("ERROR: nxsig_notification failed: %d\n", ret);
|
ferr("ERROR: nxsig_evthread failed: %d\n", ret);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -205,7 +205,7 @@ int iob_navail(void);
|
|||||||
FAR struct iob_s *iob_free(FAR struct iob_s *iob);
|
FAR struct iob_s *iob_free(FAR struct iob_s *iob);
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: iob_notify_setup
|
* Name: iob_notifier_setup
|
||||||
*
|
*
|
||||||
* Description:
|
* Description:
|
||||||
* Set up to notify the specified PID with the provided signal number.
|
* Set up to notify the specified PID with the provided signal number.
|
||||||
@ -220,14 +220,11 @@ FAR struct iob_s *iob_free(FAR struct iob_s *iob);
|
|||||||
* signo - The signal number to use with the notification.
|
* signo - The signal number to use with the notification.
|
||||||
*
|
*
|
||||||
* Returned Value:
|
* Returned Value:
|
||||||
* > 0 - There are already free IOBs and this this number of free IOBs
|
* > 0 - The signal notification is in place. The returned value is a
|
||||||
* (CAUTION: This value is volatile). No signal notification
|
* key that may be used later in a call to
|
||||||
* will be provided.
|
* iob_notifier_teardown().
|
||||||
* == 0 - There are no free IOBs. A signal will be sent to 'pid' when
|
* == 0 - There are already free IOBs. No signal notification will be
|
||||||
* at least one IOB is available. That IOB is *not* reserved for
|
* provided.
|
||||||
* the caller. Hence, due to race conditions, it could be taken
|
|
||||||
* by some other task. In that event, the caller should call
|
|
||||||
* sig_notify again.
|
|
||||||
* < 0 - An unexpected error occurred and no signal will be sent. The
|
* < 0 - An unexpected error occurred and no signal will be sent. The
|
||||||
* returned value is a negated errno value that indicates the
|
* returned value is a negated errno value that indicates the
|
||||||
* nature of the failure.
|
* nature of the failure.
|
||||||
@ -235,21 +232,21 @@ FAR struct iob_s *iob_free(FAR struct iob_s *iob);
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#ifdef CONFIG_IOB_NOTIFIER
|
#ifdef CONFIG_IOB_NOTIFIER
|
||||||
int iob_notify_setup(int pid, int signo);
|
int iob_notifier_setup(int pid, int signo);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: iob_notify_teardown
|
* Name: iob_notifier_teardown
|
||||||
*
|
*
|
||||||
* Description:
|
* Description:
|
||||||
* Eliminate an IOB notification previously setup by iob_notify_setup().
|
* Eliminate an IOB notification previously setup by iob_notifier_setup().
|
||||||
* This function should only be called if the notification should be
|
* This function should only be called if the notification should be
|
||||||
* aborted prior to the notification. The notification will automatically
|
* aborted prior to the notification. The notification will automatically
|
||||||
* be torn down after the signal is sent.
|
* be torn down after the signal is sent.
|
||||||
*
|
*
|
||||||
* Input Parameters:
|
* Input Parameters:
|
||||||
* pid - The PID whose notification will be torn down. If a zero value
|
* key - The key value returned from a previous call to
|
||||||
* is provided, then the PID of the calling thread will be used.
|
* iob_notifier_setup().
|
||||||
*
|
*
|
||||||
* Returned Value:
|
* Returned Value:
|
||||||
* Zero (OK) is returned on success; a negated errno value is returned on
|
* Zero (OK) is returned on success; a negated errno value is returned on
|
||||||
@ -258,7 +255,7 @@ int iob_notify_setup(int pid, int signo);
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#ifdef CONFIG_IOB_NOTIFIER
|
#ifdef CONFIG_IOB_NOTIFIER
|
||||||
int iob_notify_teardown(int pid, int signo);
|
int iob_notifier_teardown(int key);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
|
@ -46,6 +46,22 @@
|
|||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Public Types
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/* This is an enumeration of the various signal events that may be
|
||||||
|
* notified via nxig_notifier_signal().
|
||||||
|
*/
|
||||||
|
|
||||||
|
enum nxsig_evtype_e
|
||||||
|
{
|
||||||
|
NXSIG_IOB_AVAIL = 1, /* Signal availability of an IOB */
|
||||||
|
NXSIG_NET_DOWN, /* Signal that the network is down */
|
||||||
|
NXSIG_TCP_READAHEAD, /* Signal that TCP read-ahead data is available */
|
||||||
|
NXSIG_UDP_READAHEAD, /* Signal that TCP read-ahead data is available */
|
||||||
|
};
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Public Function Prototypes
|
* Public Function Prototypes
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
@ -431,7 +447,7 @@ unsigned int nxsig_sleep(unsigned int seconds);
|
|||||||
int nxsig_usleep(useconds_t usec);
|
int nxsig_usleep(useconds_t usec);
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: nxsig_notification
|
* Name: nxsig_evthread
|
||||||
*
|
*
|
||||||
* Description:
|
* Description:
|
||||||
* Notify a client a signal event via a function call. This function is
|
* Notify a client a signal event via a function call. This function is
|
||||||
@ -451,7 +467,89 @@ int nxsig_usleep(useconds_t usec);
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#if defined(CONFIG_SIG_EVTHREAD) && defined(CONFIG_BUILD_FLAT)
|
#if defined(CONFIG_SIG_EVTHREAD) && defined(CONFIG_BUILD_FLAT)
|
||||||
int nxsig_notification(pid_t pid, FAR struct sigevent *event);
|
int nxsig_evthread(pid_t pid, FAR struct sigevent *event);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: nxsig_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.
|
||||||
|
* evtype - The event type.
|
||||||
|
* qualifier - Event qualifier to distinguish different cases of the
|
||||||
|
* generic event type.
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* > 0 - The key which may be used later in a call to
|
||||||
|
* nxsig_notifier_teardown().
|
||||||
|
* == 0 - Not used (reserved for wrapper functions).
|
||||||
|
* < 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.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#ifdef CONFIG_SIG_NOTIFIER
|
||||||
|
int nxsig_notifier_setup(int pid, int signo, enum nxsig_evtype_e evtype,
|
||||||
|
FAR void *qualifier);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: nxsig_notifier_teardown
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Eliminate a notification previously setup by nxsig_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
|
||||||
|
* nxsig_notifier_setup().
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* Zero (OK) is returned on success; a negated errno value is returned on
|
||||||
|
* any failure.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#ifdef CONFIG_SIG_NOTIFIER
|
||||||
|
int nxsig_notifier_teardown(int key);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: nxsig_notifier_signal
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* An event has just occurred. Signal all threads waiting for that event.
|
||||||
|
*
|
||||||
|
* When an IOB becomes available, *all* of the waiters in this thread will
|
||||||
|
* be signaled. If there are multiple waiters for a resource then only
|
||||||
|
* the highest priority thread will get the resource. Lower priority
|
||||||
|
* threads will need to call nxsig_notify once again.
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* evtype - The type of the event that just occurred.
|
||||||
|
* qualifier - Event qualifier to distinguish different cases of the
|
||||||
|
* generic event type.
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* None.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#ifdef CONFIG_SIG_NOTIFIER
|
||||||
|
void nxsig_notifier_signal(enum nxsig_evtype_e evtype,
|
||||||
|
FAR void *qualifier);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* __INCLUDE_NUTTX_SIGNAL_H */
|
#endif /* __INCLUDE_NUTTX_SIGNAL_H */
|
||||||
|
@ -207,7 +207,7 @@ static void lio_sighandler(int signo, siginfo_t *info, void *ucontext)
|
|||||||
|
|
||||||
else if (ighand->sig->sigev_notify == SIGEV_THREAD)
|
else if (ighand->sig->sigev_notify == SIGEV_THREAD)
|
||||||
{
|
{
|
||||||
DEBUGASSERT(nxsig_notification(sighand->pid, &sighand->sig));
|
DEBUGASSERT(nxsig_evthread(sighand->pid, &sighand->sig));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -713,7 +713,7 @@ int lio_listio(int mode, FAR struct aiocb *const list[], int nent,
|
|||||||
|
|
||||||
else if (sig && sig->sigev_notify == SIGEV_THREAD)
|
else if (sig && sig->sigev_notify == SIGEV_THREAD)
|
||||||
{
|
{
|
||||||
status = nxsig_notification(sighand->pid, &sighand->sig);
|
status = nxsig_evthread(sighand->pid, &sighand->sig);
|
||||||
if (status < 0 && ret == OK)
|
if (status < 0 && ret == OK)
|
||||||
{
|
{
|
||||||
/* Something bad happened while performing the notification
|
/* Something bad happened while performing the notification
|
||||||
|
@ -62,23 +62,13 @@ config IOB_THROTTLE
|
|||||||
config IOB_NOTIFIER
|
config IOB_NOTIFIER
|
||||||
bool "Support IOB notifications"
|
bool "Support IOB notifications"
|
||||||
default n
|
default n
|
||||||
|
select SIG_NOTIFIER
|
||||||
---help---
|
---help---
|
||||||
Enable building of IOB notifier logic that will send a signla to
|
Enable building of IOB notifier logic that will send a signla to
|
||||||
a kernel thread when an IOB is available. This is is a general
|
a kernel thread when an IOB is available. This is is a general
|
||||||
purpose notifier, but was developed specifically to support poll()
|
purpose notifier, but was developed specifically to support poll()
|
||||||
logic where the poll must wait for an IOB to become available.
|
logic where the poll must wait for an IOB to become available.
|
||||||
|
|
||||||
config IOB_NWAITERS
|
|
||||||
int "Number of IOB waiters"
|
|
||||||
default 4
|
|
||||||
range 1 32767
|
|
||||||
depends on IOB_NOTIFIER
|
|
||||||
---help---
|
|
||||||
If CONFIG_IOB_NOTIFIER is selected, then a static array will be
|
|
||||||
allocated to hold information about pending notifications. This
|
|
||||||
then determines an upper limit for the number of waiters that can
|
|
||||||
be supported.
|
|
||||||
|
|
||||||
config IOB_DEBUG
|
config IOB_DEBUG
|
||||||
bool "Force I/O buffer debug"
|
bool "Force I/O buffer debug"
|
||||||
default n
|
default n
|
||||||
|
@ -45,7 +45,7 @@ CSRCS += iob_trimhead.c iob_trimhead_queue.c iob_trimtail.c
|
|||||||
CSRCS += iob_navail.c
|
CSRCS += iob_navail.c
|
||||||
|
|
||||||
ifeq ($(CONFIG_IOB_NOTIFIER),y)
|
ifeq ($(CONFIG_IOB_NOTIFIER),y)
|
||||||
CSRCS += iob_notify.c
|
CSRCS += iob_notifier.c
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(CONFIG_DEBUG_FEATURES),y)
|
ifeq ($(CONFIG_DEBUG_FEATURES),y)
|
||||||
|
19
mm/iob/iob.h
19
mm/iob/iob.h
@ -155,19 +155,7 @@ FAR struct iob_qentry_s *iob_tryalloc_qentry(void);
|
|||||||
FAR struct iob_qentry_s *iob_free_qentry(FAR struct iob_qentry_s *iobq);
|
FAR struct iob_qentry_s *iob_free_qentry(FAR struct iob_qentry_s *iobq);
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: iob_notify_initialize
|
* Name: iob_notifier_signal
|
||||||
*
|
|
||||||
* Description:
|
|
||||||
* Set up the notification structure for normal operation.
|
|
||||||
*
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
#ifdef CONFIG_IOB_NOTIFIER
|
|
||||||
void iob_notify_initialize(void);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* Name: iob_notify_signal
|
|
||||||
*
|
*
|
||||||
* Description:
|
* Description:
|
||||||
* An IOB has become available. Signal all threads waiting for an IOB
|
* An IOB has become available. Signal all threads waiting for an IOB
|
||||||
@ -176,7 +164,7 @@ void iob_notify_initialize(void);
|
|||||||
* When an IOB becomes available, *all* of the waiters in this thread will
|
* When an IOB becomes available, *all* of the waiters in this thread will
|
||||||
* be signaled. If there are multiple waiters then only the highest
|
* be signaled. If there are multiple waiters then only the highest
|
||||||
* priority thread will get the IOB. Lower priority threads will need to
|
* priority thread will get the IOB. Lower priority threads will need to
|
||||||
* call iob_notify once again.
|
* call iob_notifier_setup() once again.
|
||||||
*
|
*
|
||||||
* Input Parameters:
|
* Input Parameters:
|
||||||
* None.
|
* None.
|
||||||
@ -187,9 +175,8 @@ void iob_notify_initialize(void);
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#ifdef CONFIG_IOB_NOTIFIER
|
#ifdef CONFIG_IOB_NOTIFIER
|
||||||
void iob_notify_signal(void);
|
void iob_notifier_signal(void);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* CONFIG_MM_IOB */
|
#endif /* CONFIG_MM_IOB */
|
||||||
#endif /* __MM_IOB_IOB_H */
|
#endif /* __MM_IOB_IOB_H */
|
||||||
|
|
||||||
|
@ -148,7 +148,7 @@ FAR struct iob_s *iob_free(FAR struct iob_s *iob)
|
|||||||
* when an IOB becomes available.
|
* when an IOB becomes available.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
iob_notify_signal();
|
iob_notifier_signal();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -155,12 +155,6 @@ void iob_initialize(void)
|
|||||||
nxsem_init(&g_qentry_sem, 0, CONFIG_IOB_NCHAINS);
|
nxsem_init(&g_qentry_sem, 0, CONFIG_IOB_NCHAINS);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_IOB_NOTIFIER
|
|
||||||
/* Initialize the IOB notification data structures */
|
|
||||||
|
|
||||||
iob_notify_initialize();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
initialized = true;
|
initialized = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
151
mm/iob/iob_notifier.c
Normal file
151
mm/iob/iob_notifier.c
Normal file
@ -0,0 +1,151 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* mm/iob/iob_notifier.c
|
||||||
|
*
|
||||||
|
* Copyright (C) 2018 Gregory Nutt. All rights reserved.
|
||||||
|
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||||
|
*
|
||||||
|
* 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 <nuttx/config.h>
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#include <nuttx/signal.h>
|
||||||
|
#include <nuttx/mm/iob.h>
|
||||||
|
|
||||||
|
#include "iob.h"
|
||||||
|
|
||||||
|
#ifdef CONFIG_IOB_NOTIFIER
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Public Functions
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: iob_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.
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* > 0 - The signal notification is in place. The returned value is a
|
||||||
|
* key that may be used later in a call to
|
||||||
|
* iob_notifier_teardown().
|
||||||
|
* == 0 - There are already free IOBs. 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 iob_notifier_setup(int pid, int signo)
|
||||||
|
{
|
||||||
|
/* If there are already free IOBs, then return zero without setting up the
|
||||||
|
* notification.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (iob_navail() > 0)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Otherwise, this is just a simple wrapper around nxsig_notifer_setup(). */
|
||||||
|
|
||||||
|
return nxsig_notifier_setup(pid, signo, NXSIG_IOB_AVAIL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: iob_notifier_teardown
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Eliminate an IOB notification previously setup by iob_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
|
||||||
|
* iob_notifier_setup().
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* Zero (OK) is returned on success; a negated errno value is returned on
|
||||||
|
* any failure.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
int iob_notifier_teardown(int key)
|
||||||
|
{
|
||||||
|
/* This is just a simple wrapper around nxsig_notifier_teardown(). */
|
||||||
|
|
||||||
|
return nxsig_notifier_teardown(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: iob_notifier_signal
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* An IOB has become available. Signal all threads waiting for an IOB
|
||||||
|
* that an IOB is available.
|
||||||
|
*
|
||||||
|
* When an IOB 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 IOB. Lower priority threads will need to
|
||||||
|
* call iob_notifier_setup() once again.
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* None.
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* None.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
void iob_notifier_signal(void)
|
||||||
|
{
|
||||||
|
/* This is just a simple wrapper around nxsig_notifier_signal(). */
|
||||||
|
|
||||||
|
return nxsig_notifier_signal(NXSIG_IOB_AVAIL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* CONFIG_IOB_NOTIFIER */
|
@ -1,394 +0,0 @@
|
|||||||
/****************************************************************************
|
|
||||||
* mm/iob/iob_notify.c
|
|
||||||
*
|
|
||||||
* Copyright (C) 2018 Gregory Nutt. All rights reserved.
|
|
||||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
|
||||||
*
|
|
||||||
* 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 <nuttx/config.h>
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <sched.h>
|
|
||||||
#include <assert.h>
|
|
||||||
|
|
||||||
#include <nuttx/irq.h>
|
|
||||||
#include <nuttx/signal.h>
|
|
||||||
#include <nuttx/semaphore.h>
|
|
||||||
#include <nuttx/mm/iob.h>
|
|
||||||
|
|
||||||
#include "iob.h"
|
|
||||||
|
|
||||||
#ifdef CONFIG_IOB_NOTIFIER
|
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* Private Types
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
/* This is the saved information for one IOB notification */
|
|
||||||
|
|
||||||
struct iob_notify_s
|
|
||||||
{
|
|
||||||
FAR struct iob_notify_s *flink; /* Supports a singly linked list */
|
|
||||||
uint8_t signo; /* The signal number for notification */
|
|
||||||
pid_t pid; /* The PID to be notified */
|
|
||||||
};
|
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* Private Data
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
/* This is a statically allocated pool of notification structures */
|
|
||||||
|
|
||||||
static struct iob_notify_s g_iobnotify_pool[CONFIG_IOB_NWAITERS];
|
|
||||||
|
|
||||||
/* This is a list of free notification structures */
|
|
||||||
|
|
||||||
static FAR struct iob_notify_s *g_iobnotify_free;
|
|
||||||
|
|
||||||
/* This is a singly linked list pending notifications. When an IOB becomes
|
|
||||||
* available, *all* of the waiters in this list will be signaled and the
|
|
||||||
* entry will be freed. If there are multiple waiters then only the highest
|
|
||||||
* priority thread will get the IOB. Lower priority threads will need to
|
|
||||||
* call iob_notify_setup() once again.
|
|
||||||
*/
|
|
||||||
|
|
||||||
static FAR struct iob_notify_s *g_iobnotify_pending;
|
|
||||||
|
|
||||||
/* This semaphore is used as mutex to enforce mutually exclusive access to
|
|
||||||
* the IOB notification structures.
|
|
||||||
*/
|
|
||||||
|
|
||||||
static sem_t g_iobnotify_sem;
|
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* Private Functions
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* Name: iob_notify_alloc
|
|
||||||
*
|
|
||||||
* Description:
|
|
||||||
* Allocate a notification structure by removing it from the free list.
|
|
||||||
*
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
static FAR struct iob_notify_s *iob_notify_alloc(void)
|
|
||||||
{
|
|
||||||
FAR struct iob_notify_s *notify;
|
|
||||||
|
|
||||||
notify = g_iobnotify_free;
|
|
||||||
if (notify != NULL)
|
|
||||||
{
|
|
||||||
g_iobnotify_free = notify->flink;
|
|
||||||
notify->flink = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return notify;
|
|
||||||
}
|
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* Name: iob_notify_free
|
|
||||||
*
|
|
||||||
* Description:
|
|
||||||
* Free a notification structure by returning it to the head of the free
|
|
||||||
* list.
|
|
||||||
*
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
static void iob_notify_free(FAR struct iob_notify_s *notify)
|
|
||||||
{
|
|
||||||
notify->flink = g_iobnotify_free;
|
|
||||||
g_iobnotify_free = notify;
|
|
||||||
}
|
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* Public Functions
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* Name: iob_notify_initialize
|
|
||||||
*
|
|
||||||
* Description:
|
|
||||||
* Set up the notification structure for normal operation.
|
|
||||||
*
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
void iob_notify_initialize(void)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
/* Add each notification structure to the free list */
|
|
||||||
|
|
||||||
for (i = 0; i < CONFIG_IOB_NWAITERS; i++)
|
|
||||||
{
|
|
||||||
FAR struct iob_notify_s *notify = &g_iobnotify_pool[i];
|
|
||||||
|
|
||||||
/* Add the pre-allocated notification to the head of the free list */
|
|
||||||
|
|
||||||
notify->flink = g_iobnotify_free;
|
|
||||||
g_iobnotify_free = notify;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Initialize the semaphore that enforces mutually exclusive access to the
|
|
||||||
* notification data structures.
|
|
||||||
*/
|
|
||||||
|
|
||||||
nxsem_init(&g_iobnotify_sem, 0, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* Name: iob_notify_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.
|
|
||||||
*
|
|
||||||
* Returned Value:
|
|
||||||
* > 0 - There are already free IOBs and this this number of free IOBs
|
|
||||||
* (CAUTION: This value is volatile). No signal notification
|
|
||||||
* will be provided.
|
|
||||||
* == 0 - There are no free IOBs. A signal will be sent to 'pid' when
|
|
||||||
* at least one IOB is available. That IOB is *not* reserved for
|
|
||||||
* the caller. Hence, due to race conditions, it could be taken
|
|
||||||
* by some other task. In that event, the caller should call
|
|
||||||
* sig_notify again.
|
|
||||||
* < 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 iob_notify_setup(int pid, int signo)
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
/* If the pid is zero, then use the pid of the calling thread */
|
|
||||||
|
|
||||||
if (pid <= 0)
|
|
||||||
{
|
|
||||||
pid = getpid();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Get exclusive access to the notifier data structures */
|
|
||||||
|
|
||||||
ret = nxsem_wait(&g_iobnotify_sem);
|
|
||||||
if (ret < 0)
|
|
||||||
{
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If there are already free IOBs, then just return the number of free
|
|
||||||
* IOBs.
|
|
||||||
*/
|
|
||||||
|
|
||||||
ret = iob_navail();
|
|
||||||
if (ret <= 0)
|
|
||||||
{
|
|
||||||
/* Allocate a new notification */
|
|
||||||
|
|
||||||
FAR struct iob_notify_s *notify = iob_notify_alloc();
|
|
||||||
if (notify == NULL)
|
|
||||||
{
|
|
||||||
ret = -ENOSPC;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Initialize the notification structure */
|
|
||||||
|
|
||||||
notify->pid = pid;
|
|
||||||
notify->signo = signo;
|
|
||||||
|
|
||||||
/* And add it to the head of the pending list */
|
|
||||||
|
|
||||||
notify->flink = g_iobnotify_pending;
|
|
||||||
g_iobnotify_pending = notify;
|
|
||||||
ret = OK;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
(void)nxsem_post(&g_iobnotify_sem);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* Name: iob_notify_teardown
|
|
||||||
*
|
|
||||||
* Description:
|
|
||||||
* Eliminate an IOB notification previously setup by iob_notify_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:
|
|
||||||
* pid - The PID whose notification will be torn down. If a zero value
|
|
||||||
* is provided, then the PID of the calling thread will be used.
|
|
||||||
*
|
|
||||||
* Returned Value:
|
|
||||||
* Zero (OK) is returned on success; a negated errno value is returned on
|
|
||||||
* any failure.
|
|
||||||
*
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
int iob_notify_teardown(int pid, int signo)
|
|
||||||
{
|
|
||||||
FAR struct iob_notify_s *notify;
|
|
||||||
FAR struct iob_notify_s *prev;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
/* If the pid is zero, then use the pid of the calling thread */
|
|
||||||
|
|
||||||
if (pid <= 0)
|
|
||||||
{
|
|
||||||
pid = getpid();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Get exclusive access to the notifier data structures */
|
|
||||||
|
|
||||||
ret = nxsem_wait(&g_iobnotify_sem);
|
|
||||||
if (ret < 0)
|
|
||||||
{
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Find the entry matching this PID in the g_iobnotify_pending list. We
|
|
||||||
* assume that there is only one.
|
|
||||||
*/
|
|
||||||
|
|
||||||
ret = -ENOENT;
|
|
||||||
for (prev = NULL, notify = g_iobnotify_pending;
|
|
||||||
notify != NULL;
|
|
||||||
prev = notify, notify = notify->flink)
|
|
||||||
{
|
|
||||||
/* Is this the one we were looking for? */
|
|
||||||
|
|
||||||
if (notify->pid == pid)
|
|
||||||
{
|
|
||||||
/* Yes, remove it from the pending list */
|
|
||||||
|
|
||||||
if (prev == NULL)
|
|
||||||
{
|
|
||||||
g_iobnotify_pending = notify->flink;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
prev->flink = notify->flink;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* And add it to the free list */
|
|
||||||
|
|
||||||
iob_notify_free(notify);
|
|
||||||
|
|
||||||
ret = OK;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
(void)nxsem_post(&g_iobnotify_sem);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* Name: iob_notify_signal
|
|
||||||
*
|
|
||||||
* Description:
|
|
||||||
* An IOB has become available. Signal all threads waiting for an IOB
|
|
||||||
* that an IOB is available.
|
|
||||||
*
|
|
||||||
* When an IOB 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 IOB. Lower priority threads will need to
|
|
||||||
* call iob_notify once again.
|
|
||||||
*
|
|
||||||
* Input Parameters:
|
|
||||||
* None.
|
|
||||||
*
|
|
||||||
* Returned Value:
|
|
||||||
* None.
|
|
||||||
*
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
void iob_notify_signal(void)
|
|
||||||
{
|
|
||||||
FAR struct iob_notify_s *notify;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
/* Get exclusive access to the notifier data structure */
|
|
||||||
|
|
||||||
ret = nxsem_wait(&g_iobnotify_sem);
|
|
||||||
while (ret < 0)
|
|
||||||
{
|
|
||||||
DEBUGASSERT(ret == -EINTR || ret == -ECANCELED);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Don't let any newly started threads block this thread until all of
|
|
||||||
* the notifications and been sent.
|
|
||||||
*/
|
|
||||||
|
|
||||||
sched_lock();
|
|
||||||
|
|
||||||
/* Process the notification at the head of the pending list until the
|
|
||||||
* pending list is empty */
|
|
||||||
|
|
||||||
while ((notify = g_iobnotify_pending) != NULL)
|
|
||||||
{
|
|
||||||
/* Remove the notification from the pending list */
|
|
||||||
|
|
||||||
g_iobnotify_pending = notify->flink;
|
|
||||||
|
|
||||||
/* Signal the waiter */
|
|
||||||
|
|
||||||
(void)nxsig_kill(notify->pid, notify->signo);
|
|
||||||
|
|
||||||
/* Free the notification by returning it to the free list */
|
|
||||||
|
|
||||||
iob_notify_free(notify);
|
|
||||||
}
|
|
||||||
|
|
||||||
sched_unlock();
|
|
||||||
(void)nxsem_post(&g_iobnotify_sem);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* CONFIG_IOB_NOTIFIER */
|
|
@ -1174,6 +1174,26 @@ endmenu # RTOS hooks
|
|||||||
|
|
||||||
menu "Signal Configuration"
|
menu "Signal Configuration"
|
||||||
|
|
||||||
|
config SIG_NOTIFIER
|
||||||
|
bool "Generic Signal notifier"
|
||||||
|
default n
|
||||||
|
---help---
|
||||||
|
Enable building of signal notifier logic that will send a signal to
|
||||||
|
a kernel thread when an event occurs. This is is a general
|
||||||
|
purpose notifier, but was developed specifically to support poll()
|
||||||
|
logic where the poll must wait for an resources to become available.
|
||||||
|
|
||||||
|
config SIG_NOTIFIER_NWAITERS
|
||||||
|
int "Number of signal waiters"
|
||||||
|
default 4
|
||||||
|
range 1 32766
|
||||||
|
depends on SIG_NOTIFIER
|
||||||
|
---help---
|
||||||
|
If CONFIG_SIG_NOTIFIER is selected, then a pre-allocated pool of
|
||||||
|
notification structures will be allocated to hold information about
|
||||||
|
pending notifications. This then determines an upper limit for the
|
||||||
|
number of waiters that can be supported.
|
||||||
|
|
||||||
config SIG_EVTHREAD
|
config SIG_EVTHREAD
|
||||||
bool "Support SIGEV_THHREAD"
|
bool "Support SIGEV_THHREAD"
|
||||||
default n
|
default n
|
||||||
|
@ -430,7 +430,7 @@ int nxmq_do_send(mqd_t mqdes, FAR struct mqueue_msg_s *mqmsg,
|
|||||||
|
|
||||||
else if (event.sigev_notify == SIGEV_THREAD)
|
else if (event.sigev_notify == SIGEV_THREAD)
|
||||||
{
|
{
|
||||||
DEBUGVERIFY(nxsig_notification(pid, &event));
|
DEBUGVERIFY(nxsig_evthread(pid, &event));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -49,7 +49,11 @@ CSRCS += sig_default.c
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(CONFIG_SIG_EVTHREAD),y)
|
ifeq ($(CONFIG_SIG_EVTHREAD),y)
|
||||||
CSRCS += sig_notification.c
|
CSRCS += sig_evthread.c
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ($(CONFIG_SIG_NOTIFIER),y)
|
||||||
|
CSRCS += sig_notifier.c
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# Include signal build support
|
# Include signal build support
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* sched/signal/sig_notification.c
|
* sched/signal/sig_evthread.c
|
||||||
*
|
*
|
||||||
* Copyright (C) 2015, 2017 Gregory Nutt. All rights reserved.
|
* Copyright (C) 2015, 2017-2018 Gregory Nutt. All rights reserved.
|
||||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@ -52,6 +52,7 @@
|
|||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Pre-processor Definitions
|
* Pre-processor Definitions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
/* Use the low-prioriry work queue is it is available */
|
/* Use the low-prioriry work queue is it is available */
|
||||||
|
|
||||||
#if defined(CONFIG_SCHED_LPWORK)
|
#if defined(CONFIG_SCHED_LPWORK)
|
||||||
@ -68,7 +69,7 @@
|
|||||||
|
|
||||||
/* This structure retains all that is necessary to perform the notification */
|
/* This structure retains all that is necessary to perform the notification */
|
||||||
|
|
||||||
struct sig_notify_s
|
struct sig_evthread_s
|
||||||
{
|
{
|
||||||
struct work_s nt_work; /* Work queue structure */
|
struct work_s nt_work; /* Work queue structure */
|
||||||
union sigval nt_value; /* Data passed with notification */
|
union sigval nt_value; /* Data passed with notification */
|
||||||
@ -80,7 +81,7 @@ struct sig_notify_s
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: nxsig_notify_worker
|
* Name: nxsig_evthread_worker
|
||||||
*
|
*
|
||||||
* Description:
|
* Description:
|
||||||
* Perform the callback from the context of the worker thread.
|
* Perform the callback from the context of the worker thread.
|
||||||
@ -93,9 +94,9 @@ struct sig_notify_s
|
|||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static void nxsig_notify_worker(FAR void *arg)
|
static void nxsig_evthread_worker(FAR void *arg)
|
||||||
{
|
{
|
||||||
FAR struct sig_notify_s *notify = (FAR struct sig_notify_s *)arg;
|
FAR struct sig_evthread_s *notify = (FAR struct sig_evthread_s *)arg;
|
||||||
|
|
||||||
DEBUGASSERT(notify != NULL);
|
DEBUGASSERT(notify != NULL);
|
||||||
|
|
||||||
@ -117,7 +118,7 @@ static void nxsig_notify_worker(FAR void *arg)
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: nxsig_notification
|
* Name: nxsig_evthread
|
||||||
*
|
*
|
||||||
* Description:
|
* Description:
|
||||||
* Notify a client a signal event via a function call. This function is
|
* Notify a client a signal event via a function call. This function is
|
||||||
@ -136,15 +137,15 @@ static void nxsig_notify_worker(FAR void *arg)
|
|||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
int nxsig_notification(pid_t pid, FAR struct sigevent *event)
|
int nxsig_evthread(pid_t pid, FAR struct sigevent *event)
|
||||||
{
|
{
|
||||||
FAR struct sig_notify_s *notify;
|
FAR struct sig_evthread_s *notify;
|
||||||
DEBUGASSERT(event != NULL && event->sigev_notify_function != NULL);
|
DEBUGASSERT(event != NULL && event->sigev_notify_function != NULL);
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
/* Allocate a structure to hold the notification information */
|
/* Allocate a structure to hold the notification information */
|
||||||
|
|
||||||
notify = kmm_zalloc(sizeof(struct sig_notify_s));
|
notify = kmm_zalloc(sizeof(struct sig_evthread_s));
|
||||||
if (notify == NULL)
|
if (notify == NULL)
|
||||||
{
|
{
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
@ -161,7 +162,7 @@ int nxsig_notification(pid_t pid, FAR struct sigevent *event)
|
|||||||
|
|
||||||
/* Then queue the work */
|
/* Then queue the work */
|
||||||
|
|
||||||
ret = work_queue(NTWORK, ¬ify->nt_work, nxsig_notify_worker,
|
ret = work_queue(NTWORK, ¬ify->nt_work, nxsig_evthread_worker,
|
||||||
notify, 0);
|
notify, 0);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
@ -1,7 +1,8 @@
|
|||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* sched/signal/sig_initialize.c
|
* sched/signal/sig_initialize.c
|
||||||
*
|
*
|
||||||
* Copyright (C) 2007, 2009, 2011, 2017 Gregory Nutt. All rights reserved.
|
* Copyright (C) 2007, 2009, 2011, 2017-2018 Gregory Nutt. All rights
|
||||||
|
* reserved.
|
||||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@ -233,6 +234,12 @@ void nxsig_initialize(void)
|
|||||||
nxsig_alloc_pendingsignalblock(&g_sigpendingirqsignal,
|
nxsig_alloc_pendingsignalblock(&g_sigpendingirqsignal,
|
||||||
NUM_INT_SIGNALS_PENDING,
|
NUM_INT_SIGNALS_PENDING,
|
||||||
SIG_ALLOC_IRQ);
|
SIG_ALLOC_IRQ);
|
||||||
|
|
||||||
|
#ifdef CONFIG_SIG_NOTIFIER
|
||||||
|
/* Initialize the generic notifier facility */
|
||||||
|
|
||||||
|
nxsig_notifier_initialize();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
|
492
sched/signal/sig_notifier.c
Normal file
492
sched/signal/sig_notifier.c
Normal file
@ -0,0 +1,492 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* sched/signal/sig_notifier.c
|
||||||
|
*
|
||||||
|
* Copyright (C) 2018 Gregory Nutt. All rights reserved.
|
||||||
|
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||||
|
*
|
||||||
|
* 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 <nuttx/config.h>
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sched.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#include <nuttx/irq.h>
|
||||||
|
#include <nuttx/signal.h>
|
||||||
|
#include <nuttx/semaphore.h>
|
||||||
|
|
||||||
|
#include "signal/signal.h"
|
||||||
|
|
||||||
|
#ifdef CONFIG_SIG_NOTIFIER
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Private Types
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/* This is the saved information for one notification */
|
||||||
|
|
||||||
|
struct nxsig_notifier_s
|
||||||
|
{
|
||||||
|
FAR struct nxsig_notifier_s *flink; /* Supports a singly linked list */
|
||||||
|
FAR void *qualifier; /* Event qualifier value */
|
||||||
|
uint8_t signo; /* The signal number for notification */
|
||||||
|
uint8_t evtype; /* See enum nxsig_evtype_e */
|
||||||
|
pid_t pid; /* The PID to be notified */
|
||||||
|
int16_t key; /* Unique ID for this notification */
|
||||||
|
};
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Private Data
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/* This is a statically allocated pool of notification structures */
|
||||||
|
|
||||||
|
static struct nxsig_notifier_s g_notifier_pool[CONFIG_SIG_NOTIFIER_NWAITERS];
|
||||||
|
|
||||||
|
/* This is a list of free notification structures */
|
||||||
|
|
||||||
|
static FAR struct nxsig_notifier_s *g_notifier_free;
|
||||||
|
|
||||||
|
/* This is a singly linked list of pending notifications. When an event
|
||||||
|
* occurs available, *all* of the waiters for that event in this list will
|
||||||
|
* be signaled and the entry will be freed. If there are multiple waiters
|
||||||
|
* for some resource, then only the highest priority thread will get the
|
||||||
|
* resource. Lower priority threads will need to call nxsig_notifier_setup()
|
||||||
|
* once again.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static FAR struct nxsig_notifier_s *g_notifier_pending;
|
||||||
|
|
||||||
|
/* This semaphore is used as mutex to enforce mutually exclusive access to
|
||||||
|
* the notification data structures.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static sem_t g_notifier_sem;
|
||||||
|
|
||||||
|
/* Used for lookup key generation */
|
||||||
|
|
||||||
|
static uint16_t g_notifier_key;
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Private Functions
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: nxsig_notifier_alloc
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Allocate a notification structure by removing it from the free list.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
static FAR struct nxsig_notifier_s *nxsig_notifier_alloc(void)
|
||||||
|
{
|
||||||
|
FAR struct nxsig_notifier_s *notifier;
|
||||||
|
|
||||||
|
notifier = g_notifier_free;
|
||||||
|
if (notifier != NULL)
|
||||||
|
{
|
||||||
|
g_notifier_free = notifier->flink;
|
||||||
|
notifier->flink = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return notifier;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: nxsig_notifier_free
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Free a notification structure by returning it to the head of the free
|
||||||
|
* list.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
static void nxsig_notifier_free(FAR struct nxsig_notifier_s *notifier)
|
||||||
|
{
|
||||||
|
notifier->flink = g_notifier_free;
|
||||||
|
g_notifier_free = notifier;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: nxsig_notifier_find
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Given a unique key for notification, find the corresponding notification
|
||||||
|
* structure in the pending notification list.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
static FAR struct nxsig_notifier_s *
|
||||||
|
nxsig_notifier_find(int16_t key, FAR struct nxsig_notifier_s **pprev)
|
||||||
|
{
|
||||||
|
FAR struct nxsig_notifier_s *notifier;
|
||||||
|
FAR struct nxsig_notifier_s *prev;
|
||||||
|
|
||||||
|
/* Find the entry matching this key in the g_notifier_pending list. */
|
||||||
|
|
||||||
|
for (prev = NULL, notifier = g_notifier_pending;
|
||||||
|
notifier != NULL;
|
||||||
|
prev = notifier, notifier = notifier->flink)
|
||||||
|
{
|
||||||
|
/* Is this the one we were looking for? */
|
||||||
|
|
||||||
|
if (notifier->key == key)
|
||||||
|
{
|
||||||
|
/* Return the previous entry if so requested */
|
||||||
|
|
||||||
|
if (pprev != NULL)
|
||||||
|
{
|
||||||
|
*pprev = prev;
|
||||||
|
}
|
||||||
|
|
||||||
|
return notifier;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: nxsig_notifier_key
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Generate a unique key for this notification.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
static int16_t nxsig_notifier_key(void)
|
||||||
|
{
|
||||||
|
int16_t key;
|
||||||
|
|
||||||
|
/* Loop until a unique key is generated */
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if (g_notifier_key >= INT16_MAX)
|
||||||
|
{
|
||||||
|
g_notifier_key = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
key = (int16_t)++g_notifier_key;
|
||||||
|
}
|
||||||
|
while (nxsig_notifier_find(key, NULL) != NULL);
|
||||||
|
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Public Functions
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: nxsig_notifier_initialize
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Set up the notification structure for normal operation.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
void nxsig_notifier_initialize(void)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* Add each notification structure to the free list */
|
||||||
|
|
||||||
|
for (i = 0; i < CONFIG_SIG_NOTIFIER_NWAITERS; i++)
|
||||||
|
{
|
||||||
|
FAR struct nxsig_notifier_s *notifier = &g_notifier_pool[i];
|
||||||
|
|
||||||
|
/* Add the pre-allocated notification to the head of the free list */
|
||||||
|
|
||||||
|
notifier->flink = g_notifier_free;
|
||||||
|
g_notifier_free = notifier;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Initialize the semaphore that enforces mutually exclusive access to the
|
||||||
|
* notification data structures.
|
||||||
|
*/
|
||||||
|
|
||||||
|
nxsem_init(&g_notifier_sem, 0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: nxsig_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.
|
||||||
|
* evtype - The event type.
|
||||||
|
* qualifier - Event qualifier to distinguish different cases of the
|
||||||
|
* generic event type.
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* > 0 - The key which may be used later in a call to
|
||||||
|
* nxsig_notifier_teardown().
|
||||||
|
* == 0 - Not used (reserved for wrapper functions).
|
||||||
|
* < 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 nxsig_notifier_setup(int pid, int signo, enum nxsig_evtype_e evtype,
|
||||||
|
FAR void *qualifier)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
/* If the 'pid' is zero, then use the PID of the calling thread */
|
||||||
|
|
||||||
|
if (pid <= 0)
|
||||||
|
{
|
||||||
|
pid = getpid();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get exclusive access to the notifier data structures */
|
||||||
|
|
||||||
|
ret = nxsem_wait(&g_notifier_sem);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Allocate a new notification */
|
||||||
|
|
||||||
|
FAR struct nxsig_notifier_s *notifier = nxsig_notifier_alloc();
|
||||||
|
if (notifier == NULL)
|
||||||
|
{
|
||||||
|
ret = -ENOSPC;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Generate a unique key for this notification */
|
||||||
|
|
||||||
|
int16_t key = nxsig_notifier_key();
|
||||||
|
|
||||||
|
/* Initialize the notification structure */
|
||||||
|
|
||||||
|
notifier->pid = pid;
|
||||||
|
notifier->signo = signo;
|
||||||
|
notifier->evtype = evtype;
|
||||||
|
notifier->key = key;
|
||||||
|
notifier->qualifier = qualifier;
|
||||||
|
|
||||||
|
/* And add it to the head of the pending list */
|
||||||
|
|
||||||
|
notifier->flink = g_notifier_pending;
|
||||||
|
g_notifier_pending = notifier;
|
||||||
|
ret = key;
|
||||||
|
}
|
||||||
|
|
||||||
|
(void)nxsem_post(&g_notifier_sem);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: nxsig_notifier_teardown
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Eliminate a notification previously setup by nxsig_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
|
||||||
|
* nxsig_notifier_setup().
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* Zero (OK) is returned on success; a negated errno value is returned on
|
||||||
|
* any failure.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
int nxsig_notifier_teardown(int key)
|
||||||
|
{
|
||||||
|
FAR struct nxsig_notifier_s *notifier;
|
||||||
|
FAR struct nxsig_notifier_s *prev;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
/* Get exclusive access to the notifier data structures */
|
||||||
|
|
||||||
|
ret = nxsem_wait(&g_notifier_sem);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Find the entry matching this PID in the g_notifier_pending list. We
|
||||||
|
* assume that there is only one.
|
||||||
|
*/
|
||||||
|
|
||||||
|
notifier = nxsig_notifier_find(key, &prev);
|
||||||
|
if (notifier == NULL)
|
||||||
|
{
|
||||||
|
/* There is no notification with this key in the pending list */
|
||||||
|
|
||||||
|
ret = -ENOENT;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Found it! Remove the notification from the pending list */
|
||||||
|
|
||||||
|
if (prev == NULL)
|
||||||
|
{
|
||||||
|
g_notifier_pending = notifier->flink;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
prev->flink = notifier->flink;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* And add it to the free list */
|
||||||
|
|
||||||
|
nxsig_notifier_free(notifier);
|
||||||
|
ret = OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
(void)nxsem_post(&g_notifier_sem);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: nxsig_notifier_signal
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* An event has just occurred. Signal all threads waiting for that event.
|
||||||
|
*
|
||||||
|
* When an IOB becomes available, *all* of the waiters in this thread will
|
||||||
|
* be signaled. If there are multiple waiters for a resource then only
|
||||||
|
* the highest priority thread will get the resource. Lower priority
|
||||||
|
* threads will need to call nxsig_notify once again.
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* evtype - The type of the event that just occurred.
|
||||||
|
* qualifier - Event qualifier to distinguish different cases of the
|
||||||
|
* generic event type.
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* None.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
void nxsig_notifier_signal(enum nxsig_evtype_e evtype,
|
||||||
|
FAR void *qualifier)
|
||||||
|
{
|
||||||
|
FAR struct nxsig_notifier_s *notifier;
|
||||||
|
FAR struct nxsig_notifier_s *prev;
|
||||||
|
FAR struct nxsig_notifier_s *next;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
/* Get exclusive access to the notifier data structure */
|
||||||
|
|
||||||
|
ret = nxsem_wait(&g_notifier_sem);
|
||||||
|
while (ret < 0)
|
||||||
|
{
|
||||||
|
DEBUGASSERT(ret == -EINTR || ret == -ECANCELED);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Don't let any newly started threads block this thread until all of
|
||||||
|
* the notifications and been sent.
|
||||||
|
*/
|
||||||
|
|
||||||
|
sched_lock();
|
||||||
|
|
||||||
|
/* Process the notification at the head of the pending list until the
|
||||||
|
* pending list is empty */
|
||||||
|
|
||||||
|
/* Find the entry matching this key in the g_notifier_pending list. */
|
||||||
|
|
||||||
|
for (prev = NULL, notifier = g_notifier_pending;
|
||||||
|
notifier != NULL;
|
||||||
|
notifier = next)
|
||||||
|
{
|
||||||
|
/* Set up for the next time through the loop (in case the entry is
|
||||||
|
* removed from the list).
|
||||||
|
*/
|
||||||
|
|
||||||
|
next = notifier->flink;
|
||||||
|
|
||||||
|
/* Check if this is the a notification request for the event that
|
||||||
|
* just occurred.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (notifier->evtype == evtype && notifier->qualifier == qualifier)
|
||||||
|
{
|
||||||
|
/* Yes.. Remove the notification from the pending list */
|
||||||
|
|
||||||
|
if (prev == NULL)
|
||||||
|
{
|
||||||
|
g_notifier_pending = next;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
prev->flink = next;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Signal the waiter */
|
||||||
|
|
||||||
|
(void)nxsig_kill(notifier->pid, notifier->signo);
|
||||||
|
|
||||||
|
/* Free the notification by returning it to the free list */
|
||||||
|
|
||||||
|
nxsig_notifier_free(notifier);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* The entry was not removed, the current entry will be the
|
||||||
|
* next previous entry.
|
||||||
|
*/
|
||||||
|
|
||||||
|
prev = notifier;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sched_unlock();
|
||||||
|
(void)nxsem_post(&g_notifier_sem);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* CONFIG_SIG_NOTIFIER */
|
@ -68,13 +68,14 @@
|
|||||||
* Public Type Definitions
|
* Public Type Definitions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
|
/* This enumeration identifies the type of signal data allocation */
|
||||||
|
|
||||||
enum sigalloc_e
|
enum sigalloc_e
|
||||||
{
|
{
|
||||||
SIG_ALLOC_FIXED = 0, /* pre-allocated; never freed */
|
SIG_ALLOC_FIXED = 0, /* pre-allocated; never freed */
|
||||||
SIG_ALLOC_DYN, /* dynamically allocated; free when unused */
|
SIG_ALLOC_DYN, /* dynamically allocated; free when unused */
|
||||||
SIG_ALLOC_IRQ /* Preallocated, reserved for interrupt handling */
|
SIG_ALLOC_IRQ /* Preallocated, reserved for interrupt handling */
|
||||||
};
|
};
|
||||||
typedef enum sigalloc_e sigalloc_t;
|
|
||||||
|
|
||||||
/* The following defines the sigaction queue entry */
|
/* The following defines the sigaction queue entry */
|
||||||
|
|
||||||
@ -166,6 +167,12 @@ struct task_group_s;
|
|||||||
void weak_function nxsig_initialize(void);
|
void weak_function nxsig_initialize(void);
|
||||||
void nxsig_alloc_actionblock(void);
|
void nxsig_alloc_actionblock(void);
|
||||||
|
|
||||||
|
/* sig_notifier.c */
|
||||||
|
|
||||||
|
#ifdef CONFIG_SIG_NOTIFIER
|
||||||
|
void nxsig_notifier_initialize(void);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* sig_action.c */
|
/* sig_action.c */
|
||||||
|
|
||||||
void nxsig_release_action(FAR sigactq_t *sigact);
|
void nxsig_release_action(FAR sigactq_t *sigact);
|
||||||
|
@ -118,7 +118,7 @@ static inline void timer_signotify(FAR struct posix_timer_s *timer)
|
|||||||
|
|
||||||
else if (timer->pt_event.sigev_notify == SIGEV_THREAD)
|
else if (timer->pt_event.sigev_notify == SIGEV_THREAD)
|
||||||
{
|
{
|
||||||
DEBUGVERIFY(nxsig_notification(timer->pt_owner, &timer->pt_event));
|
DEBUGVERIFY(nxsig_evthread(timer->pt_owner, &timer->pt_event));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user