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);
        __xn_put_user(config->tp.nr_windows, &u_p->tp.nr_windows);
 
        for (n = 0, ret = 0; n < config->tp.nr_windows; n++) {
diff --git a/kernel/cobalt/sched-tp.c b/kernel/cobalt/sched-tp.c
index b088cf4..1c70092 100644
--- a/kernel/cobalt/sched-tp.c
+++ b/kernel/cobalt/sched-tp.c
@@ -221,16 +221,21 @@ void xnsched_tp_start_schedule(struct xnsched *sched)
 {
        struct xnsched_tp *tp = &sched->tp;
 
+       if (tp->gps == NULL)
+               return;
+
        tp->wnext = 0;
        tp->tf_start = xnclock_read_monotonic(&nkclock);
-       tp_schedule_next(&sched->tp);
+       tp_schedule_next(tp);
 }
 EXPORT_SYMBOL_GPL(xnsched_tp_start_schedule);
 
 void xnsched_tp_stop_schedule(struct xnsched *sched)
 {
        struct xnsched_tp *tp = &sched->tp;
-       xntimer_stop(&tp->tf_timer);
+
+       if (tp->gps)
+               xntimer_stop(&tp->tf_timer);
 }
 EXPORT_SYMBOL_GPL(xnsched_tp_stop_schedule);
 
diff --git a/lib/cobalt/thread.c b/lib/cobalt/thread.c
index 140033d..3b24689 100644
--- a/lib/cobalt/thread.c
+++ b/lib/cobalt/thread.c
@@ -979,32 +979,64 @@ COBALT_IMPL(int, pthread_yield, (void))
  *
  * @par Settings applicable to SCHED_TP
  *
- * This call installs the temporal partitions for @a cpu.
- *
- * - config.tp.windows should be a non-null set of time windows,
- * defining the scheduling time slots for @a cpu. Each window defines
- * its offset from the start of the global time frame
- * (windows[].offset), a duration (windows[].duration), and the
- * partition id it applies to (windows[].ptid).
- *
- * Time windows must be strictly contiguous, i.e. windows[n].offset +
- * windows[n].duration shall equal windows[n + 1].offset.
- * If windows[].ptid is in the range
+ * This call controls the temporal partitions for @a cpu, depending on
+ * the operation requested.
+ *
+ * - config.tp.op specifies the operation to perform:
+ *
+ * - @a sched_tp_install installs a new TP schedule on @a cpu, defined
+ *   by config.tp.windows[]. The global time frame is not activated
+ *   upon return from this request yet; @a sched_tp_start must be
+ *   issued to activate the temporal scheduling on @a CPU.
+ *
+ * - @a sched_tp_uninstall removes the current TP schedule from @a
+ *   cpu, releasing all the attached resources. If no TP schedule
+ *   exists on @a CPU, this request has no effect.
+ *
+ * - @a sched_tp_start enables the temporal scheduling on @a cpu,
+ * starting the global time frame. If no TP schedule exists on @a cpu,
+ * this action has no effect.
+ *
+ * - @a sched_tp_stop disables the temporal scheduling on @a cpu.  The
+ * current TP schedule is not uninstalled though, and may be
+ * re-started later by a @a sched_tp_start request.
+ * @caution As a consequence of this request, threads assigned to the
+ * un-scheduled partitions may be starved from CPU time.
+ *
+ * - for a @a sched_tp_install operation, config.tp.nr_windows
+ * indicates the number of elements present in the config.tp.windows[]
+ * array. If config.tp.nr_windows is zero, the action taken is
+ * identical to @a sched_tp_uninstall.
+ *
+ * - if config.tp.nr_windows is non-zero, config.tp.windows[] is a set
+ * scheduling time slots for threads assigned to @a cpu. Each window
+ * is specified by its offset from the start of the global time frame
+ * (windows[].offset), its duration (windows[].duration), and the
+ * partition id it should activate during such period of time
+ * (windows[].ptid). This field is not considered for other requests
+ * than @a sched_tp_install.
+ *
+ * Time slots must be strictly contiguous, i.e. windows[n].offset +
+ * windows[n].duration shall equal windows[n + 1].offset.  If
+ * windows[].ptid is in the range
  * [0..CONFIG_XENO_OPT_SCHED_TP_NRPART-1], SCHED_TP threads which
- * belong to the partition being referred to may run for the duration
- * of the time window.
- *
- * Time holes may be defined using windows assigned to the pseudo
- * partition #-1, during which no SCHED_TP threads may be scheduled.
+ * belong to the partition being referred to may be given CPU time on
+ * @a cpu, from time windows[].offset to windows[].offset +
+ * windows[].duration, provided those threads are in a runnable state.
  *
- * - config.tp.nr_windows should define the number of elements present
- * in the config.tp.windows[] array.
+ * Time holes between valid time slots may be defined using windows
+ * activating the pseudo partition -1. When such window is active in
+ * the global time frame, no CPU time is available to SCHED_TP threads
+ * on @a cpu.
  *
- * @a info is ignored for this request.
+ * @note The sched_tp_confsz(nr_windows) macro returns the length of
+ * config.tp depending on the number of time slots to be defined in
+ * config.tp.windows[], as specified by config.tp.nr_windows.
  *
  * @par Settings applicable to SCHED_QUOTA
  *
- * This call manages thread groups running on @a cpu.
+ * This call manages thread groups running on @a cpu, defining
+ * per-group quota for limiting their CPU consumption.
  *
  * - config.quota.op should define the operation to be carried
  * out. Valid operations are:


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

Reply via email to