signals: Adds a very limited, minimal implementation for SIGEV_THREAD
This commit is contained in:
parent
9852932dcc
commit
c1fff4706c
7 changed files with 219 additions and 33 deletions
|
@ -45,7 +45,7 @@
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
|
||||||
#if defined(CONFIG_SIG_EVTHREAD) && defined(__KERNEL__)
|
#if defined(CONFIG_SIG_EVTHREAD) && defined(CONFIG_BUILD_FLAT)
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Public Function Prototypes
|
* Public Function Prototypes
|
||||||
|
@ -72,5 +72,5 @@
|
||||||
|
|
||||||
int sig_notification(pid_t pid, FAR struct sigevent *event);
|
int sig_notification(pid_t pid, FAR struct sigevent *event);
|
||||||
|
|
||||||
#endif /* CONFIG_SIG_EVTHREAD && __KERNEL__ */
|
#endif /* CONFIG_SIG_EVTHREAD && CONFIG_BUILD_FLAT */
|
||||||
#endif /* __INCLUDE_NUTTX_SIGNAL_H */
|
#endif /* __INCLUDE_NUTTX_SIGNAL_H */
|
||||||
|
|
|
@ -432,6 +432,10 @@ int pthread_sigmask(int how, FAR const sigset_t *set, FAR sigset_t *oset);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/********************************************************************************
|
||||||
|
* Minimal Type Definitions
|
||||||
|
********************************************************************************/
|
||||||
|
|
||||||
#else /* __INCLUDE_PTHREAD_H */
|
#else /* __INCLUDE_PTHREAD_H */
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
|
@ -210,6 +210,12 @@ union sigval
|
||||||
* available on a queue
|
* available on a queue
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifdef CONFIG_CAN_PASS_STRUCTS
|
||||||
|
typedef CODE void (*sigev_notify_function_t)(union sigval value);
|
||||||
|
#else
|
||||||
|
typedef CODE void (*sigev_notify_function_t)(FAR void *sival_ptr);
|
||||||
|
#endif
|
||||||
|
|
||||||
struct sigevent
|
struct sigevent
|
||||||
{
|
{
|
||||||
uint8_t sigev_notify; /* Notification method: SIGEV_SIGNAL, SIGEV_NONE, or SIGEV_THREAD */
|
uint8_t sigev_notify; /* Notification method: SIGEV_SIGNAL, SIGEV_NONE, or SIGEV_THREAD */
|
||||||
|
@ -217,8 +223,8 @@ struct sigevent
|
||||||
union sigval sigev_value; /* Data passed with notification */
|
union sigval sigev_value; /* Data passed with notification */
|
||||||
|
|
||||||
#ifdef CONFIG_SIG_EVTHREAD
|
#ifdef CONFIG_SIG_EVTHREAD
|
||||||
CODE void (*sigev_notify_function)(union sigval); /* Notification function */
|
sigev_notify_function_t sigev_notify_function; /* Notification function */
|
||||||
FAR pthread_attr_t *sigev_notify_attributes; /* Notification attributes (not used) */
|
FAR pthread_attr_t *sigev_notify_attributes; /* Notification attributes (not used) */
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -264,10 +270,6 @@ struct sigaction
|
||||||
#define sa_handler sa_u._sa_handler
|
#define sa_handler sa_u._sa_handler
|
||||||
#define sa_sigaction sa_u._sa_sigaction
|
#define sa_sigaction sa_u._sa_sigaction
|
||||||
|
|
||||||
/********************************************************************************
|
|
||||||
* Public Data
|
|
||||||
********************************************************************************/
|
|
||||||
|
|
||||||
/********************************************************************************
|
/********************************************************************************
|
||||||
* Public Function Prototypes
|
* Public Function Prototypes
|
||||||
********************************************************************************/
|
********************************************************************************/
|
||||||
|
@ -310,6 +312,10 @@ int sigqueue(int pid, int signo, FAR void *sival_ptr);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/********************************************************************************
|
||||||
|
* Minimal Type Definitions
|
||||||
|
********************************************************************************/
|
||||||
|
|
||||||
#else /* __INCLUDE_SIGNAL_H */
|
#else /* __INCLUDE_SIGNAL_H */
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
|
@ -45,16 +45,13 @@
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
|
#include <nuttx/signal.h>
|
||||||
|
|
||||||
#include "libc.h"
|
#include "libc.h"
|
||||||
#include "aio/aio.h"
|
#include "aio/aio.h"
|
||||||
|
|
||||||
#ifdef CONFIG_FS_AIO
|
#ifdef CONFIG_FS_AIO
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* Pre-processor Definitions
|
|
||||||
****************************************************************************/
|
|
||||||
/* Configuration ************************************************************/
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Private Types
|
* Private Types
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
@ -69,14 +66,6 @@ struct lio_sighand_s
|
||||||
struct sigaction oact; /* Signal handler to restore */
|
struct sigaction oact; /* Signal handler to restore */
|
||||||
};
|
};
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* Private Variables
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* Public Data
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Private Functions
|
* Private Functions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
@ -205,11 +194,11 @@ static void lio_sighandler(int signo, siginfo_t *info, void *ucontext)
|
||||||
if (sighand->sig->sigev_notify == SIGEV_SIGNAL)
|
if (sighand->sig->sigev_notify == SIGEV_SIGNAL)
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_CAN_PASS_STRUCTS
|
#ifdef CONFIG_CAN_PASS_STRUCTS
|
||||||
(void)sigqueue(sighand->pid, sighand->sig->sigev_signo,
|
DEBUGASSERT(sigqueue(sighand->pid, sighand->sig->sigev_signo,
|
||||||
sighand->sig->sigev_value);
|
sighand->sig->sigev_value));
|
||||||
#else
|
#else
|
||||||
(void)sigqueue(sighand->pid, sighand->sig->sigev_signo,
|
DEBUGASSERT(sigqueue(sighand->pid, sighand->sig->sigev_signo,
|
||||||
sighand->sig->sigev_value.sival_ptr);
|
sighand->sig->sigev_value.sival_ptr));
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -218,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)
|
||||||
{
|
{
|
||||||
#warning Missing SIGEV_THREAD logic
|
DEBUGASSERT(sig_notification(sighand->pid, &sighand->sig));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -660,7 +649,7 @@ int lio_listio(int mode, FAR struct aiocb *const list[], int nent,
|
||||||
*/
|
*/
|
||||||
|
|
||||||
status = lio_waitall(list, nent);
|
status = lio_waitall(list, nent);
|
||||||
if (status < 0 && ret != OK)
|
if (status < 0 && ret == OK)
|
||||||
{
|
{
|
||||||
/* Something bad happened while waiting and this is the first
|
/* Something bad happened while waiting and this is the first
|
||||||
* error to be reported.
|
* error to be reported.
|
||||||
|
@ -688,7 +677,7 @@ int lio_listio(int mode, FAR struct aiocb *const list[], int nent,
|
||||||
/* Setup a signal handler to detect when until all I/O completes. */
|
/* Setup a signal handler to detect when until all I/O completes. */
|
||||||
|
|
||||||
status = lio_sigsetup(list, nent, sig);
|
status = lio_sigsetup(list, nent, sig);
|
||||||
if (status < 0 && ret != OK)
|
if (status < 0 && ret == OK)
|
||||||
{
|
{
|
||||||
/* Something bad happened while setting up the signal and this
|
/* Something bad happened while setting up the signal and this
|
||||||
* is the first error to be reported.
|
* is the first error to be reported.
|
||||||
|
@ -707,8 +696,7 @@ int lio_listio(int mode, FAR struct aiocb *const list[], int nent,
|
||||||
status = sigqueue(getpid(), sig->sigev_signo,
|
status = sigqueue(getpid(), sig->sigev_signo,
|
||||||
sig->sigev_value.sival_ptr);
|
sig->sigev_value.sival_ptr);
|
||||||
#endif
|
#endif
|
||||||
|
if (status < 0 && ret == OK)
|
||||||
if (status < 0 && ret != OK)
|
|
||||||
{
|
{
|
||||||
/* Something bad happened while signalling ourself and this is
|
/* Something bad happened while signalling ourself and this is
|
||||||
* the first error to be reported.
|
* the first error to be reported.
|
||||||
|
@ -725,7 +713,16 @@ 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)
|
||||||
{
|
{
|
||||||
#warning Missing SIGEV_THREAD logic
|
status = sig_notification(sighand->pid, &sighand->sig);
|
||||||
|
if (status < 0 && ret == OK)
|
||||||
|
{
|
||||||
|
/* Something bad happened while performing the notification
|
||||||
|
* and this is the first error to be reported.
|
||||||
|
*/
|
||||||
|
|
||||||
|
retcode = -status;
|
||||||
|
ret = ERROR;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -778,11 +778,14 @@ endmenu # RTOS hooks
|
||||||
config SIG_EVTHREAD
|
config SIG_EVTHREAD
|
||||||
bool "Support SIGEV_THHREAD"
|
bool "Support SIGEV_THHREAD"
|
||||||
default n
|
default n
|
||||||
depends on EXPERIMENTAL
|
depends on BUILD_FLAT && SCHED_WORKQUEUE
|
||||||
---help---
|
---help---
|
||||||
Built in support for the SIGEV_THREAD signal deliver method.
|
Built in support for the SIGEV_THREAD signal deliver method.
|
||||||
|
|
||||||
NOTE: Only partially implemented as of this writing.
|
NOTE: The current implementation uses a work queue to notify the
|
||||||
|
client. This, however, would only work in the FLAT build. A
|
||||||
|
different mechanism would need to be development to support this
|
||||||
|
feature on the PROTECTED or KERNEL build.
|
||||||
|
|
||||||
menu "Signal Numbers"
|
menu "Signal Numbers"
|
||||||
depends on !DISABLE_SIGNALS
|
depends on !DISABLE_SIGNALS
|
||||||
|
|
|
@ -44,6 +44,10 @@ CSRCS += sig_removependingsignal.c sig_releasependingsignal.c sig_lowest.c
|
||||||
CSRCS += sig_mqnotempty.c sig_cleanup.c sig_dispatch.c sig_deliver.c
|
CSRCS += sig_mqnotempty.c sig_cleanup.c sig_dispatch.c sig_deliver.c
|
||||||
CSRCS += sig_pause.c sig_nanosleep.c
|
CSRCS += sig_pause.c sig_nanosleep.c
|
||||||
|
|
||||||
|
ifeq ($(CONFIG_SIG_EVTHREAD),y)
|
||||||
|
CSRCS += sig_notification.c
|
||||||
|
endif
|
||||||
|
|
||||||
# Include signal build support
|
# Include signal build support
|
||||||
|
|
||||||
DEPPATH += --dep-path signal
|
DEPPATH += --dep-path signal
|
||||||
|
|
172
sched/signal/sig_notification.c
Normal file
172
sched/signal/sig_notification.c
Normal file
|
@ -0,0 +1,172 @@
|
||||||
|
/****************************************************************************
|
||||||
|
* sched/signal/sig_notification.c
|
||||||
|
*
|
||||||
|
* Copyright (C) 2015 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 <signal.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#include <nuttx/kmalloc.h>
|
||||||
|
#include <nuttx/wqueue.h>
|
||||||
|
|
||||||
|
#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_notify_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: sig_ntworker
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Perform the callback from the context of the worker thread.
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* arg - Work argument.
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* None.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
static void sig_ntworker(FAR void *arg)
|
||||||
|
{
|
||||||
|
FAR struct sig_notify_s *notify = (FAR struct sig_notify_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: sig_notification
|
||||||
|
*
|
||||||
|
* 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:
|
||||||
|
* Zero (OK) is returned on success; A negated errno value is returned
|
||||||
|
* on failure.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
int sig_notification(pid_t pid, FAR struct sigevent *event)
|
||||||
|
{
|
||||||
|
FAR struct sig_notify_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_notify_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, sig_ntworker, notify, 0);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
kmm_free(notify);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* CONFIG_SIG_EVTHREAD */
|
Loading…
Reference in a new issue