[Xenomai-git] Philippe Gerum : copperplate/notifier: enable notifying remote threads
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
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
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
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
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
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