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 <signal.h>
|
||||
|
||||
#if defined(CONFIG_SIG_EVTHREAD) && defined(__KERNEL__)
|
||||
#if defined(CONFIG_SIG_EVTHREAD) && defined(CONFIG_BUILD_FLAT)
|
||||
|
||||
/****************************************************************************
|
||||
* Public Function Prototypes
|
||||
|
@ -72,5 +72,5 @@
|
|||
|
||||
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 */
|
||||
|
|
|
@ -432,6 +432,10 @@ int pthread_sigmask(int how, FAR const sigset_t *set, FAR sigset_t *oset);
|
|||
}
|
||||
#endif
|
||||
|
||||
/********************************************************************************
|
||||
* Minimal Type Definitions
|
||||
********************************************************************************/
|
||||
|
||||
#else /* __INCLUDE_PTHREAD_H */
|
||||
|
||||
#include <sys/types.h>
|
||||
|
|
|
@ -210,6 +210,12 @@ union sigval
|
|||
* 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
|
||||
{
|
||||
uint8_t sigev_notify; /* Notification method: SIGEV_SIGNAL, SIGEV_NONE, or SIGEV_THREAD */
|
||||
|
@ -217,7 +223,7 @@ struct sigevent
|
|||
union sigval sigev_value; /* Data passed with notification */
|
||||
|
||||
#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) */
|
||||
#endif
|
||||
};
|
||||
|
@ -264,10 +270,6 @@ struct sigaction
|
|||
#define sa_handler sa_u._sa_handler
|
||||
#define sa_sigaction sa_u._sa_sigaction
|
||||
|
||||
/********************************************************************************
|
||||
* Public Data
|
||||
********************************************************************************/
|
||||
|
||||
/********************************************************************************
|
||||
* Public Function Prototypes
|
||||
********************************************************************************/
|
||||
|
@ -310,6 +312,10 @@ int sigqueue(int pid, int signo, FAR void *sival_ptr);
|
|||
}
|
||||
#endif
|
||||
|
||||
/********************************************************************************
|
||||
* Minimal Type Definitions
|
||||
********************************************************************************/
|
||||
|
||||
#else /* __INCLUDE_SIGNAL_H */
|
||||
|
||||
#include <stdint.h>
|
||||
|
|
|
@ -45,16 +45,13 @@
|
|||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <nuttx/signal.h>
|
||||
|
||||
#include "libc.h"
|
||||
#include "aio/aio.h"
|
||||
|
||||
#ifdef CONFIG_FS_AIO
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
/* Configuration ************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
|
@ -69,14 +66,6 @@ struct lio_sighand_s
|
|||
struct sigaction oact; /* Signal handler to restore */
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Private Variables
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Data
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
@ -205,11 +194,11 @@ static void lio_sighandler(int signo, siginfo_t *info, void *ucontext)
|
|||
if (sighand->sig->sigev_notify == SIGEV_SIGNAL)
|
||||
{
|
||||
#ifdef CONFIG_CAN_PASS_STRUCTS
|
||||
(void)sigqueue(sighand->pid, sighand->sig->sigev_signo,
|
||||
sighand->sig->sigev_value);
|
||||
DEBUGASSERT(sigqueue(sighand->pid, sighand->sig->sigev_signo,
|
||||
sighand->sig->sigev_value));
|
||||
#else
|
||||
(void)sigqueue(sighand->pid, sighand->sig->sigev_signo,
|
||||
sighand->sig->sigev_value.sival_ptr);
|
||||
DEBUGASSERT(sigqueue(sighand->pid, sighand->sig->sigev_signo,
|
||||
sighand->sig->sigev_value.sival_ptr));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -218,7 +207,7 @@ static void lio_sighandler(int signo, siginfo_t *info, void *ucontext)
|
|||
|
||||
else if (ighand->sig->sigev_notify == SIGEV_THREAD)
|
||||
{
|
||||
#warning Missing SIGEV_THREAD logic
|
||||
DEBUGASSERT(sig_notification(sighand->pid, &sighand->sig));
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -660,7 +649,7 @@ int lio_listio(int mode, FAR struct aiocb *const list[], int 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
|
||||
* 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. */
|
||||
|
||||
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
|
||||
* 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,
|
||||
sig->sigev_value.sival_ptr);
|
||||
#endif
|
||||
|
||||
if (status < 0 && ret != OK)
|
||||
if (status < 0 && ret == OK)
|
||||
{
|
||||
/* Something bad happened while signalling ourself and this is
|
||||
* 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)
|
||||
{
|
||||
#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
|
||||
|
||||
|
|
|
@ -778,11 +778,14 @@ endmenu # RTOS hooks
|
|||
config SIG_EVTHREAD
|
||||
bool "Support SIGEV_THHREAD"
|
||||
default n
|
||||
depends on EXPERIMENTAL
|
||||
depends on BUILD_FLAT && SCHED_WORKQUEUE
|
||||
---help---
|
||||
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"
|
||||
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_pause.c sig_nanosleep.c
|
||||
|
||||
ifeq ($(CONFIG_SIG_EVTHREAD),y)
|
||||
CSRCS += sig_notification.c
|
||||
endif
|
||||
|
||||
# Include signal build support
|
||||
|
||||
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