/* * Copyright (C) 2008 Philippe Gerum . * * 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 #include #include #include #include #include #include #include #include #include #include "copperplate/threadobj.h" #include "copperplate/heapobj.h" #include "copperplate/clockobj.h" #include "copperplate/registry.h" #include "copperplate/timerobj.h" #include "xenomai/init.h" #include "internal.h" struct copperplate_setup_data __copperplate_setup_data = { .mem_pool = 1024 * 1024, /* Default, 1Mb. */ .no_registry = 0, .registry_root = DEFAULT_REGISTRY_ROOT, .session_label = NULL, .session_root = NULL, .session_gid = USHRT_MAX, }; #ifdef CONFIG_XENO_COBALT int __cobalt_print_bufsz = 32 * 1024; #endif static const struct option copperplate_options[] = { { #define mempool_opt 0 .name = "mem-pool-size", .has_arg = required_argument, }, { #define regroot_opt 1 .name = "registry-root", .has_arg = required_argument, }, { #define no_registry_opt 2 .name = "no-registry", .has_arg = no_argument, .flag = &__copperplate_setup_data.no_registry, .val = 1 }, { #define session_opt 3 .name = "session", .has_arg = required_argument, }, { #define shared_registry_opt 4 .name = "shared-registry", .has_arg = no_argument, .flag = &__copperplate_setup_data.shared_registry, .val = 1, }, { /* Sentinel */ } }; /* * 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 * __copperplate_setup_data. */ void copperplate_bootstrap_internal(const char *arg0, char *mountpt, int regflags) { int ret; __node_id = get_thread_pid(); CPU_ZERO(&__base_setup_data.cpu_affinity); __boilerplate_init(); ret = heapobj_pkg_init_private(); if (ret) { early_warning("failed to initialize main private heap"); goto fail; } ret = __registry_pkg_init(arg0, mountpt, regflags); if (ret) goto fail; return; fail: early_panic("initialization failed, %s", symerror(ret)); } static int get_session_root(int *regflags_r) { char *sessdir, *session; struct passwd *pw; int ret; pw = getpwuid(geteuid()); if (pw == NULL) return -errno; if (__copperplate_setup_data.session_label == NULL) { ret = asprintf(&session, "anon@%d", __node_id); if (ret < 0) return -ENOMEM; __copperplate_setup_data.session_label = session; *regflags_r |= REGISTRY_ANON; } else if (strchr(__copperplate_setup_data.session_label, '/')) { warning("session name may not contain slashes"); return -EINVAL; } ret = asprintf(&sessdir, "%s/%s/%s", __copperplate_setup_data.registry_root, pw->pw_name, __copperplate_setup_data.session_label); if (ret < 0) return -ENOMEM; __copperplate_setup_data.session_root = sessdir; if (__copperplate_setup_data.shared_registry) *regflags_r |= REGISTRY_SHARED; return 0; } static int get_session_label(const char *optarg) { char *session, *grpname, *p; struct group *grp; gid_t gid; int ret; session = strdup(optarg); if (!session) return -ENOMEM; grpname = strrchr(session, '/'); if (grpname == NULL) goto no_group; *grpname++ = '\0'; if (isdigit(*grpname)) { gid = (gid_t)strtol(grpname, &p, 10); if (*p) { free(session); return -EINVAL; } errno = 0; grp = getgrgid(gid); } else { errno = 0; grp = getgrnam(grpname); } if (grp == NULL) { ret = errno ? -errno : -EINVAL; warning("invalid group %s", grpname); free(session); return ret; } __copperplate_setup_data.session_gid = grp->gr_gid; no_group: __copperplate_setup_data.session_label = session; return 0; } define_config_tunable(session_label, const char *, label) { get_session_label(label); } static int copperplate_init(void) { int ret, regflags = 0; threadobj_init_key(); ret = heapobj_pkg_init_private(); if (ret) { warning("failed to initialize main private heap"); return ret; } /* * We need the session label to be known before we create the * shared heap, which is named after the former. */ ret = get_session_root(®flags); if (ret) return ret; ret = heapobj_pkg_init_shared(); if (ret) { warning("failed to initialize main shared heap"); return ret; } if (__copperplate_setup_data.no_registry == 0) { ret = registry_pkg_init(__base_setup_data.arg0, regflags); if (ret) return ret; } ret = threadobj_pkg_init((regflags & REGISTRY_ANON) != 0); if (ret) { warning("failed to initialize multi-threading package"); return ret; } ret = timerobj_pkg_init(); if (ret) { warning("failed to initialize timer support"); return ret; } return 0; } static int copperplate_parse_option(int optnum, const char *optarg) { size_t memsz; int ret; switch (optnum) { case mempool_opt: memsz = get_mem_size(optarg); if (memsz == 0) return -EINVAL; /* * Emulate former sloppy syntax: values below 64k are * likely to represent kilobytes, not bytes. */ if (isdigit(optarg[strlen(optarg)-1]) && memsz < 64 * 1024) { memsz *= 1024; if (__base_setup_data.no_sanity == 0) warning("--mem-pool-size=, using %Zu bytes", memsz); } __copperplate_setup_data.mem_pool = memsz; break; case session_opt: ret = get_session_label(optarg); if (ret) return ret; break; case regroot_opt: __copperplate_setup_data.registry_root = strdup(optarg); break; case shared_registry_opt: case no_registry_opt: break; default: /* Paranoid, can't happen. */ return -EINVAL; } return 0; } static void copperplate_help(void) { fprintf(stderr, "--mem-pool-size= size of the main heap\n"); fprintf(stderr, "--no-registry suppress object registration\n"); fprintf(stderr, "--shared-registry enable public access to registry\n"); fprintf(stderr, "--registry-root= root path of registry\n"); fprintf(stderr, "--session=