[Xenomai-git] Philippe Gerum : copperplate/notifier: enable notifying remote threads

2014-05-16 Thread git repository hosting
Module: xenomai-forge
Branch: master
Commit: 8723e45601586e8a73583e33fe3bcea296f23d44
URL:
http://git.xenomai.org/?p=xenomai-forge.git;a=commit;h=8723e45601586e8a73583e33fe3bcea296f23d44

Author: Philippe Gerum r...@xenomai.org
Date:   Wed May  7 18:12:07 2014 +0200

copperplate/notifier: enable notifying remote threads

In shared multi-processing mode, we may have to suspend/resume threads
which belong to sibling processes from the same Copperplate session.

To this end, we drop the local pipe previously used for waiting for
the resume event. The suspended thread now waits for SIGRESM directly
via sigsuspend(), which is async-signal-safe.

As a side-effect, a suspended thread won't be allowed to handle any
blockable signal but SIGRESM until it is resumed, which follows the
principle of least astonishment.

---

 include/copperplate/notifier.h   |7 +-
 include/mercury/boilerplate/signal.h |9 ++-
 lib/copperplate/notifier.c   |  133 --
 lib/copperplate/threadobj.c  |   28 ---
 4 files changed, 61 insertions(+), 116 deletions(-)

diff --git a/include/copperplate/notifier.h b/include/copperplate/notifier.h
index 61e2ec4..011accf 100644
--- a/include/copperplate/notifier.h
+++ b/include/copperplate/notifier.h
@@ -23,7 +23,6 @@
 
 struct notifier {
pid_t owner;
-   int waitfd[2];
struct pvholder link;
 };
 
@@ -33,11 +32,15 @@ extern C {
 
 int notifier_init(struct notifier *nf, pid_t pid);
 
+static inline void notifier_destroy(struct notifier *nf)
+{
+}
+
 void notifier_destroy(struct notifier *nf);
 
 void notifier_signal(struct notifier *nf);
 
-void notifier_wait(const struct notifier *nf);
+void notifier_wait(void);
 
 void notifier_disable(struct notifier *nf);
 
diff --git a/include/mercury/boilerplate/signal.h 
b/include/mercury/boilerplate/signal.h
index df131fa..914c02c 100644
--- a/include/mercury/boilerplate/signal.h
+++ b/include/mercury/boilerplate/signal.h
@@ -24,15 +24,16 @@
 #define sigev_notify_thread_id  _sigev_un._tid
 #endif
 
-#define SIGNOTIFY  (SIGRTMIN + 8) /* Internal notification */
-#define SIGRELS(SIGRTMIN + 9) /* Syscall abort */
-#define SIGRRB (SIGRTMIN + 10) /* Round-robin event */
+#define SIGSUSP(SIGRTMIN + 8)
+#define SIGRESM(SIGRTMIN + 9)
+#define SIGRELS(SIGRTMIN + 10) /* Syscall abort */
+#define SIGRRB (SIGRTMIN + 11) /* Round-robin event */
 
 #define SIGSAFE_LOCK_ENTRY(__safelock) \
do {\
sigset_t __safeset, __oldsafeset;   \
sigemptyset(__safeset);\
-   sigaddset(__safeset, SIGNOTIFY);   \
+   sigaddset(__safeset, SIGSUSP); \
pthread_sigmask(SIG_BLOCK, __safeset, __oldsafeset);  \
push_cleanup_lock(__safelock);  \
write_lock(__safelock);
diff --git a/lib/copperplate/notifier.c b/lib/copperplate/notifier.c
index 0e8c832..0f02059 100644
--- a/lib/copperplate/notifier.c
+++ b/lib/copperplate/notifier.c
@@ -18,140 +18,69 @@
 
 #include signal.h
 #include memory.h
-#include unistd.h
-#include fcntl.h
-#include assert.h
 #include errno.h
 #include copperplate/notifier.h
-#include boilerplate/lock.h
 #include boilerplate/signal.h
-#include copperplate/debug.h
 #include internal.h
 
-static DEFINE_PRIVATE_LIST(notifier_list);
-
-static pthread_mutex_t notifier_lock;
-
-static struct sigaction notifier_old_sa;
-
-static void notifier_sighandler(int sig, siginfo_t *siginfo, void *uc)
+static void suspend_sighandler(int sig)
 {
-   struct notifier *nf;
-   pid_t tid;
-
-   tid = copperplate_get_tid();
-
-   if (pvlist_empty(notifier_list))
-   goto ouch;
-
-   /* We may NOT alter the notifier list, but only scan it. */
-   pvlist_for_each_entry(nf, notifier_list, link) {
-   if (nf-owner == tid) {
-   notifier_wait(nf);
-   return;
-   }
-   }
-ouch:
-   panic(received spurious notification on thread[%d] 
- (sig=%d, code=%d, fd=%d),
- tid, sig, siginfo-si_code, siginfo-si_fd);
+   notifier_wait();
 }
 
-static void lock_notifier_list(sigset_t *oset)
+static void resume_sighandler(int sig)
 {
-   sigset_t set;
-
-   sigemptyset(set);
-   sigaddset(set, SIGNOTIFY);
-   pthread_sigmask(SIG_BLOCK, set, oset);
-   write_lock(notifier_lock);
-}
-
-static void unlock_notifier_list(sigset_t *oset)
-{
-   pthread_sigmask(SIG_SETMASK, oset, NULL);
-   write_unlock(notifier_lock);
+   /* nop */
 }
 
 int notifier_init(struct notifier *nf, pid_t pid)
 {
-   sigset_t oset;
-   int ret;
-
-   if (pipe(nf-waitfd)  0) {
-  

[Xenomai-git] Philippe Gerum : copperplate/notifier: enable notifying remote threads

2014-05-13 Thread git repository hosting
Module: xenomai-forge
Branch: next
Commit: 8723e45601586e8a73583e33fe3bcea296f23d44
URL:
http://git.xenomai.org/?p=xenomai-forge.git;a=commit;h=8723e45601586e8a73583e33fe3bcea296f23d44

Author: Philippe Gerum r...@xenomai.org
Date:   Wed May  7 18:12:07 2014 +0200

copperplate/notifier: enable notifying remote threads

In shared multi-processing mode, we may have to suspend/resume threads
which belong to sibling processes from the same Copperplate session.

To this end, we drop the local pipe previously used for waiting for
the resume event. The suspended thread now waits for SIGRESM directly
via sigsuspend(), which is async-signal-safe.

As a side-effect, a suspended thread won't be allowed to handle any
blockable signal but SIGRESM until it is resumed, which follows the
principle of least astonishment.

---

 include/copperplate/notifier.h   |7 +-
 include/mercury/boilerplate/signal.h |9 ++-
 lib/copperplate/notifier.c   |  133 --
 lib/copperplate/threadobj.c  |   28 ---
 4 files changed, 61 insertions(+), 116 deletions(-)

diff --git a/include/copperplate/notifier.h b/include/copperplate/notifier.h
index 61e2ec4..011accf 100644
--- a/include/copperplate/notifier.h
+++ b/include/copperplate/notifier.h
@@ -23,7 +23,6 @@
 
 struct notifier {
pid_t owner;
-   int waitfd[2];
struct pvholder link;
 };
 
@@ -33,11 +32,15 @@ extern C {
 
 int notifier_init(struct notifier *nf, pid_t pid);
 
+static inline void notifier_destroy(struct notifier *nf)
+{
+}
+
 void notifier_destroy(struct notifier *nf);
 
 void notifier_signal(struct notifier *nf);
 
-void notifier_wait(const struct notifier *nf);
+void notifier_wait(void);
 
 void notifier_disable(struct notifier *nf);
 
diff --git a/include/mercury/boilerplate/signal.h 
b/include/mercury/boilerplate/signal.h
index df131fa..914c02c 100644
--- a/include/mercury/boilerplate/signal.h
+++ b/include/mercury/boilerplate/signal.h
@@ -24,15 +24,16 @@
 #define sigev_notify_thread_id  _sigev_un._tid
 #endif
 
-#define SIGNOTIFY  (SIGRTMIN + 8) /* Internal notification */
-#define SIGRELS(SIGRTMIN + 9) /* Syscall abort */
-#define SIGRRB (SIGRTMIN + 10) /* Round-robin event */
+#define SIGSUSP(SIGRTMIN + 8)
+#define SIGRESM(SIGRTMIN + 9)
+#define SIGRELS(SIGRTMIN + 10) /* Syscall abort */
+#define SIGRRB (SIGRTMIN + 11) /* Round-robin event */
 
 #define SIGSAFE_LOCK_ENTRY(__safelock) \
do {\
sigset_t __safeset, __oldsafeset;   \
sigemptyset(__safeset);\
-   sigaddset(__safeset, SIGNOTIFY);   \
+   sigaddset(__safeset, SIGSUSP); \
pthread_sigmask(SIG_BLOCK, __safeset, __oldsafeset);  \
push_cleanup_lock(__safelock);  \
write_lock(__safelock);
diff --git a/lib/copperplate/notifier.c b/lib/copperplate/notifier.c
index 0e8c832..0f02059 100644
--- a/lib/copperplate/notifier.c
+++ b/lib/copperplate/notifier.c
@@ -18,140 +18,69 @@
 
 #include signal.h
 #include memory.h
-#include unistd.h
-#include fcntl.h
-#include assert.h
 #include errno.h
 #include copperplate/notifier.h
-#include boilerplate/lock.h
 #include boilerplate/signal.h
-#include copperplate/debug.h
 #include internal.h
 
-static DEFINE_PRIVATE_LIST(notifier_list);
-
-static pthread_mutex_t notifier_lock;
-
-static struct sigaction notifier_old_sa;
-
-static void notifier_sighandler(int sig, siginfo_t *siginfo, void *uc)
+static void suspend_sighandler(int sig)
 {
-   struct notifier *nf;
-   pid_t tid;
-
-   tid = copperplate_get_tid();
-
-   if (pvlist_empty(notifier_list))
-   goto ouch;
-
-   /* We may NOT alter the notifier list, but only scan it. */
-   pvlist_for_each_entry(nf, notifier_list, link) {
-   if (nf-owner == tid) {
-   notifier_wait(nf);
-   return;
-   }
-   }
-ouch:
-   panic(received spurious notification on thread[%d] 
- (sig=%d, code=%d, fd=%d),
- tid, sig, siginfo-si_code, siginfo-si_fd);
+   notifier_wait();
 }
 
-static void lock_notifier_list(sigset_t *oset)
+static void resume_sighandler(int sig)
 {
-   sigset_t set;
-
-   sigemptyset(set);
-   sigaddset(set, SIGNOTIFY);
-   pthread_sigmask(SIG_BLOCK, set, oset);
-   write_lock(notifier_lock);
-}
-
-static void unlock_notifier_list(sigset_t *oset)
-{
-   pthread_sigmask(SIG_SETMASK, oset, NULL);
-   write_unlock(notifier_lock);
+   /* nop */
 }
 
 int notifier_init(struct notifier *nf, pid_t pid)
 {
-   sigset_t oset;
-   int ret;
-
-   if (pipe(nf-waitfd)  0) {
-

[Xenomai-git] Philippe Gerum : copperplate/notifier: enable notifying remote threads

2014-05-08 Thread git repository hosting
Module: xenomai-forge
Branch: next
Commit: 47488652207cc0f3dc35611c593ff9effed1381b
URL:
http://git.xenomai.org/?p=xenomai-forge.git;a=commit;h=47488652207cc0f3dc35611c593ff9effed1381b

Author: Philippe Gerum r...@xenomai.org
Date:   Wed May  7 18:12:07 2014 +0200

copperplate/notifier: enable notifying remote threads

In shared multi-processing mode, we may have to suspend/resume threads
which belong to sibling processes from the same Copperplate session.

To this end, we drop the local pipe previously used for waiting for
the resume event. The suspended thread now waits for SIGRESM directly
via sigsuspend(), which is async-signal-safe.

As a side-effect, a suspended thread won't be allowed to handle any
blockable signal but SIGRESM until it is resumed, which follows the
principle of least astonishment.

---

 include/copperplate/notifier.h   |7 +-
 include/mercury/boilerplate/signal.h |9 ++-
 lib/copperplate/notifier.c   |  133 --
 lib/copperplate/threadobj.c  |   28 ---
 4 files changed, 61 insertions(+), 116 deletions(-)

diff --git a/include/copperplate/notifier.h b/include/copperplate/notifier.h
index 61e2ec4..011accf 100644
--- a/include/copperplate/notifier.h
+++ b/include/copperplate/notifier.h
@@ -23,7 +23,6 @@
 
 struct notifier {
pid_t owner;
-   int waitfd[2];
struct pvholder link;
 };
 
@@ -33,11 +32,15 @@ extern C {
 
 int notifier_init(struct notifier *nf, pid_t pid);
 
+static inline void notifier_destroy(struct notifier *nf)
+{
+}
+
 void notifier_destroy(struct notifier *nf);
 
 void notifier_signal(struct notifier *nf);
 
-void notifier_wait(const struct notifier *nf);
+void notifier_wait(void);
 
 void notifier_disable(struct notifier *nf);
 
diff --git a/include/mercury/boilerplate/signal.h 
b/include/mercury/boilerplate/signal.h
index df131fa..914c02c 100644
--- a/include/mercury/boilerplate/signal.h
+++ b/include/mercury/boilerplate/signal.h
@@ -24,15 +24,16 @@
 #define sigev_notify_thread_id  _sigev_un._tid
 #endif
 
-#define SIGNOTIFY  (SIGRTMIN + 8) /* Internal notification */
-#define SIGRELS(SIGRTMIN + 9) /* Syscall abort */
-#define SIGRRB (SIGRTMIN + 10) /* Round-robin event */
+#define SIGSUSP(SIGRTMIN + 8)
+#define SIGRESM(SIGRTMIN + 9)
+#define SIGRELS(SIGRTMIN + 10) /* Syscall abort */
+#define SIGRRB (SIGRTMIN + 11) /* Round-robin event */
 
 #define SIGSAFE_LOCK_ENTRY(__safelock) \
do {\
sigset_t __safeset, __oldsafeset;   \
sigemptyset(__safeset);\
-   sigaddset(__safeset, SIGNOTIFY);   \
+   sigaddset(__safeset, SIGSUSP); \
pthread_sigmask(SIG_BLOCK, __safeset, __oldsafeset);  \
push_cleanup_lock(__safelock);  \
write_lock(__safelock);
diff --git a/lib/copperplate/notifier.c b/lib/copperplate/notifier.c
index 0e8c832..0f02059 100644
--- a/lib/copperplate/notifier.c
+++ b/lib/copperplate/notifier.c
@@ -18,140 +18,69 @@
 
 #include signal.h
 #include memory.h
-#include unistd.h
-#include fcntl.h
-#include assert.h
 #include errno.h
 #include copperplate/notifier.h
-#include boilerplate/lock.h
 #include boilerplate/signal.h
-#include copperplate/debug.h
 #include internal.h
 
-static DEFINE_PRIVATE_LIST(notifier_list);
-
-static pthread_mutex_t notifier_lock;
-
-static struct sigaction notifier_old_sa;
-
-static void notifier_sighandler(int sig, siginfo_t *siginfo, void *uc)
+static void suspend_sighandler(int sig)
 {
-   struct notifier *nf;
-   pid_t tid;
-
-   tid = copperplate_get_tid();
-
-   if (pvlist_empty(notifier_list))
-   goto ouch;
-
-   /* We may NOT alter the notifier list, but only scan it. */
-   pvlist_for_each_entry(nf, notifier_list, link) {
-   if (nf-owner == tid) {
-   notifier_wait(nf);
-   return;
-   }
-   }
-ouch:
-   panic(received spurious notification on thread[%d] 
- (sig=%d, code=%d, fd=%d),
- tid, sig, siginfo-si_code, siginfo-si_fd);
+   notifier_wait();
 }
 
-static void lock_notifier_list(sigset_t *oset)
+static void resume_sighandler(int sig)
 {
-   sigset_t set;
-
-   sigemptyset(set);
-   sigaddset(set, SIGNOTIFY);
-   pthread_sigmask(SIG_BLOCK, set, oset);
-   write_lock(notifier_lock);
-}
-
-static void unlock_notifier_list(sigset_t *oset)
-{
-   pthread_sigmask(SIG_SETMASK, oset, NULL);
-   write_unlock(notifier_lock);
+   /* nop */
 }
 
 int notifier_init(struct notifier *nf, pid_t pid)
 {
-   sigset_t oset;
-   int ret;
-
-   if (pipe(nf-waitfd)  0) {
-

[Xenomai-git] Philippe Gerum : copperplate/notifier: enable notifying remote threads

2014-05-07 Thread git repository hosting
Module: xenomai-forge
Branch: next
Commit: ee48f34eeb1c88dd153f04fd4519276a20b1334b
URL:
http://git.xenomai.org/?p=xenomai-forge.git;a=commit;h=ee48f34eeb1c88dd153f04fd4519276a20b1334b

Author: Philippe Gerum r...@xenomai.org
Date:   Wed May  7 18:12:07 2014 +0200

copperplate/notifier: enable notifying remote threads

In shared multi-processing mode, we may have to suspend/resume threads
which belong to sibling processes from the same Copperplate session.

To this end, the process-local pipe() is replaced by a signalfd
descriptor associated to the dedicated SIGRESM signal, which we read
from when waiting for the wake up call. Such call is issued via the
tkill(2) interface, to make sure it is queued for the proper thread
(i.e. no fallback delivery to a member of the same thread group).

---

 include/copperplate/notifier.h   |2 +-
 include/mercury/boilerplate/signal.h |9 ++---
 lib/copperplate/notifier.c   |   63 +-
 3 files changed, 37 insertions(+), 37 deletions(-)

diff --git a/include/copperplate/notifier.h b/include/copperplate/notifier.h
index 61e2ec4..0518477 100644
--- a/include/copperplate/notifier.h
+++ b/include/copperplate/notifier.h
@@ -23,7 +23,7 @@
 
 struct notifier {
pid_t owner;
-   int waitfd[2];
+   int sigfd;
struct pvholder link;
 };
 
diff --git a/include/mercury/boilerplate/signal.h 
b/include/mercury/boilerplate/signal.h
index df131fa..914c02c 100644
--- a/include/mercury/boilerplate/signal.h
+++ b/include/mercury/boilerplate/signal.h
@@ -24,15 +24,16 @@
 #define sigev_notify_thread_id  _sigev_un._tid
 #endif
 
-#define SIGNOTIFY  (SIGRTMIN + 8) /* Internal notification */
-#define SIGRELS(SIGRTMIN + 9) /* Syscall abort */
-#define SIGRRB (SIGRTMIN + 10) /* Round-robin event */
+#define SIGSUSP(SIGRTMIN + 8)
+#define SIGRESM(SIGRTMIN + 9)
+#define SIGRELS(SIGRTMIN + 10) /* Syscall abort */
+#define SIGRRB (SIGRTMIN + 11) /* Round-robin event */
 
 #define SIGSAFE_LOCK_ENTRY(__safelock) \
do {\
sigset_t __safeset, __oldsafeset;   \
sigemptyset(__safeset);\
-   sigaddset(__safeset, SIGNOTIFY);   \
+   sigaddset(__safeset, SIGSUSP); \
pthread_sigmask(SIG_BLOCK, __safeset, __oldsafeset);  \
push_cleanup_lock(__safelock);  \
write_lock(__safelock);
diff --git a/lib/copperplate/notifier.c b/lib/copperplate/notifier.c
index 0e8c832..45b3c9a 100644
--- a/lib/copperplate/notifier.c
+++ b/lib/copperplate/notifier.c
@@ -16,6 +16,7 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA.
  */
 
+#include sys/signalfd.h
 #include signal.h
 #include memory.h
 #include unistd.h
@@ -32,8 +33,6 @@ static DEFINE_PRIVATE_LIST(notifier_list);
 
 static pthread_mutex_t notifier_lock;
 
-static struct sigaction notifier_old_sa;
-
 static void notifier_sighandler(int sig, siginfo_t *siginfo, void *uc)
 {
struct notifier *nf;
@@ -61,10 +60,18 @@ static void lock_notifier_list(sigset_t *oset)
 {
sigset_t set;
 
+   /*
+* We want to defer the SIGSUSP delivery until the list is
+* unlocked, so that notifier_sighandler() will always see a
+* consistent linkage when traversing such list. Since the
+* signal handler and the lock holder always run on the same
+* process, we may use a private list, and the synchronization
+* mechanism is inherently SMP-safe. Yummie.
+*/
sigemptyset(set);
-   sigaddset(set, SIGNOTIFY);
+   sigaddset(set, SIGSUSP);
pthread_sigmask(SIG_BLOCK, set, oset);
-   write_lock(notifier_lock);
+   write_lock_nocancel(notifier_lock);
 }
 
 static void unlock_notifier_list(sigset_t *oset)
@@ -75,27 +82,24 @@ static void unlock_notifier_list(sigset_t *oset)
 
 int notifier_init(struct notifier *nf, pid_t pid)
 {
-   sigset_t oset;
-   int ret;
+   sigset_t set;
 
-   if (pipe(nf-waitfd)  0) {
-   ret = -errno;
-   goto fail;
-   }
+   sigemptyset(set);
+   sigaddset(set, SIGRESM);
+   nf-sigfd = signalfd(-1, set, SFD_CLOEXEC);
+   if (nf-sigfd  0)
+   return __bt(-errno);
 
nf-owner = pid;
+   pthread_sigmask(SIG_BLOCK, set, NULL);
 
push_cleanup_lock(notifier_lock);
-   lock_notifier_list(oset);
+   lock_notifier_list(set);
pvlist_append(nf-link, notifier_list);
-   unlock_notifier_list(oset);
+   unlock_notifier_list(set);
pop_cleanup_lock(notifier_lock);
 
return 0;
-fail:
-   warning(failed to create notifier pipe);
-
-   return __bt(ret);
 }
 

[Xenomai-git] Philippe Gerum : copperplate/notifier: enable notifying remote threads

2014-05-07 Thread git repository hosting
Module: xenomai-forge
Branch: next
Commit: a7f7fea6fc02f082873a84c38a6247ef40d35aec
URL:
http://git.xenomai.org/?p=xenomai-forge.git;a=commit;h=a7f7fea6fc02f082873a84c38a6247ef40d35aec

Author: Philippe Gerum r...@xenomai.org
Date:   Wed May  7 18:12:07 2014 +0200

copperplate/notifier: enable notifying remote threads

In shared multi-processing mode, we may have to suspend/resume threads
which belong to sibling processes from the same Copperplate session.

To this end, the process-local pipe() is replaced by a signalfd
descriptor associated to the dedicated SIGRESM signal, which we read
from when waiting for the wake up call. Such call is issued via the
tkill(2) interface, to make sure it is queued for the proper thread
(i.e. no fallback delivery to a member of the same thread group).

---

 include/copperplate/notifier.h   |2 +-
 include/mercury/boilerplate/signal.h |9 ++---
 lib/copperplate/notifier.c   |   60 --
 3 files changed, 34 insertions(+), 37 deletions(-)

diff --git a/include/copperplate/notifier.h b/include/copperplate/notifier.h
index 61e2ec4..0518477 100644
--- a/include/copperplate/notifier.h
+++ b/include/copperplate/notifier.h
@@ -23,7 +23,7 @@
 
 struct notifier {
pid_t owner;
-   int waitfd[2];
+   int sigfd;
struct pvholder link;
 };
 
diff --git a/include/mercury/boilerplate/signal.h 
b/include/mercury/boilerplate/signal.h
index df131fa..914c02c 100644
--- a/include/mercury/boilerplate/signal.h
+++ b/include/mercury/boilerplate/signal.h
@@ -24,15 +24,16 @@
 #define sigev_notify_thread_id  _sigev_un._tid
 #endif
 
-#define SIGNOTIFY  (SIGRTMIN + 8) /* Internal notification */
-#define SIGRELS(SIGRTMIN + 9) /* Syscall abort */
-#define SIGRRB (SIGRTMIN + 10) /* Round-robin event */
+#define SIGSUSP(SIGRTMIN + 8)
+#define SIGRESM(SIGRTMIN + 9)
+#define SIGRELS(SIGRTMIN + 10) /* Syscall abort */
+#define SIGRRB (SIGRTMIN + 11) /* Round-robin event */
 
 #define SIGSAFE_LOCK_ENTRY(__safelock) \
do {\
sigset_t __safeset, __oldsafeset;   \
sigemptyset(__safeset);\
-   sigaddset(__safeset, SIGNOTIFY);   \
+   sigaddset(__safeset, SIGSUSP); \
pthread_sigmask(SIG_BLOCK, __safeset, __oldsafeset);  \
push_cleanup_lock(__safelock);  \
write_lock(__safelock);
diff --git a/lib/copperplate/notifier.c b/lib/copperplate/notifier.c
index 0e8c832..02c31ec 100644
--- a/lib/copperplate/notifier.c
+++ b/lib/copperplate/notifier.c
@@ -16,6 +16,7 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA.
  */
 
+#include sys/signalfd.h
 #include signal.h
 #include memory.h
 #include unistd.h
@@ -32,8 +33,6 @@ static DEFINE_PRIVATE_LIST(notifier_list);
 
 static pthread_mutex_t notifier_lock;
 
-static struct sigaction notifier_old_sa;
-
 static void notifier_sighandler(int sig, siginfo_t *siginfo, void *uc)
 {
struct notifier *nf;
@@ -61,10 +60,15 @@ static void lock_notifier_list(sigset_t *oset)
 {
sigset_t set;
 
+   /*
+* We want to defer the SIGSUSP delivery until the list is
+* unlocked, so that notifier_sighandler() will always see a
+* consistent linkage when traversing such list.
+*/
sigemptyset(set);
-   sigaddset(set, SIGNOTIFY);
+   sigaddset(set, SIGSUSP);
pthread_sigmask(SIG_BLOCK, set, oset);
-   write_lock(notifier_lock);
+   write_lock_nocancel(notifier_lock);
 }
 
 static void unlock_notifier_list(sigset_t *oset)
@@ -75,27 +79,24 @@ static void unlock_notifier_list(sigset_t *oset)
 
 int notifier_init(struct notifier *nf, pid_t pid)
 {
-   sigset_t oset;
-   int ret;
+   sigset_t set;
 
-   if (pipe(nf-waitfd)  0) {
-   ret = -errno;
-   goto fail;
-   }
+   sigemptyset(set);
+   sigaddset(set, SIGRESM);
+   nf-sigfd = signalfd(-1, set, SFD_CLOEXEC);
+   if (nf-sigfd  0)
+   return __bt(-errno);
 
nf-owner = pid;
+   pthread_sigmask(SIG_BLOCK, set, NULL);
 
push_cleanup_lock(notifier_lock);
-   lock_notifier_list(oset);
+   lock_notifier_list(set);
pvlist_append(nf-link, notifier_list);
-   unlock_notifier_list(oset);
+   unlock_notifier_list(set);
pop_cleanup_lock(notifier_lock);
 
return 0;
-fail:
-   warning(failed to create notifier pipe);
-
-   return __bt(ret);
 }
 
 void notifier_destroy(struct notifier *nf)
@@ -107,38 +108,32 @@ void notifier_destroy(struct notifier *nf)
pvlist_remove(nf-link);
unlock_notifier_list(oset);

[Xenomai-git] Philippe Gerum : copperplate/notifier: enable notifying remote threads

2014-05-07 Thread git repository hosting
Module: xenomai-forge
Branch: next
Commit: c07dbdfb9891a2d2d7f41aaa20cf1b54adc047d9
URL:
http://git.xenomai.org/?p=xenomai-forge.git;a=commit;h=c07dbdfb9891a2d2d7f41aaa20cf1b54adc047d9

Author: Philippe Gerum r...@xenomai.org
Date:   Wed May  7 18:12:07 2014 +0200

copperplate/notifier: enable notifying remote threads

In shared multi-processing mode, we may have to suspend/resume threads
which belong to sibling processes from the same Copperplate session.

To this end, the process-local pipe() is replaced by a signalfd
descriptor associated to the dedicated SIGRESM signal, which we read
from when waiting for the wake up call. Such call is issued via the
tkill(2) interface, to make sure it is queued for the proper thread
(i.e. no fallback delivery to a member of the same thread group).

---

 include/copperplate/notifier.h   |2 +-
 include/mercury/boilerplate/signal.h |9 ++---
 lib/copperplate/notifier.c   |   63 +-
 3 files changed, 37 insertions(+), 37 deletions(-)

diff --git a/include/copperplate/notifier.h b/include/copperplate/notifier.h
index 61e2ec4..0518477 100644
--- a/include/copperplate/notifier.h
+++ b/include/copperplate/notifier.h
@@ -23,7 +23,7 @@
 
 struct notifier {
pid_t owner;
-   int waitfd[2];
+   int sigfd;
struct pvholder link;
 };
 
diff --git a/include/mercury/boilerplate/signal.h 
b/include/mercury/boilerplate/signal.h
index df131fa..914c02c 100644
--- a/include/mercury/boilerplate/signal.h
+++ b/include/mercury/boilerplate/signal.h
@@ -24,15 +24,16 @@
 #define sigev_notify_thread_id  _sigev_un._tid
 #endif
 
-#define SIGNOTIFY  (SIGRTMIN + 8) /* Internal notification */
-#define SIGRELS(SIGRTMIN + 9) /* Syscall abort */
-#define SIGRRB (SIGRTMIN + 10) /* Round-robin event */
+#define SIGSUSP(SIGRTMIN + 8)
+#define SIGRESM(SIGRTMIN + 9)
+#define SIGRELS(SIGRTMIN + 10) /* Syscall abort */
+#define SIGRRB (SIGRTMIN + 11) /* Round-robin event */
 
 #define SIGSAFE_LOCK_ENTRY(__safelock) \
do {\
sigset_t __safeset, __oldsafeset;   \
sigemptyset(__safeset);\
-   sigaddset(__safeset, SIGNOTIFY);   \
+   sigaddset(__safeset, SIGSUSP); \
pthread_sigmask(SIG_BLOCK, __safeset, __oldsafeset);  \
push_cleanup_lock(__safelock);  \
write_lock(__safelock);
diff --git a/lib/copperplate/notifier.c b/lib/copperplate/notifier.c
index 0e8c832..d3dcdae 100644
--- a/lib/copperplate/notifier.c
+++ b/lib/copperplate/notifier.c
@@ -16,6 +16,7 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA.
  */
 
+#include sys/signalfd.h
 #include signal.h
 #include memory.h
 #include unistd.h
@@ -32,8 +33,6 @@ static DEFINE_PRIVATE_LIST(notifier_list);
 
 static pthread_mutex_t notifier_lock;
 
-static struct sigaction notifier_old_sa;
-
 static void notifier_sighandler(int sig, siginfo_t *siginfo, void *uc)
 {
struct notifier *nf;
@@ -61,10 +60,18 @@ static void lock_notifier_list(sigset_t *oset)
 {
sigset_t set;
 
+   /*
+* We want to defer the SIGSUSP delivery until the list is
+* unlocked, so that notifier_sighandler() will always see a
+* consistent linkage when traversing such list.
+*
+* FIXME: this is still racy (thread != caller vs
+* notifier_sighandler()).
+*/
sigemptyset(set);
-   sigaddset(set, SIGNOTIFY);
+   sigaddset(set, SIGSUSP);
pthread_sigmask(SIG_BLOCK, set, oset);
-   write_lock(notifier_lock);
+   write_lock_nocancel(notifier_lock);
 }
 
 static void unlock_notifier_list(sigset_t *oset)
@@ -75,27 +82,24 @@ static void unlock_notifier_list(sigset_t *oset)
 
 int notifier_init(struct notifier *nf, pid_t pid)
 {
-   sigset_t oset;
-   int ret;
+   sigset_t set;
 
-   if (pipe(nf-waitfd)  0) {
-   ret = -errno;
-   goto fail;
-   }
+   sigemptyset(set);
+   sigaddset(set, SIGRESM);
+   nf-sigfd = signalfd(-1, set, SFD_CLOEXEC);
+   if (nf-sigfd  0)
+   return __bt(-errno);
 
nf-owner = pid;
+   pthread_sigmask(SIG_BLOCK, set, NULL);
 
push_cleanup_lock(notifier_lock);
-   lock_notifier_list(oset);
+   lock_notifier_list(set);
pvlist_append(nf-link, notifier_list);
-   unlock_notifier_list(oset);
+   unlock_notifier_list(set);
pop_cleanup_lock(notifier_lock);
 
return 0;
-fail:
-   warning(failed to create notifier pipe);
-
-   return __bt(ret);
 }
 
 void notifier_destroy(struct notifier *nf)
@@ -107,38 +111,32 @@ void notifier_destroy(struct