[Xenomai-git] Philippe Gerum : cobalt/sched: add start, stop SCHED_TP config operations
Module: xenomai-3 Branch: master Commit: 08af0a3457514230180cce05b3e0eda751a377db URL: http://git.xenomai.org/?p=xenomai-3.git;a=commit;h=08af0a3457514230180cce05b3e0eda751a377db Author: Philippe Gerum r...@xenomai.org Date: Thu Jul 30 14:16:04 2015 +0200 cobalt/sched: add start, stop SCHED_TP config operations We may want to start/stop a TP schedule without removing it from the CPU entirely. To this end, this commit introduces the sched_tp_start/stop requests, processed by sched_config_np(). --- include/cobalt/kernel/compat.h |1 + include/cobalt/uapi/sched.h |8 + kernel/cobalt/posix/sched.c | 30 +--- kernel/cobalt/posix/syscall32.c |4 +++ kernel/cobalt/sched-tp.c|9 +++-- lib/cobalt/thread.c | 72 --- 6 files changed, 97 insertions(+), 27 deletions(-) diff --git a/include/cobalt/kernel/compat.h b/include/cobalt/kernel/compat.h index 7420804..b0ef81e 100644 --- a/include/cobalt/kernel/compat.h +++ b/include/cobalt/kernel/compat.h @@ -61,6 +61,7 @@ struct compat_sched_tp_window { }; struct __compat_sched_config_tp { + int op; int nr_windows; struct compat_sched_tp_window windows[0]; }; diff --git a/include/cobalt/uapi/sched.h b/include/cobalt/uapi/sched.h index fc04f49..b672095 100644 --- a/include/cobalt/uapi/sched.h +++ b/include/cobalt/uapi/sched.h @@ -57,7 +57,15 @@ struct sched_tp_window { int ptid; }; +enum { + sched_tp_install, + sched_tp_uninstall, + sched_tp_start, + sched_tp_stop, +}; + struct __sched_config_tp { + int op; int nr_windows; struct sched_tp_window windows[0]; }; diff --git a/kernel/cobalt/posix/sched.c b/kernel/cobalt/posix/sched.c index 0e7d405..be2e441 100644 --- a/kernel/cobalt/posix/sched.c +++ b/kernel/cobalt/posix/sched.c @@ -242,14 +242,35 @@ int set_tp_config(int cpu, union sched_config *config, size_t len) if (len sizeof(config-tp)) return -EINVAL; - if (config-tp.nr_windows == 0) { + sched = xnsched_struct(cpu); + + switch (config-tp.op) { + case sched_tp_install: + if (config-tp.nr_windows 0) + break; + /* Fallback wanted. */ + case sched_tp_uninstall: gps = NULL; goto set_schedule; + case sched_tp_start: + xnlock_get_irqsave(nklock, s); + xnsched_tp_start_schedule(sched); + xnlock_put_irqrestore(nklock, s); + return 0; + case sched_tp_stop: + xnlock_get_irqsave(nklock, s); + xnsched_tp_stop_schedule(sched); + xnlock_put_irqrestore(nklock, s); + return 0; + default: + return -EINVAL; } + /* Install a new TP schedule on CPU. */ + gps = xnmalloc(sizeof(*gps) + config-tp.nr_windows * sizeof(*w)); if (gps == NULL) - goto fail; + return -ENOMEM; for (n = 0, p = config-tp.windows, w = gps-pwins, next_offset = 0; n config-tp.nr_windows; n++, p++, w++) { @@ -279,10 +300,8 @@ int set_tp_config(int cpu, union sched_config *config, size_t len) gps-pwin_nr = n; gps-tf_duration = next_offset; set_schedule: - sched = xnsched_struct(cpu); xnlock_get_irqsave(nklock, s); ogps = xnsched_tp_set_schedule(sched, gps); - xnsched_tp_start_schedule(sched); xnlock_put_irqrestore(nklock, s); if (ogps) @@ -292,7 +311,7 @@ set_schedule: cleanup_and_fail: xnfree(gps); -fail: + return -EINVAL; } @@ -333,6 +352,7 @@ ssize_t get_tp_config(int cpu, void __user *u_config, size_t len, goto out; } + config-tp.op = sched_tp_install; config-tp.nr_windows = gps-pwin_nr; for (n = 0, pp = p = config-tp.windows, pw = w = gps-pwins; n gps-pwin_nr; pp = p, p++, pw = w, w++, n++) { diff --git a/kernel/cobalt/posix/syscall32.c b/kernel/cobalt/posix/syscall32.c index 78d3c57..b3ce8a7 100644 --- a/kernel/cobalt/posix/syscall32.c +++ b/kernel/cobalt/posix/syscall32.c @@ -341,6 +341,7 @@ sys32_fetch_config(int policy, const void __user *u_config, size_t *len) if (policy == SCHED_QUOTA) memcpy(buf-quota, cbuf-quota, sizeof(cbuf-quota)); else { + buf-tp.op = cbuf-tp.op; buf-tp.nr_windows = cbuf-tp.nr_windows; for (n = 0; n buf-tp.nr_windows; n++) { buf-tp.windows[n].ptid = cbuf-tp.windows[n].ptid; @@ -387,9 +388,12 @@ static ssize_t sys32_put_config(int policy, sizeof(u_p-quota.info); } + /* SCHED_TP */ + if (u_len compat_sched_tp_confsz(config-tp.nr_windows)) return -ENOSPC; + __xn_put_user(config-tp.op, u_p-tp.op);
[Xenomai-git] Philippe Gerum : cobalt/sched: add start, stop SCHED_TP config operations
Module: xenomai-3 Branch: next Commit: 08af0a3457514230180cce05b3e0eda751a377db URL: http://git.xenomai.org/?p=xenomai-3.git;a=commit;h=08af0a3457514230180cce05b3e0eda751a377db Author: Philippe Gerum r...@xenomai.org Date: Thu Jul 30 14:16:04 2015 +0200 cobalt/sched: add start, stop SCHED_TP config operations We may want to start/stop a TP schedule without removing it from the CPU entirely. To this end, this commit introduces the sched_tp_start/stop requests, processed by sched_config_np(). --- include/cobalt/kernel/compat.h |1 + include/cobalt/uapi/sched.h |8 + kernel/cobalt/posix/sched.c | 30 +--- kernel/cobalt/posix/syscall32.c |4 +++ kernel/cobalt/sched-tp.c|9 +++-- lib/cobalt/thread.c | 72 --- 6 files changed, 97 insertions(+), 27 deletions(-) diff --git a/include/cobalt/kernel/compat.h b/include/cobalt/kernel/compat.h index 7420804..b0ef81e 100644 --- a/include/cobalt/kernel/compat.h +++ b/include/cobalt/kernel/compat.h @@ -61,6 +61,7 @@ struct compat_sched_tp_window { }; struct __compat_sched_config_tp { + int op; int nr_windows; struct compat_sched_tp_window windows[0]; }; diff --git a/include/cobalt/uapi/sched.h b/include/cobalt/uapi/sched.h index fc04f49..b672095 100644 --- a/include/cobalt/uapi/sched.h +++ b/include/cobalt/uapi/sched.h @@ -57,7 +57,15 @@ struct sched_tp_window { int ptid; }; +enum { + sched_tp_install, + sched_tp_uninstall, + sched_tp_start, + sched_tp_stop, +}; + struct __sched_config_tp { + int op; int nr_windows; struct sched_tp_window windows[0]; }; diff --git a/kernel/cobalt/posix/sched.c b/kernel/cobalt/posix/sched.c index 0e7d405..be2e441 100644 --- a/kernel/cobalt/posix/sched.c +++ b/kernel/cobalt/posix/sched.c @@ -242,14 +242,35 @@ int set_tp_config(int cpu, union sched_config *config, size_t len) if (len sizeof(config-tp)) return -EINVAL; - if (config-tp.nr_windows == 0) { + sched = xnsched_struct(cpu); + + switch (config-tp.op) { + case sched_tp_install: + if (config-tp.nr_windows 0) + break; + /* Fallback wanted. */ + case sched_tp_uninstall: gps = NULL; goto set_schedule; + case sched_tp_start: + xnlock_get_irqsave(nklock, s); + xnsched_tp_start_schedule(sched); + xnlock_put_irqrestore(nklock, s); + return 0; + case sched_tp_stop: + xnlock_get_irqsave(nklock, s); + xnsched_tp_stop_schedule(sched); + xnlock_put_irqrestore(nklock, s); + return 0; + default: + return -EINVAL; } + /* Install a new TP schedule on CPU. */ + gps = xnmalloc(sizeof(*gps) + config-tp.nr_windows * sizeof(*w)); if (gps == NULL) - goto fail; + return -ENOMEM; for (n = 0, p = config-tp.windows, w = gps-pwins, next_offset = 0; n config-tp.nr_windows; n++, p++, w++) { @@ -279,10 +300,8 @@ int set_tp_config(int cpu, union sched_config *config, size_t len) gps-pwin_nr = n; gps-tf_duration = next_offset; set_schedule: - sched = xnsched_struct(cpu); xnlock_get_irqsave(nklock, s); ogps = xnsched_tp_set_schedule(sched, gps); - xnsched_tp_start_schedule(sched); xnlock_put_irqrestore(nklock, s); if (ogps) @@ -292,7 +311,7 @@ set_schedule: cleanup_and_fail: xnfree(gps); -fail: + return -EINVAL; } @@ -333,6 +352,7 @@ ssize_t get_tp_config(int cpu, void __user *u_config, size_t len, goto out; } + config-tp.op = sched_tp_install; config-tp.nr_windows = gps-pwin_nr; for (n = 0, pp = p = config-tp.windows, pw = w = gps-pwins; n gps-pwin_nr; pp = p, p++, pw = w, w++, n++) { diff --git a/kernel/cobalt/posix/syscall32.c b/kernel/cobalt/posix/syscall32.c index 78d3c57..b3ce8a7 100644 --- a/kernel/cobalt/posix/syscall32.c +++ b/kernel/cobalt/posix/syscall32.c @@ -341,6 +341,7 @@ sys32_fetch_config(int policy, const void __user *u_config, size_t *len) if (policy == SCHED_QUOTA) memcpy(buf-quota, cbuf-quota, sizeof(cbuf-quota)); else { + buf-tp.op = cbuf-tp.op; buf-tp.nr_windows = cbuf-tp.nr_windows; for (n = 0; n buf-tp.nr_windows; n++) { buf-tp.windows[n].ptid = cbuf-tp.windows[n].ptid; @@ -387,9 +388,12 @@ static ssize_t sys32_put_config(int policy, sizeof(u_p-quota.info); } + /* SCHED_TP */ + if (u_len compat_sched_tp_confsz(config-tp.nr_windows)) return -ENOSPC; + __xn_put_user(config-tp.op, u_p-tp.op);