[Xenomai-git] Philippe Gerum : cobalt/signal: implement thread group sending

2013-10-01 Thread git repository hosting
Module: xenomai-forge
Branch: master
Commit: 800302464f0ad3367ba6341b6ce2354fdbbdf350
URL:
http://git.xenomai.org/?p=xenomai-forge.git;a=commit;h=800302464f0ad3367ba6341b6ce2354fdbbdf350

Author: Philippe Gerum 
Date:   Wed Sep 11 16:41:47 2013 +0200

cobalt/signal: implement thread group sending

When a signal is sent via the kill() interface and the destination
thread is not waiting for that signal, we try to deliver it to any of
the threads which belong to the same process. If no thread is waiting
for this signal, it is queued for the destination thread as usual.

This change does not affect the behavior of pthread_kill(), which
remains strictly thread-targeted.

---

 kernel/cobalt/posix/mqueue.c  |2 +-
 kernel/cobalt/posix/process.h |1 +
 kernel/cobalt/posix/signal.c  |   51 ++--
 kernel/cobalt/posix/signal.h  |6 +++-
 kernel/cobalt/posix/syscall.c |2 +
 kernel/cobalt/posix/thread.c  |   22 +
 kernel/cobalt/posix/thread.h  |4 +++
 7 files changed, 67 insertions(+), 21 deletions(-)

diff --git a/kernel/cobalt/posix/mqueue.c b/kernel/cobalt/posix/mqueue.c
index fe34fea..354ba19 100644
--- a/kernel/cobalt/posix/mqueue.c
+++ b/kernel/cobalt/posix/mqueue.c
@@ -623,7 +623,7 @@ cobalt_mq_finish_send(mqd_t fd, cobalt_mq_t *mq, struct 
cobalt_msg *msg)
sigp = cobalt_signal_alloc();
if (sigp) {
cobalt_copy_siginfo(SI_MESGQ, &sigp->si, &mq->si);
-   cobalt_signal_send(mq->target, sigp);
+   cobalt_signal_send(mq->target, sigp, 0);
resched = 1;
}
mq->target = NULL;
diff --git a/kernel/cobalt/posix/process.h b/kernel/cobalt/posix/process.h
index 121a802..42f3afd 100644
--- a/kernel/cobalt/posix/process.h
+++ b/kernel/cobalt/posix/process.h
@@ -36,6 +36,7 @@ struct cobalt_process {
struct list_head uqds;
struct list_head usems;
struct xnshadow_ppd ppd;
+   struct list_head sigwaiters;
 };
 
 extern struct cobalt_kqueues cobalt_global_kqueues;
diff --git a/kernel/cobalt/posix/signal.c b/kernel/cobalt/posix/signal.c
index 6a4199a..aa37f50 100644
--- a/kernel/cobalt/posix/signal.c
+++ b/kernel/cobalt/posix/signal.c
@@ -39,8 +39,9 @@ static LIST_HEAD(sigpending_pool);
 (_NSIG + (SIGRTMAX - SIGRTMIN) * 2))
 
 static int cobalt_signal_deliver(struct cobalt_thread *thread,
-struct cobalt_sigpending *sigp)
-{
+struct cobalt_sigpending *sigp,
+int group)
+{  /* nklocked, IRQs off */
struct cobalt_sigwait_context *swc;
struct xnthread_wait_context *wc;
int sig, ret;
@@ -48,18 +49,39 @@ static int cobalt_signal_deliver(struct cobalt_thread 
*thread,
sig = sigp->si.si_signo;
XENO_BUGON(COBALT, sig < 1 || sig > _NSIG);
 
-   if (!xnsynch_pended_p(&thread->sigwait))
-   return 0;
+   /*
+* Attempt to deliver the signal immediately to the initial
+* target that waits for it.
+*/
+   if (xnsynch_pended_p(&thread->sigwait)) {
+   wc = xnthread_get_wait_context(&thread->threadbase);
+   swc = container_of(wc, struct cobalt_sigwait_context, wc);
+   if (sigismember(swc->set, sig))
+   goto deliver;
+   }
 
-   wc = xnthread_get_wait_context(&thread->threadbase);
-   swc = container_of(wc, struct cobalt_sigwait_context, wc);
-   if (!sigismember(swc->set, sig))
+   /*
+* If that does not work out and we are sending to a thread
+* group, try to deliver to any thread from the same process
+* waiting for that signal.
+*/
+   if (!group || list_empty(&thread->process->sigwaiters))
return 0;
 
+   list_for_each_entry(thread, &thread->process->sigwaiters, signext) {
+   wc = xnthread_get_wait_context(&thread->threadbase);
+   swc = container_of(wc, struct cobalt_sigwait_context, wc);
+   if (sigismember(swc->set, sig))
+   goto deliver;
+   }
+
+   return 0;
+deliver:
cobalt_copy_siginfo(sigp->si.si_code, swc->si, &sigp->si);
cobalt_call_extension(signal_deliver, &thread->extref,
  ret, swc->si, sigp);
xnsynch_wakeup_one_sleeper(&thread->sigwait);
+   list_del(&thread->signext);
 
/*
 * This is an immediate delivery bypassing any queuing, so we
@@ -74,13 +96,14 @@ static int cobalt_signal_deliver(struct cobalt_thread 
*thread,
 }
 
 int cobalt_signal_send(struct cobalt_thread *thread,
-  struct cobalt_sigpending *sigp)
+  struct cobalt_sigpending *sigp,
+  int group)
 {  /* nklocked, IRQs off */
struc

[Xenomai-git] Philippe Gerum : cobalt/signal: implement thread group sending

2013-09-13 Thread git repository hosting
Module: xenomai-forge
Branch: next
Commit: 800302464f0ad3367ba6341b6ce2354fdbbdf350
URL:
http://git.xenomai.org/?p=xenomai-forge.git;a=commit;h=800302464f0ad3367ba6341b6ce2354fdbbdf350

Author: Philippe Gerum 
Date:   Wed Sep 11 16:41:47 2013 +0200

cobalt/signal: implement thread group sending

When a signal is sent via the kill() interface and the destination
thread is not waiting for that signal, we try to deliver it to any of
the threads which belong to the same process. If no thread is waiting
for this signal, it is queued for the destination thread as usual.

This change does not affect the behavior of pthread_kill(), which
remains strictly thread-targeted.

---

 kernel/cobalt/posix/mqueue.c  |2 +-
 kernel/cobalt/posix/process.h |1 +
 kernel/cobalt/posix/signal.c  |   51 ++--
 kernel/cobalt/posix/signal.h  |6 +++-
 kernel/cobalt/posix/syscall.c |2 +
 kernel/cobalt/posix/thread.c  |   22 +
 kernel/cobalt/posix/thread.h  |4 +++
 7 files changed, 67 insertions(+), 21 deletions(-)

diff --git a/kernel/cobalt/posix/mqueue.c b/kernel/cobalt/posix/mqueue.c
index fe34fea..354ba19 100644
--- a/kernel/cobalt/posix/mqueue.c
+++ b/kernel/cobalt/posix/mqueue.c
@@ -623,7 +623,7 @@ cobalt_mq_finish_send(mqd_t fd, cobalt_mq_t *mq, struct 
cobalt_msg *msg)
sigp = cobalt_signal_alloc();
if (sigp) {
cobalt_copy_siginfo(SI_MESGQ, &sigp->si, &mq->si);
-   cobalt_signal_send(mq->target, sigp);
+   cobalt_signal_send(mq->target, sigp, 0);
resched = 1;
}
mq->target = NULL;
diff --git a/kernel/cobalt/posix/process.h b/kernel/cobalt/posix/process.h
index 121a802..42f3afd 100644
--- a/kernel/cobalt/posix/process.h
+++ b/kernel/cobalt/posix/process.h
@@ -36,6 +36,7 @@ struct cobalt_process {
struct list_head uqds;
struct list_head usems;
struct xnshadow_ppd ppd;
+   struct list_head sigwaiters;
 };
 
 extern struct cobalt_kqueues cobalt_global_kqueues;
diff --git a/kernel/cobalt/posix/signal.c b/kernel/cobalt/posix/signal.c
index 6a4199a..aa37f50 100644
--- a/kernel/cobalt/posix/signal.c
+++ b/kernel/cobalt/posix/signal.c
@@ -39,8 +39,9 @@ static LIST_HEAD(sigpending_pool);
 (_NSIG + (SIGRTMAX - SIGRTMIN) * 2))
 
 static int cobalt_signal_deliver(struct cobalt_thread *thread,
-struct cobalt_sigpending *sigp)
-{
+struct cobalt_sigpending *sigp,
+int group)
+{  /* nklocked, IRQs off */
struct cobalt_sigwait_context *swc;
struct xnthread_wait_context *wc;
int sig, ret;
@@ -48,18 +49,39 @@ static int cobalt_signal_deliver(struct cobalt_thread 
*thread,
sig = sigp->si.si_signo;
XENO_BUGON(COBALT, sig < 1 || sig > _NSIG);
 
-   if (!xnsynch_pended_p(&thread->sigwait))
-   return 0;
+   /*
+* Attempt to deliver the signal immediately to the initial
+* target that waits for it.
+*/
+   if (xnsynch_pended_p(&thread->sigwait)) {
+   wc = xnthread_get_wait_context(&thread->threadbase);
+   swc = container_of(wc, struct cobalt_sigwait_context, wc);
+   if (sigismember(swc->set, sig))
+   goto deliver;
+   }
 
-   wc = xnthread_get_wait_context(&thread->threadbase);
-   swc = container_of(wc, struct cobalt_sigwait_context, wc);
-   if (!sigismember(swc->set, sig))
+   /*
+* If that does not work out and we are sending to a thread
+* group, try to deliver to any thread from the same process
+* waiting for that signal.
+*/
+   if (!group || list_empty(&thread->process->sigwaiters))
return 0;
 
+   list_for_each_entry(thread, &thread->process->sigwaiters, signext) {
+   wc = xnthread_get_wait_context(&thread->threadbase);
+   swc = container_of(wc, struct cobalt_sigwait_context, wc);
+   if (sigismember(swc->set, sig))
+   goto deliver;
+   }
+
+   return 0;
+deliver:
cobalt_copy_siginfo(sigp->si.si_code, swc->si, &sigp->si);
cobalt_call_extension(signal_deliver, &thread->extref,
  ret, swc->si, sigp);
xnsynch_wakeup_one_sleeper(&thread->sigwait);
+   list_del(&thread->signext);
 
/*
 * This is an immediate delivery bypassing any queuing, so we
@@ -74,13 +96,14 @@ static int cobalt_signal_deliver(struct cobalt_thread 
*thread,
 }
 
 int cobalt_signal_send(struct cobalt_thread *thread,
-  struct cobalt_sigpending *sigp)
+  struct cobalt_sigpending *sigp,
+  int group)
 {  /* nklocked, IRQs off */
struct