diff --git a/include/signal.h b/include/signal.h index 3215f04b1e..39718d7963 100644 --- a/include/signal.h +++ b/include/signal.h @@ -264,9 +264,11 @@ #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 */ +# define SIGEV_THREAD 2 /* A notification function is called */ #endif +#define SIGEV_THREAD_ID 4 /* Notify a specific thread via signal. */ + /* sigaltstack stack size */ #define MINSIGSTKSZ CONFIG_PTHREAD_STACK_MIN /* Smallest signal stack size */ @@ -345,6 +347,8 @@ struct sigevent sigev_notify_function_t sigev_notify_function; /* Notification function */ FAR struct pthread_attr_s *sigev_notify_attributes; /* Notification attributes (not used) */ #endif + + pid_t sigev_notify_thread_id; /* ID of thread to signal */ }; /* The following types is used to pass parameters to/from signal handlers */ diff --git a/sched/signal/sig_notification.c b/sched/signal/sig_notification.c index c79ae53f6e..a213c48563 100644 --- a/sched/signal/sig_notification.c +++ b/sched/signal/sig_notification.c @@ -110,11 +110,9 @@ int nxsig_notification(pid_t pid, FAR struct sigevent *event, /* Notify client via a signal? */ - if (event->sigev_notify == SIGEV_SIGNAL) + if (event->sigev_notify & SIGEV_SIGNAL) { -#ifdef CONFIG_SCHED_HAVE_PARENT FAR struct tcb_s *rtcb = this_task(); -#endif siginfo_t info; /* Yes.. Create the siginfo structure */ @@ -135,6 +133,23 @@ int nxsig_notification(pid_t pid, FAR struct sigevent *event, memcpy(&info.si_value, &event->sigev_value, sizeof(union sigval)); + /* Used only by POSIX timer. Notice that it is UNSAFE, unless + * we GUARANTEE that event->sigev_notify_thread_id is valid. + */ + + if (event->sigev_notify & SIGEV_THREAD_ID) + { + rtcb = nxsched_get_tcb(event->sigev_notify_thread_id); + if (rtcb != NULL) + { + return nxsig_tcbdispatch(rtcb, &info); + } + else + { + return -ENOENT; + } + } + /* Send the signal */ return nxsig_dispatch(pid, &info); @@ -143,7 +158,7 @@ int nxsig_notification(pid_t pid, FAR struct sigevent *event, #ifdef CONFIG_SIG_EVTHREAD /* Notify the client via a function call */ - else if (event->sigev_notify == SIGEV_THREAD) + else if (event->sigev_notify & SIGEV_THREAD) { /* Initialize the work information */ diff --git a/sched/timer/timer_create.c b/sched/timer/timer_create.c index 1aa1fbe95b..646d19ac8b 100644 --- a/sched/timer/timer_create.c +++ b/sched/timer/timer_create.c @@ -37,6 +37,7 @@ #include #include +#include "sched/sched.h" #include "timer/timer.h" #ifndef CONFIG_DISABLE_POSIX_TIMERS @@ -158,6 +159,7 @@ int timer_create(clockid_t clockid, FAR struct sigevent *evp, FAR timer_t *timerid) { FAR struct posix_timer_s *ret; + FAR struct tcb_s *tcb = this_task(); /* Sanity checks. */ @@ -181,7 +183,7 @@ int timer_create(clockid_t clockid, FAR struct sigevent *evp, ret->pt_clock = clockid; ret->pt_crefs = 1; - ret->pt_owner = nxsched_getpid(); + ret->pt_owner = tcb->pid; ret->pt_delay = 0; ret->pt_expected = 0; @@ -189,6 +191,25 @@ int timer_create(clockid_t clockid, FAR struct sigevent *evp, if (evp) { + FAR struct tcb_s *ntcb; + + /* Check the SIGEV_THREAD_ID and validate the tid */ + + if (evp->sigev_notify & SIGEV_THREAD_ID) + { + /* Make sure that the notified thread is + * in same process with current thread. + */ + + ntcb = nxsched_get_tcb(evp->sigev_notify_thread_id); + + if (ntcb == NULL || tcb->group != ntcb->group) + { + set_errno(EINVAL); + return ERROR; + } + } + /* Yes, copy the entire struct sigevent content */ memcpy(&ret->pt_event, evp, sizeof(struct sigevent));