Module: xenomai-3
Branch: next
Commit: 6ce16cb01d0acba75285f0aae0c3e863bf4b8c0b
URL:    
http://git.xenomai.org/?p=xenomai-3.git;a=commit;h=6ce16cb01d0acba75285f0aae0c3e863bf4b8c0b

Author: Philippe Gerum <r...@xenomai.org>
Date:   Fri May  8 16:27:43 2015 +0200

lib: move early setup code to the boilerplate layer

This is a preparation step to unify the Xenomai setup interface for
both pure Cobalt/POSIX and Copperplate-based applications.

The goal is to expose a common set of basic command line switches
which apply to all application programs regardless of the API being
used (e.g. --dump-config), and a single setup call for bootstrapping
the core libraries in sequence.

---

 include/boilerplate/Makefile.am            |    1 +
 include/boilerplate/setup.h                |   72 ++++
 include/copperplate/init.h                 |   21 +-
 lib/alchemy/init.c                         |    7 +-
 lib/alchemy/init.h                         |    2 -
 lib/boilerplate/Makefile.am                |   32 +-
 lib/boilerplate/setup.c                    |  527 ++++++++++++++++++++++++
 lib/{copperplate => boilerplate}/version.c |    0
 lib/copperplate/Makefile.am                |   29 +-
 lib/copperplate/heapobj-pshared.c          |    8 +-
 lib/copperplate/heapobj-tlsf.c             |    6 +-
 lib/copperplate/init.c                     |  607 +++-------------------------
 lib/copperplate/internal.h                 |   19 +-
 lib/copperplate/main.c                     |    2 +-
 lib/copperplate/regd/fs-common.c           |    4 +-
 lib/copperplate/regd/regd.c                |   10 +-
 lib/copperplate/registry.c                 |   12 +-
 lib/copperplate/traceobj.c                 |    2 +-
 lib/psos/init.c                            |   23 +-
 lib/psos/init.h                            |    2 -
 lib/smokey/init.c                          |   22 +-
 lib/trank/init.c                           |    2 +
 lib/trank/init.h                           |    2 -
 lib/vxworks/init.c                         |    7 +-
 lib/vxworks/init.h                         |    2 -
 25 files changed, 745 insertions(+), 676 deletions(-)

diff --git a/include/boilerplate/Makefile.am b/include/boilerplate/Makefile.am
index 1957080..b611364 100644
--- a/include/boilerplate/Makefile.am
+++ b/include/boilerplate/Makefile.am
@@ -12,5 +12,6 @@ includesub_HEADERS =  \
        obstack.h       \
        private-list.h  \
        scope.h         \
+       setup.h         \
        shared-list.h   \
        time.h
diff --git a/include/boilerplate/setup.h b/include/boilerplate/setup.h
new file mode 100644
index 0000000..73452d1
--- /dev/null
+++ b/include/boilerplate/setup.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2015 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 _BOILERPLATE_SETUP_H
+#define _BOILERPLATE_SETUP_H
+
+#include <boilerplate/list.h>
+#include <sched.h>
+
+struct base_setup_data {
+       cpu_set_t cpu_affinity;
+       int no_mlock;
+       int no_sanity;
+       int silent_mode;
+       const char *arg0;
+};
+
+struct option;
+
+struct skin_descriptor {
+       const char *name;
+       int (*init)(void);
+       const struct option *options;
+       int (*parse_option)(int optnum, const char *optarg);
+       void (*help)(void);
+       struct {
+               int opt_start;
+               int opt_end;
+               struct pvholder next;
+       } __reserved;
+};
+
+#define DECLARE_SKIN(__name, __priority)               \
+static __attribute__ ((constructor(__priority)))       \
+void __declare_ ## __name(void)                                \
+{                                                      \
+       __register_skin(&(__name));                     \
+}
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void __register_skin(struct skin_descriptor *p);
+       
+void xenomai_init(int *argcp, char *const **argvp);
+
+extern pid_t __node_id;
+
+extern struct base_setup_data __base_setup_data;
+
+extern const char *xenomai_version_string;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !_BOILERPLATE_SETUP_H */
diff --git a/include/copperplate/init.h b/include/copperplate/init.h
index 0f72ffc..66b471c 100644
--- a/include/copperplate/init.h
+++ b/include/copperplate/init.h
@@ -22,23 +22,10 @@
 #include <stdarg.h>
 #include <sched.h>
 #include <boilerplate/trace.h>
-#include <boilerplate/list.h>
 #include <boilerplate/ancillaries.h>
+#include <boilerplate/setup.h>
 
-struct option;
-
-struct copperskin {
-       const char *name;
-       int (*init)(void);
-       const struct option *options;
-       int (*parse_option)(int optnum, const char *optarg);
-       void (*help)(void);
-       struct {
-               int opt_start;
-               int opt_end;
-               struct pvholder next;
-       } __reserved; /* Don't init, reserved to Copperplate. */
-};
+#define __LIBCOPPERPLATE_CTOR_PRIO  250
 
 #ifdef __cplusplus
 extern "C" {
@@ -46,10 +33,6 @@ extern "C" {
 
 int copperplate_main(int argc, char *const argv[]);
 
-void copperplate_init(int *argcp, char *const **argvp);
-
-void copperplate_register_skin(struct copperskin *p);
-
 #ifdef __cplusplus
 }
 #endif
diff --git a/lib/alchemy/init.c b/lib/alchemy/init.c
index 14ec212..65ede3c 100644
--- a/lib/alchemy/init.c
+++ b/lib/alchemy/init.c
@@ -132,7 +132,7 @@ static int alchemy_init(void)
        return 0;
 }
 
-static struct copperskin alchemy_skin = {
+static struct skin_descriptor alchemy_skin = {
        .name = "alchemy",
        .init = alchemy_init,
        .options = alchemy_options,
@@ -140,7 +140,4 @@ static struct copperskin alchemy_skin = {
        .help = alchemy_help,
 };
 
-static __libalchemy_ctor void register_alchemy(void)
-{
-       copperplate_register_skin(&alchemy_skin);
-}
+DECLARE_SKIN(alchemy_skin, __LIBALCHEMY_CTOR_PRIO);
diff --git a/lib/alchemy/init.h b/lib/alchemy/init.h
index ff95bb3..d3cf5f3 100644
--- a/lib/alchemy/init.h
+++ b/lib/alchemy/init.h
@@ -20,6 +20,4 @@
 
 #define __LIBALCHEMY_CTOR_PRIO  300
 
-#define __libalchemy_ctor  __attribute__ 
((constructor(__LIBALCHEMY_CTOR_PRIO)))
-
 #endif /* _ALCHEMY_INIT_H */
diff --git a/lib/boilerplate/Makefile.am b/lib/boilerplate/Makefile.am
index 9314d25..c8496c9 100644
--- a/lib/boilerplate/Makefile.am
+++ b/lib/boilerplate/Makefile.am
@@ -1,18 +1,41 @@
 
-noinst_LTLIBRARIES = libboilerplate.la
-
+noinst_LTLIBRARIES = libversion.la libiniparser.la libboilerplate.la
 libboilerplate_la_LDFLAGS = @XENO_LIB_LDFLAGS@ -lpthread
+libboilerplate_la_LIBADD = libversion.la libiniparser.la
 
 libboilerplate_la_SOURCES =    \
        ancillaries.c           \
        hash.c                  \
        obstack.c               \
+       setup.c                 \
        time.c
 
 if XENO_DEBUG
 libboilerplate_la_SOURCES += debug.c
 endif
 
+libversion_la_CFLAGS = @XENO_USER_CFLAGS@
+libversion_la_SOURCES = version.c
+version.c: git-stamp.h
+
+git-stamp.h: git-stamp
+       @if test -r $(top_srcdir)/.git; then                                    
        \
+         stamp=`git --git-dir=$(top_srcdir)/.git rev-list --abbrev-commit -1 
HEAD`;    \
+         if test \! -s $@ || grep -wvq $$stamp $@; then                        
        \
+               date=`git --git-dir=$(top_srcdir)/.git log -1 $$stamp 
--pretty=format:%ci`;     \
+               echo "#define GIT_STAMP \"#$$stamp ($$date)\"" > $@;            
        \
+         fi;                                                                   
        \
+       elif test \! -r $@ -o -s $@; then                                       
        \
+           rm -f $@ && touch $@;                                               
        \
+       fi; true
+
+sbin_PROGRAMS = version
+version_CFLAGS = @XENO_USER_CFLAGS@ -I$(top_srcdir)/include -D__PROGRAM__
+version_SOURCES = version.c
+
+clean-local:
+       $(RM) git-stamp.h
+
 nodist_libboilerplate_la_SOURCES = config-dump.h
 BUILT_SOURCES = config-dump.h
 CLEANFILES = config-dump.h
@@ -31,9 +54,6 @@ libboilerplate_la_CPPFLAGS =                          \
        -I$(top_srcdir)                                 \
        -I$(top_srcdir)/include
 
-libboilerplate_la_LIBADD = libiniparser.la
-noinst_LTLIBRARIES += libiniparser.la
-
 libiniparser_la_SOURCES        =       \
        iniparser/dictionary.c  \
        iniparser/dictionary.h  \
@@ -71,3 +91,5 @@ sparse:
        @for i in $(libboilerplate_la_SOURCES) $(libtlsf_la_SOURCES) 
$(libiniparser_la_SOURCES; do \
                $(SPARSE) $(CHECKFLAGS) $(srcdir)/$$i; \
        done
+
+.PHONY: git-stamp
diff --git a/lib/boilerplate/setup.c b/lib/boilerplate/setup.c
new file mode 100644
index 0000000..1ea950a
--- /dev/null
+++ b/lib/boilerplate/setup.c
@@ -0,0 +1,527 @@
+/*
+ * Copyright (C) 2015 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 <sys/types.h>
+#include <sys/mman.h>
+#include <sched.h>
+#include <getopt.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <memory.h>
+#include <malloc.h>
+#include <assert.h>
+#include <xeno_config.h>
+#include <boilerplate/setup.h>
+#include <boilerplate/lock.h>
+#include <boilerplate/debug.h>
+#include <boilerplate/ancillaries.h>
+
+struct base_setup_data __base_setup_data = {
+       .no_mlock = 0,
+       .no_sanity = !CONFIG_XENO_SANITY,
+       .silent_mode = 0,
+       .arg0 = NULL,
+};
+
+pid_t __node_id;
+
+static DEFINE_PRIVATE_LIST(skins);
+
+static const struct option base_options[] = {
+       {
+#define help_opt       0
+               .name = "help",
+       },
+       {
+#define no_mlock_opt   1
+               .name = "no-mlock",
+               .flag = &__base_setup_data.no_mlock,
+               .val = 1
+       },
+       {
+#define affinity_opt   2
+               .name = "cpu-affinity",
+               .has_arg = 1,
+       },
+       {
+#define silent_opt     3
+               .name = "silent",
+               .flag = &__base_setup_data.silent_mode,
+               .val = 1
+       },
+       {
+#define version_opt    4
+               .name = "version",
+       },
+       {
+#define dumpconfig_opt 5
+               .name = "dump-config",
+       },
+       {
+#define no_sanity_opt  6
+               .name = "no-sanity",
+               .flag = &__base_setup_data.no_sanity,
+               .val = 1
+       },
+       {
+#define sanity_opt     7
+               .name = "sanity",
+               .flag = &__base_setup_data.no_sanity,
+       },
+       {
+               /* sentinel */
+       }
+};
+
+static inline void print_version(void)
+{
+       fprintf(stderr, "%s\n", xenomai_version_string);
+}
+
+static inline void dump_configuration(void)
+{
+       int n;
+
+       for (n = 0; config_strings[n]; n++)
+               puts(config_strings[n]);
+}
+
+static int collect_cpu_affinity(const char *cpu_list)
+{
+       char *s = strdup(cpu_list), *p, *n;
+       int ret, cpu;
+
+       n = s;
+       while ((p = strtok(n, ",")) != NULL) {
+               cpu = atoi(p);
+               if (cpu >= CPU_SETSIZE) {
+                       free(s);
+                       warning("invalid CPU number '%d'", cpu);
+                       return -EINVAL;
+               }
+               CPU_SET(cpu, &__base_setup_data.cpu_affinity);
+               n = NULL;
+       }
+
+       free(s);
+
+       /*
+        * Check we may use this affinity, at least one CPU from the
+        * given set should be available for running threads. Since
+        * CPU affinity will be inherited by children threads, we only
+        * have to set it here.
+        *
+        * NOTE: we don't clear __base_setup_data.cpu_affinity on
+        * entry to this routine to allow cumulative --cpu-affinity
+        * options to appear in the command line arguments.
+        */
+       ret = sched_setaffinity(0, sizeof(__base_setup_data.cpu_affinity),
+                               &__base_setup_data.cpu_affinity);
+       if (ret) {
+               warning("invalid CPU in affinity list '%s'", cpu_list);
+               return -errno;
+       }
+
+       return 0;
+}
+
+static inline char **prep_args(int argc, char *const argv[], int *largcp)
+{
+       int in, out, n, maybe_arg, lim;
+       char **uargv, *p;
+
+       uargv = malloc(argc * sizeof(char *));
+       if (uargv == NULL)
+               return NULL;
+
+       for (n = 0; n < argc; n++) {
+               uargv[n] = strdup(argv[n]);
+               if (uargv[n] == NULL)
+                       return NULL;
+       }
+
+       lim = argc;
+       in = maybe_arg = 0;
+       while (in < lim) {
+               if ((uargv[in][0] == '-' && uargv[in][1] != '-') ||
+                   (maybe_arg && uargv[in][0] != '-')) {
+                       p = strdup(uargv[in]);
+                       for (n = in, out = in + 1; out < argc; out++, n++) {
+                               free(uargv[n]);
+                               uargv[n] = strdup(uargv[out]);
+                       }
+                       free(uargv[argc - 1]);
+                       uargv[argc - 1] = p;
+                       if (*p == '-')
+                               maybe_arg = 1;
+                       lim--;
+               } else {
+                       in++;
+                       maybe_arg = 0;
+               }
+       }
+
+       *largcp = lim;
+
+       return uargv;
+}
+
+static inline void pack_args(int *argcp, int *largcp, char **argv)
+{
+       int in, out;
+
+       for (in = out = 0; in < *argcp; in++) {
+               if (*argv[in])
+                       argv[out++] = argv[in];
+               else {
+                       free(argv[in]);
+                       (*largcp)--;
+               }
+       }
+
+       *argcp = out;
+}
+
+static struct option *build_option_array(int *base_opt_startp)
+{
+       struct skin_descriptor *skin;
+       struct option *options, *q;
+       const struct option *p;
+       int nopts;
+
+       nopts = sizeof(base_options) / sizeof(base_options[0]);
+
+       if (!pvlist_empty(&skins)) {
+               pvlist_for_each_entry(skin, &skins, __reserved.next) {
+                       p = skin->options;
+                       if (p) {
+                               while (p->name) {
+                                       nopts++;
+                                       p++;
+                               }
+                       }
+               }
+       }
+
+       options = malloc(sizeof(*options) * nopts);
+       if (options == NULL)
+               return NULL;
+
+       q = options;
+
+       if (!pvlist_empty(&skins)) {
+               pvlist_for_each_entry(skin, &skins, __reserved.next) {
+                       p = skin->options;
+                       if (p) {
+                               skin->__reserved.opt_start = q - options;
+                               while (p->name)
+                                       memcpy(q++, p++, sizeof(*q));
+                       }
+                       skin->__reserved.opt_end = q - options;
+               }
+       }
+
+       *base_opt_startp = q - options;
+       memcpy(q, base_options, sizeof(base_options));
+
+       return options;
+}
+
+static void usage(void)
+{
+       struct skin_descriptor *skin;
+
+       print_version();
+        fprintf(stderr, "usage: program <options>, where options may be:\n");
+        fprintf(stderr, "--no-mlock                       do not lock memory 
at init (Mercury only)\n");
+        fprintf(stderr, "--cpu-affinity=<cpu[,cpu]...>    set CPU affinity of 
threads\n");
+        fprintf(stderr, "--[no-]sanity                    disable/enable 
sanity checks\n");
+        fprintf(stderr, "--silent                         tame down 
verbosity\n");
+        fprintf(stderr, "--version                        get version 
information\n");
+        fprintf(stderr, "--dump-config                    dump configuration 
settings\n");
+
+       if (pvlist_empty(&skins))
+               return;
+
+       pvlist_for_each_entry(skin, &skins, __reserved.next) {
+               if (skin->help)
+                       skin->help();
+       }
+}
+
+static int parse_base_options(int *argcp, char *const **argvp,
+                             int *largcp, char ***uargvp,
+                             const struct option *options,
+                             int base_opt_start)
+{
+       int c, lindex, ret, n;
+       char **uargv;
+
+       /*
+        * Prepare a user argument vector we can modify, copying the
+        * one we have been given by the application code in
+        * xenomai_init(). This vector will be expunged from Xenomai
+        * proper options as we discover them.
+        */
+       uargv = prep_args(*argcp, *argvp, largcp);
+       if (uargv == NULL)
+               return -ENOMEM;
+
+       __base_setup_data.arg0 = uargv[0];
+       *uargvp = uargv;
+       opterr = 0;
+
+       /*
+        * NOTE: since we pack the argument vector on the fly while
+        * processing the options, optarg should be considered as
+        * volatile by skin option handlers; i.e. strdup() is required
+        * if the value has to be retained. Values from the user
+        * vector returned by xenomai_init() live in permanent memory
+        * though.
+        */
+
+       for (;;) {
+               lindex = -1;
+               c = getopt_long(*largcp, uargv, "", options, &lindex);
+               if (c == EOF)
+                       break;
+               if (lindex == -1)
+                       continue;
+
+               switch (lindex - base_opt_start) {
+               case affinity_opt:
+                       ret = collect_cpu_affinity(optarg);
+                       if (ret)
+                               return ret;
+                       break;
+               case no_mlock_opt:
+               case no_sanity_opt:
+               case sanity_opt:
+               case silent_opt:
+                       break;
+               case version_opt:
+                       print_version();
+                       exit(0);
+               case dumpconfig_opt:
+                       dump_configuration();
+                       exit(0);
+               case help_opt:
+                       usage();
+                       exit(0);
+               default:
+                       /* Skin option, don't process yet. */
+                       continue;
+               }
+
+               /*
+                * Clear the first byte of the base option we found
+                * (including any companion argument), pack_args()
+                * will expunge all options we have already handled.
+                *
+                * NOTE: this code relies on the fact that only long
+                * options with double-dash markers can be parsed here
+                * after prep_args() did its job (we do not support
+                * -foo as a long option). This is aimed at reserving
+                * use of short options to the application layer,
+                * sharing only the long option namespace with the
+                * Xenomai core libs.
+                */
+               n = optind - 1;
+               if (uargv[n][0] != '-' || uargv[n][1] != '-')
+                       /* Clear the separate argument value. */
+                       uargv[n--][0] = '\0';
+               uargv[n][0] = '\0'; /* Clear the option switch. */
+       }
+
+       pack_args(argcp, largcp, uargv);
+
+       optind = 0;
+
+       return 0;
+}
+
+static int parse_skin_options(int *argcp, int largc, char **uargv,
+                             const struct option *options)
+{
+       struct skin_descriptor *skin;
+       int lindex, n, c, ret;
+
+       for (;;) {
+               lindex = -1;
+               c = getopt_long(largc, uargv, "", options, &lindex);
+               if (c == EOF)
+                       break;
+               if (lindex == -1)
+                       continue; /* Not handled here. */
+               pvlist_for_each_entry(skin, &skins, __reserved.next) {
+                       if (skin->parse_option == NULL)
+                               continue;
+                       if (lindex < skin->__reserved.opt_start ||
+                           lindex >= skin->__reserved.opt_end)
+                               continue;
+                       lindex -= skin->__reserved.opt_start;
+                       ret = skin->parse_option(lindex, optarg);
+                       if (ret == 0)
+                               break;
+                       return ret;
+               }
+               n = optind - 1;
+               if (uargv[n][0] != '-' || uargv[n][1] != '-')
+                       /* Clear the separate argument value. */
+                       uargv[n--][0] = '\0';
+               uargv[n][0] = '\0'; /* Clear the option switch. */
+       }
+
+       pack_args(argcp, &largc, uargv);
+
+       optind = 0;
+
+       return 0;
+}
+
+void xenomai_init(int *argcp, char *const **argvp)
+{
+       int ret, largc, base_opt_start;
+       struct skin_descriptor *skin;
+       struct option *options;
+       static int init_done;
+       char **uargv = NULL;
+       struct service svc;
+
+       if (init_done) {
+               warning("duplicate call to %s() ignored", __func__);
+               warning("(xeno-config --no-auto-init disables implicit call)");
+               return;
+       }
+
+       boilerplate_init();
+
+       /* Our node id. is the tid of the main thread. */
+       __node_id = get_thread_pid();
+
+       /* No ifs, no buts: we must be called over the main thread. */
+       assert(getpid() == __node_id);
+
+       /* Define default CPU affinity, i.e. no particular affinity. */
+       CPU_ZERO(&__base_setup_data.cpu_affinity);
+
+       /*
+        * Build the global option array, merging the base and
+        * per-skin option sets.
+        */
+       options = build_option_array(&base_opt_start);
+       if (options == NULL) {
+               ret = -ENOMEM;
+               goto fail;
+       }
+
+       /*
+        * Parse the base options first, to bootstrap the core with
+        * the right config values.
+        */
+       ret = parse_base_options(argcp, argvp, &largc, &uargv,
+                                options, base_opt_start);
+       if (ret)
+               goto fail;
+
+#ifndef CONFIG_SMP
+       if (__base_setup_data.no_sanity == 0) {
+               ret = get_static_cpu_count();
+               if (ret > 0)
+                       early_panic("running non-SMP libraries on SMP kernel?\n"
+           "              build with --enable-smp or disable check with 
--no-sanity");
+       }
+#endif
+
+       ret = debug_init();
+       if (ret) {
+               warning("failed to initialize debugging features");
+               goto fail;
+       }
+
+#ifdef CONFIG_XENO_MERCURY
+       if (__base_setup_data.no_mlock == 0) {
+               ret = mlockall(MCL_CURRENT | MCL_FUTURE);
+               if (ret) {
+                       ret = -errno;
+                       warning("failed to lock memory");
+                       goto fail;
+               }
+       }
+#endif
+
+       /*
+        * Now that we have bootstrapped the core, we may call the
+        * skin handlers for parsing their own options, which in turn
+        * may create system objects on the fly.
+        */
+       if (!pvlist_empty(&skins)) {
+               ret = parse_skin_options(argcp, largc, uargv, options);
+               if (ret)
+                       goto fail;
+
+               CANCEL_DEFER(svc);
+
+               pvlist_for_each_entry(skin, &skins, __reserved.next) {
+                       ret = skin->init();
+                       if (ret)
+                               break;
+               }
+
+               CANCEL_RESTORE(svc);
+
+               if (ret) {
+                       warning("skin %s won't initialize", skin->name);
+                       goto fail;
+               }
+       }
+
+       free(options);
+
+#ifdef CONFIG_XENO_DEBUG
+       if (__base_setup_data.silent_mode == 0) {
+               warning("Xenomai compiled with %s debug enabled,\n"
+                       "                              "
+                       "%shigh latencies expected [--enable-debug=%s]",
+#ifdef CONFIG_XENO_DEBUG_FULL
+                       "full", "very ", "full"
+#else
+                       "partial", "", "partial"
+#endif
+                       );
+       }
+#endif
+
+       /*
+        * The final user arg vector only contains options we could
+        * not handle. The caller should be able to process them, or
+        * bail out.
+        */
+       *argvp = uargv;
+       init_done = 1;
+
+       return;
+fail:
+       early_panic("initialization failed, %s", symerror(ret));
+}
+
+void __register_skin(struct skin_descriptor *p)
+{
+       pvlist_append(&p->__reserved.next, &skins);
+}
diff --git a/lib/copperplate/version.c b/lib/boilerplate/version.c
similarity index 100%
rename from lib/copperplate/version.c
rename to lib/boilerplate/version.c
diff --git a/lib/copperplate/Makefile.am b/lib/copperplate/Makefile.am
index 2c08846..21ff51b 100644
--- a/lib/copperplate/Makefile.am
+++ b/lib/copperplate/Makefile.am
@@ -2,6 +2,8 @@
 lib_LTLIBRARIES = libcopperplate.la
 
 libcopperplate_la_LDFLAGS = @XENO_LIB_LDFLAGS@ -lpthread -lrt -version-info 
0:0:0
+libcopperplate_la_LIBADD =
+noinst_LTLIBRARIES =
 
 libcopperplate_la_SOURCES =    \
        clockobj.c      \
@@ -24,31 +26,6 @@ libcopperplate_la_CPPFLAGS =         \
        -I$(top_srcdir)/include         \
        -I$(top_srcdir)/lib
 
-noinst_LTLIBRARIES = libversion.la
-libversion_la_CFLAGS = @XENO_USER_CFLAGS@
-libversion_la_SOURCES = version.c
-version.c: git-stamp.h
-
-git-stamp.h: git-stamp
-       @if test -r $(top_srcdir)/.git; then                                    
        \
-         stamp=`git --git-dir=$(top_srcdir)/.git rev-list --abbrev-commit -1 
HEAD`;    \
-         if test \! -s $@ || grep -wvq $$stamp $@; then                        
        \
-               date=`git --git-dir=$(top_srcdir)/.git log -1 $$stamp 
--pretty=format:%ci`;     \
-               echo "#define GIT_STAMP \"#$$stamp ($$date)\"" > $@;            
        \
-         fi;                                                                   
        \
-       elif test \! -r $@ -o -s $@; then                                       
        \
-           rm -f $@ && touch $@;                                               
        \
-       fi; true
-
-sbin_PROGRAMS = version
-version_CFLAGS = @XENO_USER_CFLAGS@ -I$(top_srcdir)/include -D__PROGRAM__
-version_SOURCES = version.c
-
-clean-local:
-       $(RM) git-stamp.h
-
-libcopperplate_la_LIBADD = libversion.la
-
 if XENO_MERCURY
 libcopperplate_la_LIBADD += ../boilerplate/libboilerplate.la
 endif
@@ -89,5 +66,3 @@ sparse:
        @for i in $(libcopperplate_la_SOURCES) ; do \
                $(SPARSE) $(CHECKFLAGS) $(srcdir)/$$i; \
        done
-
-.PHONY: git-stamp
diff --git a/lib/copperplate/heapobj-pshared.c 
b/lib/copperplate/heapobj-pshared.c
index 88c0e21..f810ec0 100644
--- a/lib/copperplate/heapobj-pshared.c
+++ b/lib/copperplate/heapobj-pshared.c
@@ -585,8 +585,8 @@ out:
 
 static int create_main_heap(pid_t *cnode_r)
 {
-       const char *session = __node_info.session_label;
-       size_t size = __node_info.mem_pool;
+       const char *session = __copperplate_setup_data.session_label;
+       size_t size = __copperplate_setup_data.mem_pool;
        struct heapobj *hobj = &main_pool;
        struct session_heap *m_heap;
        struct stat sbuf;
@@ -806,7 +806,7 @@ int pshared_check(void *__heap, void *__addr)
 
 int heapobj_init(struct heapobj *hobj, const char *name, size_t size)
 {
-       const char *session = __node_info.session_label;
+       const char *session = __copperplate_setup_data.session_label;
        struct shared_heap *heap;
        size_t len;
 
@@ -953,7 +953,7 @@ int heapobj_pkg_init_shared(void)
        ret = create_main_heap(&cnode);
        if (ret == -EEXIST)
                warning("session %s is still active (pid %d)\n",
-                       __node_info.session_label, cnode);
+                       __copperplate_setup_data.session_label, cnode);
 
        return __bt(ret);
 }
diff --git a/lib/copperplate/heapobj-tlsf.c b/lib/copperplate/heapobj-tlsf.c
index 8a0691e..e5d30a3 100644
--- a/lib/copperplate/heapobj-tlsf.c
+++ b/lib/copperplate/heapobj-tlsf.c
@@ -89,13 +89,13 @@ int heapobj_pkg_init_private(void)
         * per-block overhead for an undefined number of individual
         * allocation requests. Ugly.
         */
-       mem = tlsf_malloc(__node_info.mem_pool);
-       size = init_memory_pool(__node_info.mem_pool, mem);
+       mem = tlsf_malloc(__copperplate_setup_data.mem_pool);
+       size = init_memory_pool(__copperplate_setup_data.mem_pool, mem);
        if (size == (size_t)-1)
                panic("cannot initialize TLSF memory manager");
 
        destroy_memory_pool(mem);
-       tlsf_pool_overhead = __node_info.mem_pool - size;
+       tlsf_pool_overhead = __copperplate_setup_data.mem_pool - size;
        tlsf_pool_overhead = (tlsf_pool_overhead + 1024) & ~15;
        tlsf_free(mem);
 
diff --git a/lib/copperplate/init.c b/lib/copperplate/init.c
index ebfa81f..fccb319 100644
--- a/lib/copperplate/init.c
+++ b/lib/copperplate/init.c
@@ -17,465 +17,64 @@
  */
 
 #include <sys/types.h>
-#include <sys/mman.h>
-#include <pthread.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
 #include <string.h>
-#include <memory.h>
-#include <malloc.h>
-#include <assert.h>
 #include <pwd.h>
-#include <signal.h>
 #include <errno.h>
 #include <getopt.h>
-#include <sched.h>
 #include "copperplate/threadobj.h"
 #include "copperplate/heapobj.h"
 #include "copperplate/clockobj.h"
 #include "copperplate/registry.h"
 #include "copperplate/timerobj.h"
-#include "copperplate/debug.h"
 #include "internal.h"
 
-struct coppernode __node_info = {
+struct copperplate_setup_data __copperplate_setup_data = {
        .mem_pool = 1024 * 1024, /* Default, 1Mb. */
-       .no_mlock = 0,
        .no_registry = 0,
-       .no_sanity = !CONFIG_XENO_SANITY,
-       .silent_mode = 0,
        .registry_root = DEFAULT_REGISTRY_ROOT,
        .session_label = NULL,
        .session_root = NULL,
 };
 
-pid_t __node_id;
-
 #ifdef CONFIG_XENO_COBALT
 int __cobalt_print_bufsz = 32 * 1024;
 #endif
 
-static DEFINE_PRIVATE_LIST(skins);
-
-static const struct option base_options[] = {
-       {
-#define help_opt       0
-               .name = "help",
-               .has_arg = 0,
-               .flag = NULL,
-               .val = 0
-       },
+static const struct option copperplate_options[] = {
        {
-#define mempool_opt    1
+#define mempool_opt    0
                .name = "mem-pool-size",
                .has_arg = 1,
-               .flag = NULL,
-               .val = 0
        },
        {
-#define no_mlock_opt   2
-               .name = "no-mlock",
-               .has_arg = 0,
-               .flag = &__node_info.no_mlock,
-               .val = 1
-       },
-       {
-#define regroot_opt    3
+#define regroot_opt    1
                .name = "registry-root",
                .has_arg = 1,
-               .flag = NULL,
-               .val = 0
        },
        {
-#define no_registry_opt        4
+#define no_registry_opt        2
                .name = "no-registry",
-               .has_arg = 0,
-               .flag = &__node_info.no_registry,
+               .flag = &__copperplate_setup_data.no_registry,
                .val = 1
        },
        {
-#define session_opt    5
+#define session_opt    3
                .name = "session",
                .has_arg = 1,
-               .flag = NULL,
-               .val = 0
        },
        {
-#define affinity_opt   6
-               .name = "cpu-affinity",
-               .has_arg = 1,
-               .flag = NULL,
-               .val = 0
-       },
-       {
-#define silent_opt     7
-               .name = "silent",
-               .has_arg = 0,
-               .flag = &__node_info.silent_mode,
-               .val = 1
-       },
-       {
-#define version_opt    8
-               .name = "version",
-               .has_arg = 0,
-               .flag = NULL,
-               .val = 0
-       },
-       {
-#define dumpconfig_opt 9
-               .name = "dump-config",
-               .has_arg = 0,
-               .flag = NULL,
-               .val = 0
-       },
-       {
-#define no_sanity_opt  10
-               .name = "no-sanity",
-               .has_arg = 0,
-               .flag = &__node_info.no_sanity,
-               .val = 1
-       },
-       {
-#define sanity_opt     11
-               .name = "sanity",
-               .has_arg = 0,
-               .flag = &__node_info.no_sanity,
-               .val = 0
-       },
-       {
-               .name = NULL,
-               .has_arg = 0,
-               .flag = NULL,
-               .val = 0
+               /* sentinel */
        }
 };
 
-static inline void print_version(void)
-{
-       extern const char *xenomai_version_string;
-       fprintf(stderr, "%s\n", xenomai_version_string);
-}
-
-static inline void dump_configuration(void)
-{
-       int n;
-
-       for (n = 0; config_strings[n]; n++)
-               puts(config_strings[n]);
-}
-
-static void usage(void)
-{
-       struct copperskin *skin;
-
-       print_version();
-        fprintf(stderr, "usage: program <options>, where options may be:\n");
-       fprintf(stderr, "--mem-pool-size=<sizeK>          size of the main heap 
(kbytes)\n");
-        fprintf(stderr, "--no-mlock                       do not lock memory 
at init (Mercury only)\n");
-        fprintf(stderr, "--registry-root=<path>           root path of 
registry\n");
-        fprintf(stderr, "--no-registry                    suppress object 
registration\n");
-        fprintf(stderr, "--session=<label>                label of shared 
multi-processing session\n");
-        fprintf(stderr, "--cpu-affinity=<cpu[,cpu]...>    set CPU affinity of 
threads\n");
-        fprintf(stderr, "--[no-]sanity                    disable/enable 
sanity checks\n");
-        fprintf(stderr, "--silent                         tame down 
verbosity\n");
-        fprintf(stderr, "--version                        get version 
information\n");
-        fprintf(stderr, "--dump-config                    dump configuration 
settings\n");
-
-       if (pvlist_empty(&skins))
-               return;
-
-       pvlist_for_each_entry(skin, &skins, __reserved.next) {
-               if (skin->help)
-                       skin->help();
-       }
-}
-
-static int collect_cpu_affinity(const char *cpu_list)
-{
-       char *s = strdup(cpu_list), *p, *n;
-       int ret, cpu;
-
-       n = s;
-       while ((p = strtok(n, ",")) != NULL) {
-               cpu = atoi(p);
-               if (cpu >= CPU_SETSIZE) {
-                       free(s);
-                       warning("invalid CPU number '%d'", cpu);
-                       return __bt(-EINVAL);
-               }
-               CPU_SET(cpu, &__node_info.cpu_affinity);
-               n = NULL;
-       }
-
-       free(s);
-
-       /*
-        * Check we may use this affinity, at least one CPU from the
-        * given set should be available for running threads. Since
-        * CPU affinity will be inherited by children threads, we only
-        * have to set it here.
-        *
-        * NOTE: we don't clear __node_info.cpu_affinity on entry to
-        * this routine to allow cumulative --cpu-affinity options to
-        * appear in the command line arguments.
-        */
-       ret = sched_setaffinity(0, sizeof(__node_info.cpu_affinity),
-                               &__node_info.cpu_affinity);
-       if (ret) {
-               warning("invalid CPU in affinity list '%s'", cpu_list);
-               return __bt(-errno);
-       }
-
-       return 0;
-}
-
-static inline char **prep_args(int argc, char *const argv[], int *largcp)
-{
-       int in, out, n, maybe_arg, lim;
-       char **uargv, *p;
-
-       uargv = malloc(argc * sizeof(char *));
-       if (uargv == NULL)
-               return NULL;
-
-       for (n = 0; n < argc; n++) {
-               uargv[n] = strdup(argv[n]);
-               if (uargv[n] == NULL)
-                       return NULL;
-       }
-
-       lim = argc;
-       in = maybe_arg = 0;
-       while (in < lim) {
-               if ((uargv[in][0] == '-' && uargv[in][1] != '-') ||
-                   (maybe_arg && uargv[in][0] != '-')) {
-                       p = strdup(uargv[in]);
-                       for (n = in, out = in + 1; out < argc; out++, n++) {
-                               free(uargv[n]);
-                               uargv[n] = strdup(uargv[out]);
-                       }
-                       free(uargv[argc - 1]);
-                       uargv[argc - 1] = p;
-                       if (*p == '-')
-                               maybe_arg = 1;
-                       lim--;
-               } else {
-                       in++;
-                       maybe_arg = 0;
-               }
-       }
-
-       *largcp = lim;
-
-       return uargv;
-}
-
-static inline void pack_args(int *argcp, int *largcp, char **argv)
-{
-       int in, out;
-
-       for (in = out = 0; in < *argcp; in++) {
-               if (*argv[in])
-                       argv[out++] = argv[in];
-               else {
-                       free(argv[in]);
-                       (*largcp)--;
-               }
-       }
-
-       *argcp = out;
-}
-
-static struct option *build_option_array(int *base_opt_startp)
-{
-       struct option *options, *q;
-       struct copperskin *skin;
-       const struct option *p;
-       int nopts;
-
-       nopts = sizeof(base_options) / sizeof(base_options[0]);
-
-       if (!pvlist_empty(&skins)) {
-               pvlist_for_each_entry(skin, &skins, __reserved.next) {
-                       p = skin->options;
-                       if (p) {
-                               while (p->name) {
-                                       nopts++;
-                                       p++;
-                               }
-                       }
-               }
-       }
-
-       options = malloc(sizeof(*options) * nopts);
-       if (options == NULL)
-               return NULL;
-
-       q = options;
-
-       if (!pvlist_empty(&skins)) {
-               pvlist_for_each_entry(skin, &skins, __reserved.next) {
-                       p = skin->options;
-                       if (p) {
-                               skin->__reserved.opt_start = q - options;
-                               while (p->name)
-                                       memcpy(q++, p++, sizeof(*q));
-                       }
-                       skin->__reserved.opt_end = q - options;
-               }
-       }
-
-       *base_opt_startp = q - options;
-       memcpy(q, base_options, sizeof(base_options));
-
-       return options;
-}
-
-static int parse_base_options(int *argcp, char *const **argvp,
-                             int *largcp, char ***uargvp,
-                             const struct option *options,
-                             int base_opt_start)
-{
-       int c, lindex, ret, n;
-       char **uargv;
-
-       /*
-        * Prepare a user argument vector we can modify, copying the
-        * one we have been given by the application code in
-        * copperplate_init(). This vector will be expunged from
-        * Xenomai proper options as we discover them.
-        */
-       uargv = prep_args(*argcp, *argvp, largcp);
-       if (uargv == NULL)
-               return -ENOMEM;
-
-       *uargvp = uargv;
-       opterr = 0;
-
-       /*
-        * NOTE: since we pack the argument vector on the fly while
-        * processing the options, optarg should be considered as
-        * volatile by skin option handlers; i.e. strdup() is required
-        * if the value has to be retained. Values from the user
-        * vector returned by copperplate_init() live in permanent
-        * memory though.
-        */
-
-       for (;;) {
-               lindex = -1;
-               c = getopt_long(*largcp, uargv, "", options, &lindex);
-               if (c == EOF)
-                       break;
-               if (lindex == -1)
-                       continue;
-
-               switch (lindex - base_opt_start) {
-               case mempool_opt:
-                       __node_info.mem_pool = atoi(optarg) * 1024;
-                       break;
-               case session_opt:
-                       __node_info.session_label = strdup(optarg);
-                       break;
-               case regroot_opt:
-                       __node_info.registry_root = strdup(optarg);
-                       break;
-               case affinity_opt:
-                       ret = collect_cpu_affinity(optarg);
-                       if (ret)
-                               return ret;
-                       break;
-               case no_mlock_opt:
-               case no_sanity_opt:
-               case no_registry_opt:
-               case sanity_opt:
-               case silent_opt:
-                       break;
-               case version_opt:
-                       print_version();
-                       exit(0);
-               case dumpconfig_opt:
-                       dump_configuration();
-                       exit(0);
-               case help_opt:
-                       usage();
-                       exit(0);
-               default:
-                       /* Skin option, don't process yet. */
-                       continue;
-               }
-
-               /*
-                * Clear the first byte of the base option we found
-                * (including any companion argument), pack_args()
-                * will expunge all options we have already handled.
-                *
-                * NOTE: this code relies on the fact that only long
-                * options with double-dash markers can be parsed here
-                * after prep_args() did its job (we do not support
-                * -foo as a long option). This is aimed at reserving
-                * use of short options to the application layer,
-                * sharing only the long option namespace with the
-                * Xenomai core libs.
-                */
-               n = optind - 1;
-               if (uargv[n][0] != '-' || uargv[n][1] != '-')
-                       /* Clear the separate argument value. */
-                       uargv[n--][0] = '\0';
-               uargv[n][0] = '\0'; /* Clear the option switch. */
-       }
-
-       pack_args(argcp, largcp, uargv);
-
-       optind = 0;
-
-       return 0;
-}
-
-static int parse_skin_options(int *argcp, int largc, char **uargv,
-                             const struct option *options)
-{
-       struct copperskin *skin;
-       int lindex, n, c, ret;
-
-       for (;;) {
-               lindex = -1;
-               c = getopt_long(largc, uargv, "", options, &lindex);
-               if (c == EOF)
-                       break;
-               if (lindex == -1)
-                       continue; /* Not handled here. */
-               pvlist_for_each_entry(skin, &skins, __reserved.next) {
-                       if (skin->parse_option == NULL)
-                               continue;
-                       if (lindex < skin->__reserved.opt_start ||
-                           lindex >= skin->__reserved.opt_end)
-                               continue;
-                       lindex -= skin->__reserved.opt_start;
-                       ret = skin->parse_option(lindex, optarg);
-                       if (ret == 0)
-                               break;
-                       return ret;
-               }
-               n = optind - 1;
-               if (uargv[n][0] != '-' || uargv[n][1] != '-')
-                       /* Clear the separate argument value. */
-                       uargv[n--][0] = '\0';
-               uargv[n][0] = '\0'; /* Clear the option switch. */
-       }
-
-       pack_args(argcp, &largc, uargv);
-
-       optind = 0;
-
-       return 0;
-}
-
 /*
  * Routine to bring up the basic copperplate features, but not enough
  * to run over a non-POSIX real-time interface though. For internal
  * code only, such as sysregd. No code traversed should depend on
- * __node_info.
+ * __copperplate_setup_data.
  */
 void copperplate_bootstrap_minimal(const char *arg0, char *mountpt,
                                   int regflags)
@@ -517,96 +116,38 @@ static int get_session_root(int *regflags_r)
        if (pw == NULL)
                return -errno;
 
-       if (__node_info.session_label == NULL) {
+       if (__copperplate_setup_data.session_label == NULL) {
                ret = asprintf(&session, "anon@%d", __node_id);
                if (ret < 0)
                        return -ENOMEM;
-               __node_info.session_label = session;
+               __copperplate_setup_data.session_label = session;
                *regflags_r |= REGISTRY_ANON;
-       } else if (strchr(__node_info.session_label, '/')) {
+       } else if (strchr(__copperplate_setup_data.session_label, '/')) {
                warning("session name may not contain slashes");
                return -EINVAL;
        }
 
        ret = asprintf(&sessdir, "%s/%s/%s",
-                      __node_info.registry_root,
-                      pw->pw_name, __node_info.session_label);
+                      __copperplate_setup_data.registry_root,
+                      pw->pw_name, __copperplate_setup_data.session_label);
        if (ret < 0)
                return -ENOMEM;
 
-       __node_info.session_root = sessdir;
+       __copperplate_setup_data.session_root = sessdir;
 
        return 0;
 }
 
-/* The application-level copperplate init call. */
-
-void copperplate_init(int *argcp, char *const **argvp)
+static int copperplate_init(void)
 {
-       int ret, largc, base_opt_start, regflags = 0;
-       struct copperskin *skin;
-       struct option *options;
-       static int init_done;
-       char **uargv = NULL;
-       struct service svc;
-
-       if (init_done) {
-               warning("duplicate call to %s() ignored", __func__);
-               warning("(xeno-config --no-auto-init disables implicit call)");
-               return;
-       }
-
-       boilerplate_init();
+       int ret, regflags = 0;
 
        threadobj_init_key();
 
-       /* Our node id. is the tid of the main thread. */
-       __node_id = get_thread_pid();
-
-       /* No ifs, no buts: we must be called over the main thread. */
-       assert(getpid() == __node_id);
-
-       /* Define default CPU affinity, i.e. no particular affinity. */
-       CPU_ZERO(&__node_info.cpu_affinity);
-
-       /*
-        * Build the global option array, merging the base and
-        * per-skin option sets.
-        */
-       options = build_option_array(&base_opt_start);
-       if (options == NULL) {
-               ret = -ENOMEM;
-               goto fail;
-       }
-
-       /*
-        * Parse the base options first, to bootstrap the core with
-        * the right config values.
-        */
-       ret = parse_base_options(argcp, argvp, &largc, &uargv,
-                                options, base_opt_start);
-       if (ret)
-               goto fail;
-
-#ifndef CONFIG_SMP
-       if (__node_info.no_sanity == 0) {
-               ret = get_static_cpu_count();
-               if (ret > 0)
-                       early_panic("running non-SMP libraries on SMP kernel?\n"
-           "              build with --enable-smp or disable check with 
--no-sanity");
-       }
-#endif
-
-       ret = debug_init();
-       if (ret) {
-               warning("failed to initialize debugging features");
-               goto fail;
-       }
-
        ret = heapobj_pkg_init_private();
        if (ret) {
                warning("failed to initialize main private heap");
-               goto fail;
+               return ret;
        }
 
        /*
@@ -615,103 +156,75 @@ void copperplate_init(int *argcp, char *const **argvp)
         */
        ret = get_session_root(&regflags);
        if (ret)
-               goto fail;
+               return ret;
 
        ret = heapobj_pkg_init_shared();
        if (ret) {
                warning("failed to initialize main shared heap");
-               goto fail;
+               return ret;
        }
 
-       if (__node_info.no_registry == 0) {
-               ret = registry_pkg_init(uargv[0], regflags);
+       if (__copperplate_setup_data.no_registry == 0) {
+               ret = registry_pkg_init(__base_setup_data.arg0, regflags);
                if (ret)
-                       goto fail;
+                       return ret;
        }
 
        ret = threadobj_pkg_init();
        if (ret) {
                warning("failed to initialize multi-threading package");
-               goto fail;
+               return ret;
        }
 
        ret = timerobj_pkg_init();
        if (ret) {
                warning("failed to initialize timer support");
-               goto fail;
-       }
-
-#ifdef CONFIG_XENO_MERCURY
-       if (__node_info.no_mlock == 0) {
-               ret = mlockall(MCL_CURRENT | MCL_FUTURE);
-               if (ret) {
-                       ret = -errno;
-                       warning("failed to lock memory");
-                       goto fail;
-               }
+               return ret;
        }
-#endif
-
-       /*
-        * Now that we have bootstrapped the core, we may call the
-        * skin handlers for parsing their own options, which in turn
-        * may create system objects on the fly.
-        */
-       if (!pvlist_empty(&skins)) {
-               ret = parse_skin_options(argcp, largc, uargv, options);
-               if (ret)
-                       goto fail;
-
-               CANCEL_DEFER(svc);
-
-               pvlist_for_each_entry(skin, &skins, __reserved.next) {
-                       ret = skin->init();
-                       if (ret)
-                               break;
-               }
 
-               CANCEL_RESTORE(svc);
-
-               if (ret) {
-                       warning("skin %s won't initialize", skin->name);
-                       goto fail;
-               }
-       }
+       return 0;
+}
 
-       free(options);
-
-#ifdef CONFIG_XENO_DEBUG
-       if (__node_info.silent_mode == 0) {
-               warning("Xenomai compiled with %s debug enabled,\n"
-                       "                              "
-                       "%shigh latencies expected [--enable-debug=%s]",
-#ifdef CONFIG_XENO_DEBUG_FULL
-                       "full", "very ", "full"
-#else
-                       "partial", "", "partial"
-#endif
-                       );
+static int copperplate_parse_option(int optnum, const char *optarg)
+{
+       switch (optnum) {
+       case mempool_opt:
+               __copperplate_setup_data.mem_pool = atoi(optarg) * 1024;
+               break;
+       case session_opt:
+               __copperplate_setup_data.session_label = strdup(optarg);
+               break;
+       case regroot_opt:
+               __copperplate_setup_data.registry_root = strdup(optarg);
+               break;
+       case no_registry_opt:
+               break;
+       default:
+               /* Paranoid, can't happen. */
+               return -EINVAL;
        }
-#endif
 
-       /*
-        * The final user arg vector only contains options we could
-        * not handle. The caller should be able to process them, or
-        * bail out.
-        */
-       *argvp = uargv;
-       init_done = 1;
-
-       return;
-fail:
-       early_panic("initialization failed, %s", symerror(ret));
+       return 0;
 }
 
-void copperplate_register_skin(struct copperskin *p)
+static void copperplate_help(void)
 {
-       pvlist_append(&p->__reserved.next, &skins);
+       fprintf(stderr, "--mem-pool-size=<sizeK>          size of the main heap 
(kbytes)\n");
+        fprintf(stderr, "--no-registry                    suppress object 
registration\n");
+        fprintf(stderr, "--registry-root=<path>           root path of 
registry\n");
+        fprintf(stderr, "--session=<label>                label of shared 
multi-processing session\n");
 }
 
+static struct skin_descriptor copperplate_interface = {
+       .name = "copperplate",
+       .init = copperplate_init,
+       .options = copperplate_options,
+       .parse_option = copperplate_parse_option,
+       .help = copperplate_help,
+};
+
+DECLARE_SKIN(copperplate_interface, __LIBCOPPERPLATE_CTOR_PRIO);
+
 /**
  * @{
  *
diff --git a/lib/copperplate/internal.h b/lib/copperplate/internal.h
index 7f42e86..582c4a1 100644
--- a/lib/copperplate/internal.h
+++ b/lib/copperplate/internal.h
@@ -28,6 +28,7 @@
 #include <boilerplate/ancillaries.h>
 #include <boilerplate/limits.h>
 #include <boilerplate/sched.h>
+#include <boilerplate/setup.h>
 #include <copperplate/heapobj.h>
 
 #ifdef CONFIG_XENO_REGISTRY
@@ -36,16 +37,12 @@
 #define DEFAULT_REGISTRY_ROOT          NULL
 #endif
 
-struct coppernode {
-       unsigned int mem_pool;
-       const char *registry_root;
-       const char *session_label;
+struct copperplate_setup_data {
        const char *session_root;
-       cpu_set_t cpu_affinity;
-       int no_mlock;
+       const char *session_label;
+       const char *registry_root;
        int no_registry;
-       int no_sanity;
-       int silent_mode;
+       unsigned int mem_pool;
 };
 
 #define HOBJ_MINLOG2    3
@@ -88,13 +85,11 @@ struct corethread_attributes {
        } __reserved;
 };
 
-extern pid_t __node_id;
-
-extern struct coppernode __node_info;
+extern struct copperplate_setup_data __copperplate_setup_data;
 
 static inline void copperplate_set_silent(void)
 {
-       __node_info.silent_mode = 1;
+       __base_setup_data.silent_mode = 1;
 }
 
 #ifdef __cplusplus
diff --git a/lib/copperplate/main.c b/lib/copperplate/main.c
index 561bcf2..f67a592 100644
--- a/lib/copperplate/main.c
+++ b/lib/copperplate/main.c
@@ -24,7 +24,7 @@ __attribute__((alias("copperplate_main"), weak));
 
 int copperplate_main(int argc, char *const argv[])
 {
-       copperplate_init(&argc, &argv);
+       xenomai_init(&argc, &argv);
 
        return __real_main(argc, argv);
 }
diff --git a/lib/copperplate/regd/fs-common.c b/lib/copperplate/regd/fs-common.c
index ab73d5c..1276b63 100644
--- a/lib/copperplate/regd/fs-common.c
+++ b/lib/copperplate/regd/fs-common.c
@@ -78,7 +78,7 @@ int open_threads(struct fsobj *fsobj, void *priv)
        const char *sched_class;
        int ret, count, len = 0;
 
-       ret = heapobj_bind_session(__node_info.session_label);
+       ret = heapobj_bind_session(__copperplate_setup_data.session_label);
        if (ret)
                return ret;
 
@@ -206,7 +206,7 @@ int open_heaps(struct fsobj *fsobj, void *priv)
        struct shared_heap *heap;
        int ret, count, len = 0;
 
-       ret = heapobj_bind_session(__node_info.session_label);
+       ret = heapobj_bind_session(__copperplate_setup_data.session_label);
        if (ret)
                return ret;
 
diff --git a/lib/copperplate/regd/regd.c b/lib/copperplate/regd/regd.c
index 18915cd..e544431 100644
--- a/lib/copperplate/regd/regd.c
+++ b/lib/copperplate/regd/regd.c
@@ -384,8 +384,8 @@ static void handle_requests(void)
                                        delete_system_fs();
                                        if (daemonize) {
                                                note("unlinking session %s",
-                                                    __node_info.session_label);
-                                               
heapobj_unlink_session(__node_info.session_label);
+                                                    
__copperplate_setup_data.session_label);
+                                               
heapobj_unlink_session(__copperplate_setup_data.session_label);
                                        }
                                        exit(0);
                                }
@@ -438,9 +438,9 @@ static void create_system_fs(const char *arg0, const char 
*rootdir, int flags)
 bootstrap:
        atexit(delete_system_fs);
 
-       CPU_ZERO(&__node_info.cpu_affinity);
-       __node_info.session_label = session;
-       __node_info.registry_root = rootdir;
+       CPU_ZERO(&__base_setup_data.cpu_affinity);
+       __copperplate_setup_data.session_label = session;
+       __copperplate_setup_data.registry_root = rootdir;
        sysroot = mountpt;
        copperplate_bootstrap_minimal(arg0, mountpt, flags);
 
diff --git a/lib/copperplate/registry.c b/lib/copperplate/registry.c
index 46a2f4e..ac041f1 100644
--- a/lib/copperplate/registry.c
+++ b/lib/copperplate/registry.c
@@ -100,7 +100,7 @@ int registry_add_dir(const char *fmt, ...)
        int ret, state;
        va_list ap;
 
-       if (__node_info.no_registry)
+       if (__copperplate_setup_data.no_registry)
                return 0;
 
        va_start(ap, fmt);
@@ -164,7 +164,7 @@ int registry_init_file(struct fsobj *fsobj,
        pthread_mutexattr_t mattr;
        int ret;
 
-       if (__node_info.no_registry)
+       if (__copperplate_setup_data.no_registry)
                return 0;
 
        fsobj->path = NULL;
@@ -191,7 +191,7 @@ int registry_add_file(struct fsobj *fsobj, int mode, const 
char *fmt, ...)
        int ret, state;
        va_list ap;
 
-       if (__node_info.no_registry)
+       if (__copperplate_setup_data.no_registry)
                return 0;
 
        va_start(ap, fmt);
@@ -244,7 +244,7 @@ void registry_destroy_file(struct fsobj *fsobj)
        struct regfs_dir *d;
        int state;
 
-       if (__node_info.no_registry)
+       if (__copperplate_setup_data.no_registry)
                return;
 
        write_lock_safe(&p->lock, state);
@@ -271,7 +271,7 @@ out:
 
 void registry_touch_file(struct fsobj *fsobj)
 {
-       if (__node_info.no_registry)
+       if (__copperplate_setup_data.no_registry)
                return;
 
        __RT(clock_gettime(CLOCK_COPPERPLATE, &fsobj->mtime));
@@ -814,7 +814,7 @@ int registry_pkg_init(const char *arg0, int flags)
        char *mountpt;
        int ret;
 
-       ret = connect_regd(__node_info.session_root, &mountpt, flags);
+       ret = connect_regd(__copperplate_setup_data.session_root, &mountpt, 
flags);
        if (ret)
                return ret;
 
diff --git a/lib/copperplate/traceobj.c b/lib/copperplate/traceobj.c
index 29a4528..f93975f 100644
--- a/lib/copperplate/traceobj.c
+++ b/lib/copperplate/traceobj.c
@@ -162,7 +162,7 @@ fail:
         * such unit tests on Mercury should be pinned on a single CPU
         * using --cpu-affinity.
         */
-       if (CPU_COUNT(&__node_info.cpu_affinity) == 0)
+       if (CPU_COUNT(&__base_setup_data.cpu_affinity) == 0)
                warning("NOTE: --cpu-affinity option was not given - this might 
explain?");
 #endif
 #ifndef CONFIG_XENO_ASYNC_CANCEL
diff --git a/lib/psos/init.c b/lib/psos/init.c
index 99521fa..c57afeb 100644
--- a/lib/psos/init.c
+++ b/lib/psos/init.c
@@ -130,19 +130,6 @@ static int psos_init(void)
        return 0;
 }
 
-static struct copperskin psos_skin = {
-       .name = "psos",
-       .init = psos_init,
-       .options = psos_options,
-       .parse_option = psos_parse_option,
-       .help = psos_help,
-};
-
-static __libpsos_ctor void register_psos(void)
-{
-       copperplate_register_skin(&psos_skin);
-}
-
 const char *__psos_maybe_short_name(char shrt[5], const char *lng)
 {
        if (psos_long_names)
@@ -153,3 +140,13 @@ const char *__psos_maybe_short_name(char shrt[5], const 
char *lng)
 
        return (const char *)shrt;
 }
+
+static struct skin_descriptor psos_skin = {
+       .name = "psos",
+       .init = psos_init,
+       .options = psos_options,
+       .parse_option = psos_parse_option,
+       .help = psos_help,
+};
+
+DECLARE_SKIN(psos_skin, __LIBPSOS_CTOR_PRIO);
diff --git a/lib/psos/init.h b/lib/psos/init.h
index eaaf265..34d832f 100644
--- a/lib/psos/init.h
+++ b/lib/psos/init.h
@@ -20,6 +20,4 @@
 
 #define __LIBPSOS_CTOR_PRIO  300
 
-#define __libpsos_ctor  __attribute__ ((constructor(__LIBPSOS_CTOR_PRIO)))
-
 #endif /* _PSOS_INIT_H */
diff --git a/lib/smokey/init.c b/lib/smokey/init.c
index 3241d45..1fc6e7f 100644
--- a/lib/smokey/init.c
+++ b/lib/smokey/init.c
@@ -272,7 +272,7 @@ static const struct option smokey_options[] = {
                .val = 1,
        },
        {
-               .name = NULL,
+               /* sentinel */
        }
 };
 
@@ -415,6 +415,12 @@ static void list_all_tests(void)
                       t->__reserved.id, t->name, t->description);
 }
 
+void smokey_register_plugin(struct smokey_test *t)
+{
+       pvlist_append(&t->__reserved.next, &register_list);
+       t->__reserved.id = test_count++;
+}
+
 static int smokey_parse_option(int optnum, const char *optarg)
 {
        int ret = 0;
@@ -455,7 +461,7 @@ static int smokey_init(void)
        return 0;
 }
 
-static struct copperskin smokey_interface = {
+static struct skin_descriptor smokey_interface = {
        .name = "smokey",
        .init = smokey_init,
        .options = smokey_options,
@@ -463,14 +469,4 @@ static struct copperskin smokey_interface = {
        .help = smokey_help,
 };
 
-static  __attribute__ ((constructor(__SMOKEYPLUG_CTOR_PRIO+1)))
-void register_smokey(void)
-{
-       copperplate_register_skin(&smokey_interface);
-}
-
-void smokey_register_plugin(struct smokey_test *t)
-{
-       pvlist_append(&t->__reserved.next, &register_list);
-       t->__reserved.id = test_count++;
-}
+DECLARE_SKIN(smokey_interface, __SMOKEYPLUG_CTOR_PRIO+1);
diff --git a/lib/trank/init.c b/lib/trank/init.c
index 9dc1671..5773c79 100644
--- a/lib/trank/init.c
+++ b/lib/trank/init.c
@@ -29,6 +29,8 @@
  * over Xenomai 3.x.
  */
 
+#define __libtrank_ctor  __attribute__ ((constructor(__LIBTRANK_CTOR_PRIO)))
+
 static __libtrank_ctor void init_trank(void)
 {
        trank_init_interface();
diff --git a/lib/trank/init.h b/lib/trank/init.h
index 287880e..182b109 100644
--- a/lib/trank/init.h
+++ b/lib/trank/init.h
@@ -20,6 +20,4 @@
 
 #define __LIBTRANK_CTOR_PRIO  350
 
-#define __libtrank_ctor  __attribute__ ((constructor(__LIBTRANK_CTOR_PRIO)))
-
 #endif /* !_TRANK_INIT_H */
diff --git a/lib/vxworks/init.c b/lib/vxworks/init.c
index 54b7cf9..d1f0581 100644
--- a/lib/vxworks/init.c
+++ b/lib/vxworks/init.c
@@ -102,7 +102,7 @@ static int vxworks_init(void)
        return 0;
 }
 
-static struct copperskin vxworks_skin = {
+static struct skin_descriptor vxworks_skin = {
        .name = "vxworks",
        .init = vxworks_init,
        .options = vxworks_options,
@@ -110,7 +110,4 @@ static struct copperskin vxworks_skin = {
        .help = vxworks_help,
 };
 
-static __libvxworks_ctor void register_vxworks(void)
-{
-       copperplate_register_skin(&vxworks_skin);
-}
+DECLARE_SKIN(vxworks_skin, __LIBVXWORKS_CTOR_PRIO);
diff --git a/lib/vxworks/init.h b/lib/vxworks/init.h
index a45bfc1..2f35162 100644
--- a/lib/vxworks/init.h
+++ b/lib/vxworks/init.h
@@ -20,6 +20,4 @@
 
 #define __LIBVXWORKS_CTOR_PRIO  300
 
-#define __libvxworks_ctor  __attribute__ 
((constructor(__LIBVXWORKS_CTOR_PRIO)))
-
 #endif /* _VXWORKS_INIT_H */


_______________________________________________
Xenomai-git mailing list
Xenomai-git@xenomai.org
http://www.xenomai.org/mailman/listinfo/xenomai-git

Reply via email to