Module: xenomai-3 Branch: next Commit: d90722e2b7102fb9f340cb181a080629e1fe3aeb URL: http://git.xenomai.org/?p=xenomai-3.git;a=commit;h=d90722e2b7102fb9f340cb181a080629e1fe3aeb
Author: Philippe Gerum <r...@xenomai.org> Date: Sun Dec 27 16:20:41 2015 +0100 cobalt/corectl: move implementation to separate file --- kernel/cobalt/posix/Makefile | 1 + kernel/cobalt/posix/corectl.c | 189 +++++++++++++++++++++++++++++++++++++++++ kernel/cobalt/posix/corectl.h | 27 ++++++ kernel/cobalt/posix/syscall.c | 163 +---------------------------------- 4 files changed, 218 insertions(+), 162 deletions(-) diff --git a/kernel/cobalt/posix/Makefile b/kernel/cobalt/posix/Makefile index 2da764a..f194bff 100644 --- a/kernel/cobalt/posix/Makefile +++ b/kernel/cobalt/posix/Makefile @@ -6,6 +6,7 @@ obj-$(CONFIG_XENOMAI) += xenomai.o xenomai-y := \ clock.o \ cond.o \ + corectl.o \ event.o \ io.o \ memory.o \ diff --git a/kernel/cobalt/posix/corectl.c b/kernel/cobalt/posix/corectl.c new file mode 100644 index 0000000..f5af386 --- /dev/null +++ b/kernel/cobalt/posix/corectl.c @@ -0,0 +1,189 @@ +/* + * Copyright (C) 2016 Philippe Gerum <r...@xenomai.org>. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ +#include <linux/types.h> +#include <linux/errno.h> +#include <linux/ipipe.h> +#include <linux/kconfig.h> +#include <linux/atomic.h> +#include <linux/printk.h> +#include <cobalt/kernel/init.h> +#include <cobalt/kernel/thread.h> +#include <xenomai/version.h> +#include <asm/xenomai/syscall.h> +#include "corectl.h" + +static int get_conf_option(int option, void __user *u_buf, size_t u_bufsz) +{ + int ret, val = 0; + + if (u_bufsz < sizeof(val)) + return -EINVAL; + + switch (option) { + case _CC_COBALT_GET_VERSION: + val = XENO_VERSION_CODE; + break; + case _CC_COBALT_GET_NR_PIPES: +#ifdef CONFIG_XENO_OPT_PIPE + val = CONFIG_XENO_OPT_PIPE_NRDEV; +#endif + break; + case _CC_COBALT_GET_NR_TIMERS: + val = CONFIG_XENO_OPT_NRTIMERS; + break; + case _CC_COBALT_GET_POLICIES: + val = _CC_COBALT_SCHED_FIFO|_CC_COBALT_SCHED_RR; + if (IS_ENABLED(CONFIG_XENO_OPT_SCHED_WEAK)) + val |= _CC_COBALT_SCHED_WEAK; + if (IS_ENABLED(CONFIG_XENO_OPT_SCHED_SPORADIC)) + val |= _CC_COBALT_SCHED_SPORADIC; + if (IS_ENABLED(CONFIG_XENO_OPT_SCHED_QUOTA)) + val |= _CC_COBALT_SCHED_QUOTA; + if (IS_ENABLED(CONFIG_XENO_OPT_SCHED_TP)) + val |= _CC_COBALT_SCHED_TP; + break; + case _CC_COBALT_GET_DEBUG: + if (IS_ENABLED(CONFIG_XENO_OPT_DEBUG_COBALT)) + val |= _CC_COBALT_DEBUG_ASSERT; + if (IS_ENABLED(CONFIG_XENO_OPT_DEBUG_CONTEXT)) + val |= _CC_COBALT_DEBUG_CONTEXT; + if (IS_ENABLED(CONFIG_XENO_OPT_DEBUG_LOCKING)) + val |= _CC_COBALT_DEBUG_LOCKING; + if (IS_ENABLED(CONFIG_XENO_OPT_DEBUG_USER)) + val |= _CC_COBALT_DEBUG_USER; + if (IS_ENABLED(CONFIG_XENO_OPT_DEBUG_MUTEX_RELAXED)) + val |= _CC_COBALT_DEBUG_MUTEX_RELAXED; + if (IS_ENABLED(CONFIG_XENO_OPT_DEBUG_MUTEX_SLEEP)) + val |= _CC_COBALT_DEBUG_MUTEX_SLEEP; + if (IS_ENABLED(CONFIG_XENO_OPT_DEBUG_POSIX_SYNCHRO)) + val |= _CC_COBALT_DEBUG_POSIX_SYNCHRO; + if (IS_ENABLED(CONFIG_XENO_OPT_DEBUG_LEGACY)) + val |= _CC_COBALT_DEBUG_LEGACY; + if (IS_ENABLED(CONFIG_XENO_OPT_DEBUG_TRACE_RELAX)) + val |= _CC_COBALT_DEBUG_TRACE_RELAX; + break; + case _CC_COBALT_GET_WATCHDOG: +#ifdef CONFIG_XENO_OPT_WATCHDOG + val = CONFIG_XENO_OPT_WATCHDOG_TIMEOUT; +#endif + break; + case _CC_COBALT_GET_CORE_STATUS: + val = realtime_core_state(); + break; + default: + return -EINVAL; + } + + ret = cobalt_copy_to_user(u_buf, &val, sizeof(val)); + + return ret ? -EFAULT : 0; +} + +static int stop_services(const void __user *u_buf, size_t u_bufsz) +{ + const int final_grace_period = 3; /* seconds */ + enum cobalt_run_states state; + int ret, timeout; + + /* + * XXX: we don't have any syscall for unbinding a thread from + * the Cobalt core, so we deny real-time threads from stopping + * Cobalt services. i.e. _CC_COBALT_STOP_CORE must be issued + * from a plain regular linux thread. + */ + if (xnthread_current()) + return -EPERM; + + if (u_bufsz != sizeof(int)) + return -EINVAL; + + ret = cobalt_copy_from_user(&timeout, u_buf, sizeof(timeout)); + if (ret) + return ret; + + state = atomic_cmpxchg(&cobalt_runstate, + COBALT_STATE_RUNNING, + COBALT_STATE_TEARDOWN); + switch (state) { + case COBALT_STATE_STOPPED: + break; + case COBALT_STATE_RUNNING: + /* Kill user threads. */ + ret = xnthread_killall(timeout, XNUSER); + if (ret) { + set_realtime_core_state(state); + return ret; + } + cobalt_call_notifier_chain(COBALT_STATE_TEARDOWN); + /* Kill lingering RTDM tasks. */ + ret = xnthread_killall(final_grace_period, 0); + if (ret == -EAGAIN) + printk(XENO_WARNING "some RTDM tasks won't stop"); + xntimer_release_hardware(); + set_realtime_core_state(COBALT_STATE_STOPPED); + printk(XENO_INFO "services stopped\n"); + break; + default: + ret = -EINPROGRESS; + } + + return ret; +} + +static int start_services(void) +{ + enum cobalt_run_states state; + int ret = 0; + + state = atomic_cmpxchg(&cobalt_runstate, + COBALT_STATE_STOPPED, + COBALT_STATE_WARMUP); + switch (state) { + case COBALT_STATE_RUNNING: + break; + case COBALT_STATE_STOPPED: + xntimer_grab_hardware(); + cobalt_call_notifier_chain(COBALT_STATE_WARMUP); + set_realtime_core_state(COBALT_STATE_RUNNING); + printk(XENO_INFO "services started\n"); + break; + default: + ret = -EINPROGRESS; + } + + return ret; +} + +COBALT_SYSCALL(corectl, probing, + (int request, void __user *u_buf, size_t u_bufsz)) +{ + int ret; + + switch (request) { + case _CC_COBALT_STOP_CORE: + ret = stop_services(u_buf, u_bufsz); + break; + case _CC_COBALT_START_CORE: + ret = start_services(); + break; + default: + ret = get_conf_option(request, u_buf, u_bufsz); + } + + return ret; +} diff --git a/kernel/cobalt/posix/corectl.h b/kernel/cobalt/posix/corectl.h new file mode 100644 index 0000000..79f46ae --- /dev/null +++ b/kernel/cobalt/posix/corectl.h @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2016 Philippe Gerum <r...@xenomai.org>. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ +#ifndef _COBALT_POSIX_CORECTL_H +#define _COBALT_POSIX_CORECTL_H + +#include <xenomai/posix/syscall.h> +#include <cobalt/uapi/corectl.h> + +COBALT_SYSCALL_DECL(corectl, + (int request, void __user *u_buf, size_t u_bufsz)); + +#endif /* !_COBALT_POSIX_CORECTL_H */ diff --git a/kernel/cobalt/posix/syscall.c b/kernel/cobalt/posix/syscall.c index 7f2e1c6..dd4dfba 100644 --- a/kernel/cobalt/posix/syscall.c +++ b/kernel/cobalt/posix/syscall.c @@ -24,7 +24,6 @@ #include <cobalt/kernel/tree.h> #include <cobalt/kernel/vdso.h> #include <cobalt/kernel/init.h> -#include <xenomai/version.h> #include <asm-generic/xenomai/mayday.h> #include "internal.h" #include "thread.h" @@ -40,6 +39,7 @@ #include "event.h" #include "timerfd.h" #include "io.h" +#include "corectl.h" #include "../debug.h" #include <trace/events/cobalt-posix.h> @@ -359,167 +359,6 @@ static COBALT_SYSCALL(extend, lostage, (unsigned int magic)) return cobalt_bind_personality(magic); } -static int get_conf_option(int option, void __user *u_buf, size_t u_bufsz) -{ - int ret, val = 0; - - if (u_bufsz < sizeof(val)) - return -EINVAL; - - switch (option) { - case _CC_COBALT_GET_VERSION: - val = XENO_VERSION_CODE; - break; - case _CC_COBALT_GET_NR_PIPES: -#ifdef CONFIG_XENO_OPT_PIPE - val = CONFIG_XENO_OPT_PIPE_NRDEV; -#endif - break; - case _CC_COBALT_GET_NR_TIMERS: - val = CONFIG_XENO_OPT_NRTIMERS; - break; - case _CC_COBALT_GET_POLICIES: - val = _CC_COBALT_SCHED_FIFO|_CC_COBALT_SCHED_RR; - if (IS_ENABLED(CONFIG_XENO_OPT_SCHED_WEAK)) - val |= _CC_COBALT_SCHED_WEAK; - if (IS_ENABLED(CONFIG_XENO_OPT_SCHED_SPORADIC)) - val |= _CC_COBALT_SCHED_SPORADIC; - if (IS_ENABLED(CONFIG_XENO_OPT_SCHED_QUOTA)) - val |= _CC_COBALT_SCHED_QUOTA; - if (IS_ENABLED(CONFIG_XENO_OPT_SCHED_TP)) - val |= _CC_COBALT_SCHED_TP; - break; - case _CC_COBALT_GET_DEBUG: - if (IS_ENABLED(CONFIG_XENO_OPT_DEBUG_COBALT)) - val |= _CC_COBALT_DEBUG_ASSERT; - if (IS_ENABLED(CONFIG_XENO_OPT_DEBUG_CONTEXT)) - val |= _CC_COBALT_DEBUG_CONTEXT; - if (IS_ENABLED(CONFIG_XENO_OPT_DEBUG_LOCKING)) - val |= _CC_COBALT_DEBUG_LOCKING; - if (IS_ENABLED(CONFIG_XENO_OPT_DEBUG_USER)) - val |= _CC_COBALT_DEBUG_USER; - if (IS_ENABLED(CONFIG_XENO_OPT_DEBUG_MUTEX_RELAXED)) - val |= _CC_COBALT_DEBUG_MUTEX_RELAXED; - if (IS_ENABLED(CONFIG_XENO_OPT_DEBUG_MUTEX_SLEEP)) - val |= _CC_COBALT_DEBUG_MUTEX_SLEEP; - if (IS_ENABLED(CONFIG_XENO_OPT_DEBUG_POSIX_SYNCHRO)) - val |= _CC_COBALT_DEBUG_POSIX_SYNCHRO; - if (IS_ENABLED(CONFIG_XENO_OPT_DEBUG_LEGACY)) - val |= _CC_COBALT_DEBUG_LEGACY; - if (IS_ENABLED(CONFIG_XENO_OPT_DEBUG_TRACE_RELAX)) - val |= _CC_COBALT_DEBUG_TRACE_RELAX; - break; - case _CC_COBALT_GET_WATCHDOG: -#ifdef CONFIG_XENO_OPT_WATCHDOG - val = CONFIG_XENO_OPT_WATCHDOG_TIMEOUT; -#endif - break; - case _CC_COBALT_GET_CORE_STATUS: - val = realtime_core_state(); - break; - default: - return -EINVAL; - } - - ret = cobalt_copy_to_user(u_buf, &val, sizeof(val)); - - return ret ? -EFAULT : 0; -} - -static int stop_services(const void __user *u_buf, size_t u_bufsz) -{ - const int final_grace_period = 3; /* seconds */ - enum cobalt_run_states state; - int ret, timeout; - - /* - * XXX: we don't have any syscall for unbinding a thread from - * the Cobalt core, so we deny real-time threads from stopping - * Cobalt services. i.e. _CC_COBALT_STOP_CORE must be issued - * from a plain regular linux thread. - */ - if (xnthread_current()) - return -EPERM; - - if (u_bufsz != sizeof(int)) - return -EINVAL; - - ret = cobalt_copy_from_user(&timeout, u_buf, sizeof(timeout)); - if (ret) - return ret; - - state = atomic_cmpxchg(&cobalt_runstate, - COBALT_STATE_RUNNING, - COBALT_STATE_TEARDOWN); - switch (state) { - case COBALT_STATE_STOPPED: - break; - case COBALT_STATE_RUNNING: - /* Kill user threads. */ - ret = xnthread_killall(timeout, XNUSER); - if (ret) { - set_realtime_core_state(state); - return ret; - } - cobalt_call_notifier_chain(COBALT_STATE_TEARDOWN); - /* Kill lingering RTDM tasks. */ - ret = xnthread_killall(final_grace_period, 0); - if (ret == -EAGAIN) - printk(XENO_WARNING "some RTDM tasks won't stop"); - xntimer_release_hardware(); - set_realtime_core_state(COBALT_STATE_STOPPED); - printk(XENO_INFO "services stopped\n"); - break; - default: - ret = -EINPROGRESS; - } - - return ret; -} - -static int start_services(void) -{ - enum cobalt_run_states state; - int ret = 0; - - state = atomic_cmpxchg(&cobalt_runstate, - COBALT_STATE_STOPPED, - COBALT_STATE_WARMUP); - switch (state) { - case COBALT_STATE_RUNNING: - break; - case COBALT_STATE_STOPPED: - xntimer_grab_hardware(); - cobalt_call_notifier_chain(COBALT_STATE_WARMUP); - set_realtime_core_state(COBALT_STATE_RUNNING); - printk(XENO_INFO "services started\n"); - break; - default: - ret = -EINPROGRESS; - } - - return ret; -} - -static COBALT_SYSCALL(corectl, probing, - (int request, void __user *u_buf, size_t u_bufsz)) -{ - int ret; - - switch (request) { - case _CC_COBALT_STOP_CORE: - ret = stop_services(u_buf, u_bufsz); - break; - case _CC_COBALT_START_CORE: - ret = start_services(); - break; - default: - ret = get_conf_option(request, u_buf, u_bufsz); - } - - return ret; -} - static int CoBaLt_ni(void) { return -ENOSYS; _______________________________________________ Xenomai-git mailing list Xenomai-git@xenomai.org http://xenomai.org/mailman/listinfo/xenomai-git