Module: xenomai-forge Branch: next Commit: a36021cdf17298ef27830af5de651b0f92c6c663 URL: http://git.xenomai.org/?p=xenomai-forge.git;a=commit;h=a36021cdf17298ef27830af5de651b0f92c6c663
Author: Philippe Gerum <r...@xenomai.org> Date: Thu May 8 17:35:46 2014 +0200 copperplate/notifier: merge to threadobj building block Now that the suspend/resume mechanism for Mercury is trivially simple, just merge it into where it belongs to, i.e. in the threadobj implementation. --- include/copperplate/Makefile.am | 1 - include/copperplate/Makefile.in | 1 - include/copperplate/notifier.h | 55 --------------------- include/copperplate/threadobj.h | 2 - lib/copperplate/Makefile.am | 1 - lib/copperplate/Makefile.in | 50 ++++++++----------- lib/copperplate/notifier.c | 103 --------------------------------------- lib/copperplate/threadobj.c | 89 +++++++++++++++++++++++++-------- 8 files changed, 90 insertions(+), 212 deletions(-) diff --git a/include/copperplate/Makefile.am b/include/copperplate/Makefile.am index f721ff8..89b92ff 100644 --- a/include/copperplate/Makefile.am +++ b/include/copperplate/Makefile.am @@ -8,7 +8,6 @@ includesub_HEADERS = \ heapobj.h \ init.h \ semobj.h \ - notifier.h \ reference.h \ registry.h \ syncobj.h \ diff --git a/include/copperplate/Makefile.in b/include/copperplate/Makefile.in index cc060cc..1db15f5 100644 --- a/include/copperplate/Makefile.in +++ b/include/copperplate/Makefile.in @@ -345,7 +345,6 @@ includesub_HEADERS = \ heapobj.h \ init.h \ semobj.h \ - notifier.h \ reference.h \ registry.h \ syncobj.h \ diff --git a/include/copperplate/notifier.h b/include/copperplate/notifier.h deleted file mode 100644 index 011accf..0000000 --- a/include/copperplate/notifier.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (C) 2008 Philippe Gerum <r...@xenomai.org>. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#ifndef _COPPERPLATE_NOTIFIER_H -#define _COPPERPLATE_NOTIFIER_H - -#include <boilerplate/list.h> - -struct notifier { - pid_t owner; - struct pvholder link; -}; - -#ifdef __cplusplus -extern "C" { -#endif - -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(void); - -void notifier_disable(struct notifier *nf); - -void notifier_release(struct notifier *nf); - -void notifier_pkg_init(void); - -#ifdef __cplusplus -} -#endif - -#endif /* _COPPERPLATE_NOTIFIER_H */ diff --git a/include/copperplate/threadobj.h b/include/copperplate/threadobj.h index 754de3d..fd87829 100644 --- a/include/copperplate/threadobj.h +++ b/include/copperplate/threadobj.h @@ -77,14 +77,12 @@ void threadobj_save_timeout(struct threadobj_corespec *corespec, #else /* CONFIG_XENO_MERCURY */ #include <sys/time.h> -#include <copperplate/notifier.h> struct threadobj_corespec { pthread_cond_t grant_sync; int policy_unlocked; int prio_unlocked; timer_t rr_timer; - struct notifier notifier; struct timespec wakeup; ticks_t period; /** Timeout reported by sysregd. */ diff --git a/lib/copperplate/Makefile.am b/lib/copperplate/Makefile.am index 17ebeb4..2664e53 100644 --- a/lib/copperplate/Makefile.am +++ b/lib/copperplate/Makefile.am @@ -46,7 +46,6 @@ clean-local: libcopperplate_la_LIBADD = libversion.la if XENO_MERCURY -libcopperplate_la_SOURCES += notifier.c libcopperplate_la_LIBADD += ../boilerplate/libboilerplate.la endif diff --git a/lib/copperplate/Makefile.in b/lib/copperplate/Makefile.in index a9b360e..0a948fe 100644 --- a/lib/copperplate/Makefile.in +++ b/lib/copperplate/Makefile.in @@ -79,17 +79,16 @@ POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ -@XENO_MERCURY_TRUE@am__append_1 = notifier.c -@XENO_MERCURY_TRUE@am__append_2 = ../boilerplate/libboilerplate.la +@XENO_MERCURY_TRUE@am__append_1 = ../boilerplate/libboilerplate.la +@XENO_REGISTRY_TRUE@am__append_2 = libregistry.la @XENO_REGISTRY_TRUE@am__append_3 = libregistry.la -@XENO_REGISTRY_TRUE@am__append_4 = libregistry.la # The process shareable heap has real-time properties, therefore it # fits both the cobalt and mercury cores equally. Yummie. -@XENO_PSHARED_TRUE@am__append_5 = heapobj-pshared.c reference.c -@XENO_TLSF_TRUE@am__append_6 = heapobj-tlsf.c -@XENO_TLSF_FALSE@am__append_7 = heapobj-malloc.c -@XENO_REGISTRY_TRUE@am__append_8 = regd +@XENO_PSHARED_TRUE@am__append_4 = heapobj-pshared.c reference.c +@XENO_TLSF_TRUE@am__append_5 = heapobj-tlsf.c +@XENO_TLSF_FALSE@am__append_6 = heapobj-malloc.c +@XENO_REGISTRY_TRUE@am__append_7 = regd subdir = lib/copperplate DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(top_srcdir)/config/depcomp COPYING @@ -137,18 +136,17 @@ am__uninstall_files_from_dir = { \ } am__installdirs = "$(DESTDIR)$(libdir)" LTLIBRARIES = $(lib_LTLIBRARIES) $(noinst_LTLIBRARIES) -libcopperplate_la_DEPENDENCIES = libversion.la $(am__append_2) \ - $(am__append_3) +libcopperplate_la_DEPENDENCIES = libversion.la $(am__append_1) \ + $(am__append_2) am__libcopperplate_la_SOURCES_DIST = clockobj.c cluster.c eventobj.c \ init.c internal.c internal.h main.c syncobj.c semobj.c \ - threadobj.c timerobj.c traceobj.c wrappers.c notifier.c \ - heapobj-pshared.c reference.c heapobj-tlsf.c heapobj-malloc.c -@XENO_MERCURY_TRUE@am__objects_1 = libcopperplate_la-notifier.lo -@XENO_PSHARED_TRUE@am__objects_2 = \ + threadobj.c timerobj.c traceobj.c wrappers.c heapobj-pshared.c \ + reference.c heapobj-tlsf.c heapobj-malloc.c +@XENO_PSHARED_TRUE@am__objects_1 = \ @XENO_PSHARED_TRUE@ libcopperplate_la-heapobj-pshared.lo \ @XENO_PSHARED_TRUE@ libcopperplate_la-reference.lo -@XENO_TLSF_TRUE@am__objects_3 = libcopperplate_la-heapobj-tlsf.lo -@XENO_TLSF_FALSE@am__objects_4 = libcopperplate_la-heapobj-malloc.lo +@XENO_TLSF_TRUE@am__objects_2 = libcopperplate_la-heapobj-tlsf.lo +@XENO_TLSF_FALSE@am__objects_3 = libcopperplate_la-heapobj-malloc.lo am_libcopperplate_la_OBJECTS = libcopperplate_la-clockobj.lo \ libcopperplate_la-cluster.lo libcopperplate_la-eventobj.lo \ libcopperplate_la-init.lo libcopperplate_la-internal.lo \ @@ -156,7 +154,7 @@ am_libcopperplate_la_OBJECTS = libcopperplate_la-clockobj.lo \ libcopperplate_la-semobj.lo libcopperplate_la-threadobj.lo \ libcopperplate_la-timerobj.lo libcopperplate_la-traceobj.lo \ libcopperplate_la-wrappers.lo $(am__objects_1) \ - $(am__objects_2) $(am__objects_3) $(am__objects_4) + $(am__objects_2) $(am__objects_3) libcopperplate_la_OBJECTS = $(am_libcopperplate_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) @@ -458,25 +456,25 @@ lib_LTLIBRARIES = libcopperplate.la libcopperplate_la_LDFLAGS = @XENO_LIB_LDFLAGS@ -version-info 0:0:0 libcopperplate_la_SOURCES = clockobj.c cluster.c eventobj.c init.c \ internal.c internal.h main.c syncobj.c semobj.c threadobj.c \ - timerobj.c traceobj.c wrappers.c $(am__append_1) \ - $(am__append_5) $(am__append_6) $(am__append_7) + timerobj.c traceobj.c wrappers.c $(am__append_4) \ + $(am__append_5) $(am__append_6) libcopperplate_la_CPPFLAGS = \ @XENO_USER_CFLAGS@ \ -I$(top_srcdir) \ -I$(top_srcdir)/include \ -I$(top_srcdir)/lib -noinst_LTLIBRARIES = libversion.la $(am__append_4) +noinst_LTLIBRARIES = libversion.la $(am__append_3) libversion_la_CFLAGS = @XENO_USER_CFLAGS@ libversion_la_SOURCES = version.c -libcopperplate_la_LIBADD = libversion.la $(am__append_2) \ - $(am__append_3) +libcopperplate_la_LIBADD = libversion.la $(am__append_1) \ + $(am__append_2) @XENO_REGISTRY_TRUE@libregistry_la_SOURCES = registry.c @XENO_REGISTRY_TRUE@libregistry_la_CPPFLAGS = \ @XENO_REGISTRY_TRUE@ $(libcopperplate_la_CPPFLAGS) \ @XENO_REGISTRY_TRUE@ @XENO_FUSE_CFLAGS@ -SUBDIRS = . $(am__append_8) +SUBDIRS = . $(am__append_7) SPARSE = sparse all: all-recursive @@ -583,7 +581,6 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcopperplate_la-init.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcopperplate_la-internal.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcopperplate_la-main.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcopperplate_la-notifier.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcopperplate_la-reference.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcopperplate_la-semobj.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcopperplate_la-syncobj.Plo@am__quote@ @@ -699,13 +696,6 @@ libcopperplate_la-wrappers.lo: wrappers.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcopperplate_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libcopperplate_la-wrappers.lo `test -f 'wrappers.c' || echo '$(srcdir)/'`wrappers.c -libcopperplate_la-notifier.lo: notifier.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcopperplate_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libcopperplate_la-notifier.lo -MD -MP -MF $(DEPDIR)/libcopperplate_la-notifier.Tpo -c -o libcopperplate_la-notifier.lo `test -f 'notifier.c' || echo '$(srcdir)/'`notifier.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcopperplate_la-notifier.Tpo $(DEPDIR)/libcopperplate_la-notifier.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='notifier.c' object='libcopperplate_la-notifier.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcopperplate_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libcopperplate_la-notifier.lo `test -f 'notifier.c' || echo '$(srcdir)/'`notifier.c - libcopperplate_la-heapobj-pshared.lo: heapobj-pshared.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcopperplate_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libcopperplate_la-heapobj-pshared.lo -MD -MP -MF $(DEPDIR)/libcopperplate_la-heapobj-pshared.Tpo -c -o libcopperplate_la-heapobj-pshared.lo `test -f 'heapobj-pshared.c' || echo '$(srcdir)/'`heapobj-pshared.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcopperplate_la-heapobj-pshared.Tpo $(DEPDIR)/libcopperplate_la-heapobj-pshared.Plo diff --git a/lib/copperplate/notifier.c b/lib/copperplate/notifier.c deleted file mode 100644 index 0f02059..0000000 --- a/lib/copperplate/notifier.c +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright (C) 2008 Philippe Gerum <r...@xenomai.org>. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#include <signal.h> -#include <memory.h> -#include <errno.h> -#include "copperplate/notifier.h" -#include "boilerplate/signal.h" -#include "internal.h" - -static void suspend_sighandler(int sig) -{ - notifier_wait(); -} - -static void resume_sighandler(int sig) -{ - /* nop */ -} - -int notifier_init(struct notifier *nf, pid_t pid) -{ - sigset_t set; - - nf->owner = pid; - sigemptyset(&set); - sigaddset(&set, SIGRESM); - pthread_sigmask(SIG_BLOCK, &set, NULL); - - return 0; -} - -void notifier_signal(struct notifier *nf) -{ - copperplate_kill_tid(nf->owner, SIGSUSP); -} - -void notifier_release(struct notifier *nf) -{ - copperplate_kill_tid(nf->owner, SIGRESM); -} - -void notifier_wait(void) -{ - sigset_t set; - - /* - * A suspended thread is supposed to do nothing but wait for - * the wake up signal, so we may happily block all signals but - * SIGRESM. Note that SIGRRB won't be accumulated during the - * sleep time anyhow, as the round-robin timer is based on - * CLOCK_THREAD_CPUTIME_ID, and we'll obviously don't consume - * any CPU time while blocked. - */ - sigfillset(&set); - sigdelset(&set, SIGRESM); - sigsuspend(&set); -} - -void notifier_disable(struct notifier *nf) -{ - /* Unblock any ongoing wait. */ - copperplate_kill_tid(nf->owner, SIGRESM); -} - -void notifier_pkg_init(void) -{ - struct sigaction sa; - /* - * We have two basic requirements for the notification - * scheme implementing the suspend/resume mechanism: - * - * - we have to rely on Linux signals for notification, which - * guarantees that the target thread will receive the suspend - * request asap, regardless of what it was doing when notified - * (syscall wait, pure runtime etc.). - * - * - we must process the suspension signal on behalf of the - * target thread, as we want that thread to block upon - * receipt. - */ - memset(&sa, 0, sizeof(sa)); - sa.sa_flags = SA_RESTART; - sa.sa_handler = suspend_sighandler; - sigaction(SIGSUSP, &sa, NULL); - sa.sa_handler = resume_sighandler; - sigaction(SIGRESM, &sa, NULL); -} diff --git a/lib/copperplate/threadobj.c b/lib/copperplate/threadobj.c index 7a7f970..042828c 100644 --- a/lib/copperplate/threadobj.c +++ b/lib/copperplate/threadobj.c @@ -377,7 +377,6 @@ int threadobj_stat(struct threadobj *thobj, struct threadobj_stat *p) /* thobj-> #else /* CONFIG_XENO_MERCURY */ #include <sys/prctl.h> -#include "copperplate/notifier.h" static int threadobj_lock_prio; @@ -404,6 +403,33 @@ static void roundrobin_handler(int sig) sched_yield(); } +static void sleep_suspended(void) +{ + sigset_t set; + + /* + * A suspended thread is supposed to do nothing but wait for + * the wake up signal, so we may happily block all signals but + * SIGRESM. Note that SIGRRB won't be accumulated during the + * sleep time anyhow, as the round-robin timer is based on + * CLOCK_THREAD_CPUTIME_ID, and we'll obviously don't consume + * any CPU time while blocked. + */ + sigfillset(&set); + sigdelset(&set, SIGRESM); + sigsuspend(&set); +} + +static void suspend_sighandler(int sig) +{ + sleep_suspended(); +} + +static void resume_sighandler(int sig) +{ + /* nop */ +} + static inline void pkg_init_corespec(void) { struct sigaction sa; @@ -422,8 +448,10 @@ static inline void pkg_init_corespec(void) sigaction(SIGRELS, &sa, NULL); sa.sa_handler = roundrobin_handler; sigaction(SIGRRB, &sa, NULL); - - notifier_pkg_init(); + sa.sa_handler = suspend_sighandler; + sigaction(SIGSUSP, &sa, NULL); + sa.sa_handler = resume_sighandler; + sigaction(SIGRESM, &sa, NULL); } static inline void threadobj_init_corespec(struct threadobj *thobj) @@ -449,12 +477,27 @@ static inline void threadobj_uninit_corespec(struct threadobj *thobj) static inline int threadobj_setup_corespec(struct threadobj *thobj) { struct sigevent sev; + sigset_t set; int ret; prctl(PR_SET_NAME, (unsigned long)thobj->name, 0, 0, 0); - ret = notifier_init(&thobj->core.notifier, threadobj_get_pid(thobj)); - if (ret) - return __bt(ret); + + /* + * Do the per-thread setup for supporting the suspend/resume + * actions over Mercury. We have two basic requirements for + * this mechanism: + * + * - suspended requests must be handled asap, regardless of + * what the target thread is doing when notified (syscall + * wait, pure runtime etc.), hence the use of signals. + * + * - we must process the suspension signal on behalf of the + * target thread, as we want that thread to block upon + * receipt. + */ + sigemptyset(&set); + sigaddset(&set, SIGRESM); + pthread_sigmask(SIG_BLOCK, &set, NULL); thobj->core.period = 0; @@ -467,18 +510,14 @@ static inline int threadobj_setup_corespec(struct threadobj *thobj) sev.sigev_notify_thread_id = threadobj_get_pid(thobj); ret = timer_create(CLOCK_THREAD_CPUTIME_ID, &sev, &thobj->core.rr_timer); - if (ret) { - ret = __bt(-errno); - notifier_destroy(&thobj->core.notifier); - } + if (ret) + return __bt(-errno); return 0; } static inline void threadobj_cleanup_corespec(struct threadobj *thobj) { - notifier_destroy(&thobj->core.notifier); - if (thobj->core.rr_timer) timer_delete(thobj->core.rr_timer); } @@ -492,11 +531,15 @@ static inline void threadobj_cancel_1_corespec(struct threadobj *thobj) /* thobj /* * If the target thread we are about to cancel gets suspended * while it is currently warming up, we have to unblock it - * from notifier_wait(), so that we don't get stuck in + * from sleep_suspended(), so that we don't get stuck in * cancel_sync(), waiting for a warmed up state which will * never come. + * + * Just send it SIGRESM unconditionally, this will either + * unblock it if the thread waits in sleep_suspended(), or + * lead to a nop since that signal is blocked otherwise. */ - notifier_disable(&thobj->core.notifier); + copperplate_kill_tid(thobj->pid, SIGRESM); } static inline void threadobj_cancel_2_corespec(struct threadobj *thobj) /* thobj->lock held */ @@ -505,18 +548,22 @@ static inline void threadobj_cancel_2_corespec(struct threadobj *thobj) /* thobj int threadobj_suspend(struct threadobj *thobj) /* thobj->lock held */ { - struct notifier *nf = &thobj->core.notifier; - __threadobj_check_locked(thobj); if (thobj == threadobj_current()) { thobj->status |= __THREAD_S_SUSPENDED; threadobj_unlock(thobj); - notifier_wait(); + sleep_suspended(); threadobj_lock(thobj); } else if ((thobj->status & __THREAD_S_SUSPENDED) == 0) { + /* + * We prevent suspension requests from cumulating, so + * that we always have a flat, consistent sequence of + * alternate suspend/resume events. It's up to the + * client code to handle nested requests if need be. + */ thobj->status |= __THREAD_S_SUSPENDED; - notifier_signal(nf); + copperplate_kill_tid(thobj->pid, SIGSUSP); } return 0; @@ -529,7 +576,11 @@ int threadobj_resume(struct threadobj *thobj) /* thobj->lock held */ if (thobj != threadobj_current() && (thobj->status & __THREAD_S_SUSPENDED) != 0) { thobj->status &= ~__THREAD_S_SUSPENDED; - notifier_release(&thobj->core.notifier); + /* + * We prevent resumption requests from cumulating. See + * threadobj_suspend(). + */ + copperplate_kill_tid(thobj->pid, SIGRESM); } return 0; _______________________________________________ Xenomai-git mailing list Xenomai-git@xenomai.org http://www.xenomai.org/mailman/listinfo/xenomai-git