signals: Basic framework to support SIGEV_THREAD

This commit is contained in:
Gregory Nutt 2015-12-30 13:20:31 -06:00
parent e76e8f41c6
commit 9835eeb181
15 changed files with 252 additions and 84 deletions

7
TODO
View File

@ -340,9 +340,10 @@ o Signals (sched/signal, arch/)
embedded system.
Title: SIGEV_THREAD
Description: sig_notify() logic does not support SIGEV_THREAD; structure
struct sigevent does not provide required members sigev_notify_function
or sigev_notify_attributes.
Description: Implementation of support for support for SIGEV_THREAD is incomplete;
The internal OS functin sig_notification has not been implemented (and
will be tricky!). There are also some unimplemented function call logic
in libc/aio
Status: Low, there are alternative designs. However, these features
are required by the POSIX standard.
Priority: Low for now

2
arch

@ -1 +1 @@
Subproject commit 4e962ff8a0a2f15247232d7e9aef89032c9b2898
Subproject commit 08f9810f5922c627fd378ea3727faa0ba4eb0d74

@ -1 +1 @@
Subproject commit bf83eb388aea59fb76651ba22c86f22a0da5d6dc
Subproject commit d4540c0f83378a6680ffd792ff1e4a8ca0ddd8b8

View File

@ -51,29 +51,10 @@
#ifdef CONFIG_FS_AIO
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/****************************************************************************
* Private Types
****************************************************************************/
/****************************************************************************
* Private Data
****************************************************************************/
/****************************************************************************
* Public Data
****************************************************************************/
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: aio_signal
*
@ -126,6 +107,19 @@ int aio_signal(pid_t pid, FAR struct aiocb *aiocbp)
}
}
#ifdef CONFIG_SIG_EVTHREAD
/* Notify the client via a function call */
else if (aiocbp->aio_sigevent.sigev_notify == SIGEV_THREAD)
{
ret = sig_notification(pid, &aiocbp->aio_sigevent);
if (ret < 0)
{
fdbg("ERROR: sig_notification failed: %d\n", ret);
}
}
#endif
/* Send the poll signal in any event in case the caller is waiting
* on sig_suspend();
*/

View File

@ -1,7 +1,7 @@
/****************************************************************************
* include/nuttx/mqueue.h
*
* Copyright (C) 2007, 2009, 2011, 2014 Gregory Nutt. All rights reserved.
* Copyright (C) 2007, 2009, 2011, 2014-2015 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@ -80,8 +80,7 @@ struct mqueue_inode_s
#ifndef CONFIG_DISABLE_SIGNALS
FAR struct mq_des *ntmqdes; /* Notification: Owning mqdes (NULL if none) */
pid_t ntpid; /* Notification: Receiving Task's PID */
int ntsigno; /* Notification: Signal number */
union sigval ntvalue; /* Notification: Signal value */
struct sigevent ntevent; /* Notification description */
#endif
};

View File

@ -158,8 +158,11 @@ extern "C"
/* pthread-specific types */
typedef int pthread_key_t;
typedef FAR void *pthread_addr_t;
typedef int pthread_key_t;
#define __PTHREAD_KEY_T_DEFINED 1
typedef FAR void *pthread_addr_t;
#define __PTHREAD_ADDR_T_DEFINED 1
typedef pthread_addr_t (*pthread_startroutine_t)(pthread_addr_t);
typedef pthread_startroutine_t pthread_func_t;
@ -182,17 +185,24 @@ struct pthread_attr_s
struct timespec budget; /* Initial budget */
#endif
};
typedef struct pthread_attr_s pthread_attr_t;
#define __PTHREAD_ATTR_T_DEFINED 1
typedef pid_t pthread_t;
#define __PTHREAD_T_DEFINED 1
typedef int pthread_condattr_t;
#define __PTHREAD_CONDATTR_T_DEFINED 1
struct pthread_cond_s
{
sem_t sem;
};
typedef struct pthread_cond_s pthread_cond_t;
#define __PTHREAD_COND_T_DEFINED 1
#define PTHREAD_COND_INITIALIZER {SEM_INITIALIZER(0)}
struct pthread_mutexattr_s
@ -202,7 +212,9 @@ struct pthread_mutexattr_s
uint8_t type; /* Type of the mutex. See PTHREAD_MUTEX_* definitions */
#endif
};
typedef struct pthread_mutexattr_s pthread_mutexattr_t;
#define __PTHREAD_MUTEXATTR_T_DEFINED 1
struct pthread_mutex_s
{
@ -213,7 +225,9 @@ struct pthread_mutex_s
int nlocks; /* The number of recursive locks held */
#endif
};
typedef struct pthread_mutex_s pthread_mutex_t;
#define __PTHREAD_MUTEX_T_DEFINED 1
#ifdef CONFIG_MUTEX_TYPES
# define PTHREAD_MUTEX_INITIALIZER {-1, SEM_INITIALIZER(1), PTHREAD_MUTEX_DEFAULT, 0}
@ -225,16 +239,21 @@ struct pthread_barrierattr_s
{
int pshared;
};
typedef struct pthread_barrierattr_s pthread_barrierattr_t;
#define __PTHREAD_BARRIERATTR_T_DEFINED 1
struct pthread_barrier_s
{
sem_t sem;
unsigned int count;
};
typedef struct pthread_barrier_s pthread_barrier_t;
#define __PTHREAD_BARRIER_T_DEFINED 1
typedef bool pthread_once_t;
#define __PTHREAD_ONCE_T_DEFINED 1
/* Forware references */
@ -413,4 +432,74 @@ int pthread_sigmask(int how, FAR const sigset_t *set, FAR sigset_t *oset);
}
#endif
#else /* __INCLUDE_PTHREAD_H */
#include <sys/types.h>
#include <stdbool.h>
/* Avoid a circular dependencies by assuring that simple type definitions
* are avaiable in any inclusion ordering.
*/
#ifndef __PTHREAD_KEY_T_DEFINED
typedef int pthread_key_t;
# define __PTHREAD_KEY_T_DEFINED 1
#endif
#ifndef __PTHREAD_ADDR_T_DEFINED
typedef FAR void *pthread_addr_t;
# define __PTHREAD_ADDR_T_DEFINED 1
#endif
#ifndef __PTHREAD_ATTR_T_DEFINED
struct pthread_attr_s;
typedef struct pthread_attr_s pthread_attr_t;
# define __PTHREAD_ATTR_T_DEFINED 1
#endif
#ifndef __PTHREAD_T_DEFINED
typedef pid_t pthread_t;
# define __PTHREAD_T_DEFINED 1
#endif
#ifndef __PTHREAD_CONDATTR_T_DEFINED
typedef int pthread_condattr_t;
# define __PTHREAD_CONDATTR_T_DEFINED 1
#endif
#ifndef __PTHREAD_COND_T_DEFINED
struct pthread_cond_s;
typedef struct pthread_cond_s pthread_cond_t;
# define __PTHREAD_COND_T_DEFINED 1
#endif
#ifndef __PTHREAD_MUTEXATTR_T_DEFINED
struct pthread_mutexattr_s;
typedef struct pthread_mutexattr_s pthread_mutexattr_t;
# define __PTHREAD_MUTEXATTR_T_DEFINED 1
#endif
#ifndef __PTHREAD_MUTEX_T_DEFINED
struct pthread_mutex_s;
typedef struct pthread_mutex_s pthread_mutex_t;
# define __PTHREAD_MUTEX_T_DEFINED 1
#endif
#ifndef __PTHREAD_BARRIERATTR_T_DEFINED
struct pthread_barrierattr_s;
typedef struct pthread_barrierattr_s pthread_barrierattr_t;
# define __PTHREAD_BARRIERATTR_T_DEFINED 1
#endif
#ifndef __PTHREAD_BARRIER_T_DEFINED
struct pthread_barrier_s;
typedef struct pthread_barrier_s pthread_barrier_t;
# define __PTHREAD_BARRIER_T_DEFINED 1
#endif
#ifndef __PTHREAD_ONCE_T_DEFINED
typedef bool pthread_once_t;
# define __PTHREAD_ONCE_T_DEFINED 1
#endif
#endif /* __INCLUDE_PTHREAD_H */

View File

@ -45,6 +45,9 @@
#include <stdint.h>
#include <time.h>
#ifdef CONFIG_SIG_EVTHREAD
# include <pthread.h> /* Needed for pthread_attr_t */
#endif
/********************************************************************************
* Pre-processor Definitions
@ -162,8 +165,11 @@
/* Values for the sigev_notify field of struct sigevent */
#define SIGEV_NONE 0 /* No notification desired */
#define SIGEV_SIGNAL 1 /* Notify via signal */
#define SIGEV_NONE 0 /* No asynchronous notification is delivered */
#define SIGEV_SIGNAL 1 /* Notify via signal,with an application-defined value */
#ifdef CONFIG_SIG_EVTHREAD
# define SIGEV_THREAD 3 /* A notification function is called */
#endif
/* Special values of of sa_handler used by sigaction and sigset. They are all
* treated like NULL for now. This is okay for SIG_DFL and SIG_IGN because
@ -189,6 +195,7 @@
/* This defines a set of 32 signals (numbered 0 through 31). */
typedef uint32_t sigset_t; /* Bit set of 32 signals */
#define __SIGSET_T_DEFINED 1
/* This defines the type of the siginfo si_value field */
@ -205,9 +212,14 @@ union sigval
struct sigevent
{
uint8_t sigev_notify; /* Notification method: SIGEV_SIGNAL or SIGEV_NONE */
uint8_t sigev_notify; /* Notification method: SIGEV_SIGNAL, SIGEV_NONE, or SIGEV_THREAD */
uint8_t sigev_signo; /* Notification signal */
union sigval sigev_value; /* Data passed with notification */
#ifdef CONFIG_SIG_EVTHREAD
CODE void (*sigev_notify_function)(union sigval); /* Notification function */
FAR pthread_attr_t *sigev_notify_attributes; /* Notification attributes (not used) */
#endif
};
/* The following types is used to pass parameters to/from signal handlers */
@ -225,6 +237,7 @@ struct siginfo
};
typedef struct siginfo siginfo_t;
#define __SIGINFO_T_DEFINED 1
/* Non-standard convenience definition of signal handling function types.
* These should be used only internally within the NuttX signal logic.
@ -297,4 +310,23 @@ int sigqueue(int pid, int signo, FAR void *sival_ptr);
}
#endif
#else /* __INCLUDE_SIGNAL_H */
#include <stdint.h>
/* Avoid a circular dependencies by assuring that simple type definitions
* are avaiable in any inclusion ordering.
*/
#ifndef __SIGSET_T_DEFINED
typedef uint32_t sigset_t;
# define __SIGSET_T_DEFINED 1
#endif
#ifndef __SIGINFO_T_DEFINED
struct siginfo;
typedef struct siginfo siginfo_t;
# define __SIGINFO_T_DEFINED 1
#endif
#endif /* __INCLUDE_SIGNAL_H */

View File

@ -213,6 +213,15 @@ static void lio_sighandler(int signo, siginfo_t *info, void *ucontext)
#endif
}
#ifdef CONFIG_SIG_EVTHREAD
/* Notify the client via a function call */
else if (ighand->sig->sigev_notify == SIGEV_THREAD)
{
#warning Missing SIGEV_THREAD logic
}
#endif
/* And free the container */
lib_free(sighand);
@ -711,6 +720,15 @@ int lio_listio(int mode, FAR struct aiocb *const list[], int nent,
}
}
#ifdef CONFIG_SIG_EVTHREAD
/* Notify the client via a function call */
else if (sig && sig->sigev_notify == SIGEV_THREAD)
{
#warning Missing SIGEV_THREAD logic
}
#endif
/* Case 3: mode == LIO_NOWAIT and sig == NULL
*
* Just return now.

View File

@ -775,6 +775,15 @@ config SCHED_ONEXIT_MAX
endmenu # RTOS hooks
config SIG_EVTHREAD
bool "Support SIGEV_THHREAD"
default n
depends on EXPERIMENTAL
---help---
Built in support for the SIGEV_THREAD signal deliver method.
NOTE: Only partially implemented as of this writing.
menu "Signal Numbers"
depends on !DISABLE_SIGNALS

View File

@ -41,6 +41,7 @@
#include <mqueue.h>
#include <sched.h>
#include <string.h>
#include <assert.h>
#include <queue.h>
@ -128,9 +129,8 @@ void mq_desclose(mqd_t mqdes)
#ifndef CONFIG_DISABLE_SIGNALS
if (msgq->ntmqdes == mqdes)
{
memset(&msgq->ntevent, 0, sizeof(struct sigevent));
msgq->ntpid = INVALID_PROCESS_ID;
msgq->ntsigno = 0;
msgq->ntvalue.sival_int = 0;
msgq->ntmqdes = NULL;
}
#endif

View File

@ -42,6 +42,7 @@
#include <signal.h>
#include <mqueue.h>
#include <sched.h>
#include <string.h>
#include <errno.h>
#include <nuttx/sched.h>
@ -93,7 +94,7 @@
* Parameters:
* mqdes - Message queue descriptor
* notification - Real-time signal structure containing:
* sigev_notify - Should be SIGEV_SIGNAL (but actually ignored)
* sigev_notify - Should be SIGEV_SIGNAL or SIGEV_THREAD
* sigev_signo - The signo to use for the notification
* sigev_value - Value associated with the signal
*
@ -171,10 +172,11 @@ int mq_notify(mqd_t mqdes, const struct sigevent *notification)
/* Yes... Assign it to the current task. */
msgq->ntvalue.sival_ptr = notification->sigev_value.sival_ptr;
msgq->ntsigno = notification->sigev_signo;
msgq->ntpid = rtcb->pid;
msgq->ntmqdes = mqdes;
memcpy(&msgq->ntevent, &notification->sigev_value,
sizeof(struct sigevent));
msgq->ntpid = rtcb->pid;
msgq->ntmqdes = mqdes;
}
}
@ -197,10 +199,9 @@ int mq_notify(mqd_t mqdes, const struct sigevent *notification)
* thread to detach the notification.
*/
msgq->ntpid = INVALID_PROCESS_ID;
msgq->ntsigno = 0;
msgq->ntvalue.sival_ptr = NULL;
msgq->ntmqdes = NULL;
memset(&msgq->ntevent, 0, sizeof(struct sigevent));
msgq->ntpid = INVALID_PROCESS_ID;
msgq->ntmqdes = NULL;
}
sched_unlock();

View File

@ -51,6 +51,8 @@
#include <nuttx/kmalloc.h>
#include <nuttx/arch.h>
#include <nuttx/sched.h>
#include <nuttx/signal.h>
#include "sched/sched.h"
#ifndef CONFIG_DISABLE_SIGNALS
# include "signal/signal.h"
@ -384,30 +386,44 @@ int mq_dosend(mqd_t mqdes, FAR struct mqueue_msg_s *mqmsg, FAR const char *msg,
#ifndef CONFIG_DISABLE_SIGNALS
if (msgq->ntmqdes)
{
struct sigevent event;
pid_t pid;
/* Remove the message notification data from the message queue. */
#ifdef CONFIG_CAN_PASS_STRUCTS
union sigval value = msgq->ntvalue;
#else
void *sival_ptr = msgq->ntvalue.sival_ptr;
#endif
int signo = msgq->ntsigno;
int pid = msgq->ntpid;
memcpy(&event, &msgq->ntevent, sizeof(struct sigevent));
pid = msgq->ntpid;
/* Detach the notification */
msgq->ntpid = INVALID_PROCESS_ID;
msgq->ntsigno = 0;
msgq->ntvalue.sival_int = 0;
msgq->ntmqdes = NULL;
memset(&msgq->ntevent, 0, sizeof(struct sigevent));
msgq->ntpid = INVALID_PROCESS_ID;
msgq->ntmqdes = NULL;
/* Queue the signal -- What if this returns an error? */
/* Notification the client via signal? */
if (event.sigev_notify == SIGEV_SIGNAL)
{
/* Yes... Queue the signal -- What if this returns an error? */
#ifdef CONFIG_CAN_PASS_STRUCTS
sig_mqnotempty(pid, signo, value);
DEBUGVERIFY(sig_mqnotempty(pid, event.sigev_signo,
event.sigev_value));
#else
sig_mqnotempty(pid, signo, sival_ptr);
DEBUGVERIFY(sig_mqnotempty(pid, event.sigev_signo,
event.sigev_value.sival_ptr));
#endif
}
#ifdef CONFIG_SIG_EVTHREAD
/* Notify the client via a function call */
else if (event.sigev_notify == SIGEV_THREAD)
{
DEBUGVERIFY(sig_notification(pid, &event));
}
#endif
}
#endif

View File

@ -1,7 +1,7 @@
/********************************************************************************
* sched/timer/timer.h
*
* Copyright (C) 2007-2009, 2014 Gregory Nutt. All rights reserved.
* Copyright (C) 2007-2009, 2014-2015 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@ -67,12 +67,11 @@ struct posix_timer_s
uint8_t pt_flags; /* See PT_FLAGS_* definitions */
uint8_t pt_crefs; /* Reference count */
uint8_t pt_signo; /* Notification signal */
pid_t pt_owner; /* Creator of timer */
int pt_delay; /* If non-zero, used to reset repetitive timers */
int pt_last; /* Last value used to set watchdog */
WDOG_ID pt_wdog; /* The watchdog that provides the timing */
union sigval pt_value; /* Data passed with notification */
struct sigevent pt_event; /* Notification information */
};
/********************************************************************************

View File

@ -215,17 +215,11 @@ int timer_create(clockid_t clockid, FAR struct sigevent *evp, FAR timer_t *timer
if (evp)
{
ret->pt_signo = evp->sigev_signo;
#ifdef CONFIG_CAN_PASS_STRUCTS
ret->pt_value = evp->sigev_value;
#else
ret->pt_value.sival_ptr = evp->sigev_value.sival_ptr;
#endif
memcpy(&ret->pt_event, evp, sizeof(struct sigevent));
}
else
{
ret->pt_signo = SIGALRM;
ret->pt_value.sival_ptr = ret;
memset(&ret->pt_event, 0, sizeof(struct sigevent));
}
/* Return the timer */

View File

@ -44,6 +44,8 @@
#include <string.h>
#include <errno.h>
#include <nuttx/signal.h>
#include "clock/clock.h"
#include "signal/signal.h"
#include "timer/timer.h"
@ -66,7 +68,7 @@
* Private Function Prototypes
********************************************************************************/
static inline void timer_sigqueue(FAR struct posix_timer_s *timer);
static inline void timer_signotify(FAR struct posix_timer_s *timer);
static inline void timer_restart(FAR struct posix_timer_s *timer, wdparm_t itimer);
static void timer_timeout(int argc, wdparm_t itimer);
@ -75,7 +77,7 @@ static void timer_timeout(int argc, wdparm_t itimer);
********************************************************************************/
/********************************************************************************
* Name: timer_sigqueue
* Name: timer_signotify
*
* Description:
* This function basically reimplements sigqueue() so that the si_code can
@ -92,28 +94,42 @@ static void timer_timeout(int argc, wdparm_t itimer);
*
********************************************************************************/
static inline void timer_sigqueue(FAR struct posix_timer_s *timer)
static inline void timer_signotify(FAR struct posix_timer_s *timer)
{
siginfo_t info;
/* Create the siginfo structure */
/* Notify client via a signal? */
info.si_signo = timer->pt_signo;
info.si_code = SI_TIMER;
info.si_errno = OK;
if (timer->pt_event.sigev_notify == SIGEV_SIGNAL)
{
/* Yes.. Create the siginfo structure */
info.si_signo = timer->pt_event.sigev_signo;
info.si_code = SI_TIMER;
info.si_errno = OK;
#ifdef CONFIG_CAN_PASS_STRUCTS
info.si_value = timer->pt_value;
info.si_value = timer->pt_event.sigev_value;
#else
info.si_value.sival_ptr = timer->pt_value.sival_ptr;
info.si_value.sival_ptr = timer->pt_event.sigev_value.sival_ptr;
#endif
#ifdef CONFIG_SCHED_HAVE_PARENT
info.si_pid = 0; /* Not applicable */
info.si_status = OK;
info.si_pid = 0; /* Not applicable */
info.si_status = OK;
#endif
/* Send the signal */
/* Send the signal */
(void)sig_dispatch(timer->pt_owner, &info);
DEBUGVERIFY(sig_dispatch(timer->pt_owner, &info));
}
#ifdef CONFIG_SIG_EVTHREAD
/* Notify the client via a function call */
else if (timer->pt_event.sigev_notify == SIGEV_THREAD)
{
DEBUGVERIFY(sig_notification(timer->pt_owner, &timer->pt_event));
}
#endif
}
/********************************************************************************
@ -187,7 +203,7 @@ static void timer_timeout(int argc, wdparm_t itimer)
*/
u.timer->pt_crefs++;
timer_sigqueue(u.timer);
timer_signotify(u.timer);
/* Release the reference. timer_release will return nonzero if the timer
* was not deleted.
@ -208,7 +224,7 @@ static void timer_timeout(int argc, wdparm_t itimer)
*/
timer->pt_crefs++;
timer_sigqueue(timer);
timer_signotify(timer);
/* Release the reference. timer_release will return nonzero if the timer
* was not deleted.