Module: xenomai-forge
Branch: master
Commit: 6d3e789670abd9eec7a6596c94cf9a991434816c
URL:    
http://git.xenomai.org/?p=xenomai-forge.git;a=commit;h=6d3e789670abd9eec7a6596c94cf9a991434816c

Author: Philippe Gerum <r...@xenomai.org>
Date:   Sat Nov 12 12:15:58 2011 +0100

cobalt/nucleus: sanitize RRB implementation

Ticking at each individual base period while we undergo round-robin
scheduling for a thread does not make any sense; all intermediate
ticks are just 100% worthless overhead.

We fix this by assigning an internal timer to each thread dedicated to
round-robin scheduling. The thread's scheduling class still decides
what to do upon expiration of the round-robin quantum, most likely
requeue the target thread at the end of its priority group -- but
something else/additional could be done if need be.

The global time slicing timer disappears, along with the virtual tick
configuration knob. A new XENO_OPT_RR_QUANTUM configuration symbol now
defines the duration of the default time quantum for RRB scheduling.

---

 doc/txt/cobalt-skin.txt          |   10 ---------
 include/cobalt/nucleus/pod.h     |    5 +---
 include/cobalt/nucleus/sched.h   |   13 ++++++-----
 include/cobalt/nucleus/thread.h  |    7 ++---
 kernel/cobalt/module.c           |    6 +----
 kernel/cobalt/nucleus/Kconfig    |   16 ++++++--------
 kernel/cobalt/nucleus/pod.c      |   40 +++++++++----------------------------
 kernel/cobalt/nucleus/sched-rt.c |   17 +++------------
 kernel/cobalt/nucleus/sched.c    |    2 +
 kernel/cobalt/nucleus/thread.c   |   16 ++++++++++++--
 10 files changed, 48 insertions(+), 84 deletions(-)

diff --git a/doc/txt/cobalt-skin.txt b/doc/txt/cobalt-skin.txt
index a4853cb..bf00eb2 100644
--- a/doc/txt/cobalt-skin.txt
+++ b/doc/txt/cobalt-skin.txt
@@ -143,13 +143,3 @@ The Cobalt skin still lacks some features which will be 
added gradually :
 - spinlocks/rwlocks/barriers ;
 - real-time signals in primary mode for user-space threads.
 - dimensioning constants configurable through kernel configuration menu.
-
-
-Module parameters
-=================
-
-The following parameter can be passed at startup to the Cobalt skin
-module:
-
-- "time_slice_arg", duration, as a number of base periods, of the
-  default round-robin time slice. Defaults to 1 period.
diff --git a/include/cobalt/nucleus/pod.h b/include/cobalt/nucleus/pod.h
index 2b55143..a377f85 100644
--- a/include/cobalt/nucleus/pod.h
+++ b/include/cobalt/nucleus/pod.h
@@ -78,10 +78,7 @@ struct xnpod {
         tswitchq,              /*!< Thread switch hook queue. */
         tdeleteq;              /*!< Thread delete hook queue. */
 
-       atomic_counter_t timerlck;      /*!< Timer lock depth.  */
-
-       xntimer_t tslicer;      /*!< Time-slicing timer  */
-       int tsliced;            /*!< Number of threads using the slicer */
+       atomic_counter_t timerlck; /*!< Timer lock depth.  */
 
        int refcnt;             /*!< Reference count.  */
 
diff --git a/include/cobalt/nucleus/sched.h b/include/cobalt/nucleus/sched.h
index fd385a8..8915754 100644
--- a/include/cobalt/nucleus/sched.h
+++ b/include/cobalt/nucleus/sched.h
@@ -115,7 +115,7 @@ struct xnsched_class {
        void (*sched_dequeue)(struct xnthread *thread);
        void (*sched_requeue)(struct xnthread *thread);
        struct xnthread *(*sched_pick)(struct xnsched *sched);
-       void (*sched_tick)(struct xnthread *curr);
+       void (*sched_tick)(struct xnthread *thread);
        void (*sched_rotate)(struct xnsched *sched,
                             const union xnsched_policy_param *p);
        void (*sched_migrate)(struct xnthread *thread,
@@ -329,18 +329,19 @@ static inline struct xnsched_class 
*xnsched_root_class(struct xnsched *sched)
        return sched->rootcb.sched_class;
 }
 
-static inline void xnsched_tick(struct xnthread *curr)
+static inline void xnsched_tick(struct xnthread *thread)
 {
-       struct xnsched_class *sched_class = curr->sched_class;
+       struct xnsched_class *sched_class = thread->sched_class;
        /*
         * A thread that undergoes round-robin scheduling only
         * consumes its time slice when it runs within its own
         * scheduling class, which excludes temporary PIP boosts.
         */
        if (sched_class != &xnsched_class_idle &&
-           sched_class == curr->base_class &&
-           xnthread_test_state(curr, XNTHREAD_BLOCK_BITS|XNLOCK|XNRRB) == 
XNRRB)
-               sched_class->sched_tick(curr);
+           sched_class == thread->base_class &&
+           thread->sched->curr == thread &&
+           xnthread_test_state(thread, XNTHREAD_BLOCK_BITS|XNLOCK|XNRRB) == 
XNRRB)
+               sched_class->sched_tick(thread);
 }
 
 #ifdef CONFIG_XENO_OPT_SCHED_CLASSES
diff --git a/include/cobalt/nucleus/thread.h b/include/cobalt/nucleus/thread.h
index dfa1d74..d2b9ba2 100644
--- a/include/cobalt/nucleus/thread.h
+++ b/include/cobalt/nucleus/thread.h
@@ -250,11 +250,11 @@ typedef struct xnthread {
 
        xntimer_t ptimer;               /* Periodic timer */
 
-       xnsigmask_t signals;            /* Pending core signals */
+       xntimer_t rrbtimer;             /* Round-robin timer */
 
-       xnticks_t rrperiod;             /* Allotted round-robin period (ticks) 
*/
+       xnsigmask_t signals;            /* Pending core signals */
 
-       xnticks_t rrcredit;             /* Remaining round-robin time credit 
(ticks) */
+       xnticks_t rrperiod;             /* Allotted round-robin period (ns) */
 
        struct xnthread_wait_context *wcontext; /* Active wait context. */
 
@@ -341,7 +341,6 @@ typedef struct xnhook {
 #define xnthread_base_class(thread)        ((thread)->base_class)
 #define xnthread_sched_class(thread)       ((thread)->sched_class)
 #define xnthread_time_slice(thread)        ((thread)->rrperiod)
-#define xnthread_time_credit(thread)       ((thread)->rrcredit)
 #define xnthread_archtcb(thread)           (&((thread)->tcb))
 #define xnthread_asr_level(thread)         ((thread)->asrlevel)
 #define xnthread_pending_signals(thread)  ((thread)->signals)
diff --git a/kernel/cobalt/module.c b/kernel/cobalt/module.c
index 82f55c5..2689741 100644
--- a/kernel/cobalt/module.c
+++ b/kernel/cobalt/module.c
@@ -67,10 +67,6 @@ MODULE_DESCRIPTION("POSIX/COBALT interface");
 MODULE_AUTHOR("gilles.chanteperd...@xenomai.org");
 MODULE_LICENSE("GPL");
 
-static u_long time_slice_arg = 1;      /* Default (round-robin) time slice */
-module_param_named(time_slice, time_slice_arg, ulong, 0444);
-MODULE_PARM_DESC(time_slice, "Default time slice (in ticks)");
-
 static void cobalt_shutdown(int xtype)
 {
        cobalt_thread_pkg_cleanup();
@@ -138,7 +134,7 @@ int SKIN_INIT(posix)
        cobalt_shm_pkg_init();
 #endif /* CONFIG_XENO_OPT_POSIX_SHM */
 
-       cobalt_thread_pkg_init(module_param_value(time_slice_arg));
+       cobalt_thread_pkg_init(CONFIG_XENO_OPT_RR_QUANTUM * 1000);
 
        return 0;
 }
diff --git a/kernel/cobalt/nucleus/Kconfig b/kernel/cobalt/nucleus/Kconfig
index 06abce6..9b30f1a 100644
--- a/kernel/cobalt/nucleus/Kconfig
+++ b/kernel/cobalt/nucleus/Kconfig
@@ -82,18 +82,15 @@ config XENO_OPT_SHIRQ
        are allowed to control dedicated hardware devices which are
        configured to share the same interrupt line.
 
-config XENO_OPT_TIMING_VIRTICK
-       int "Virtual tick duration (us)"
+config XENO_OPT_RR_QUANTUM
+       int "Round-robin quantum (us)"
        default 1000
        help
 
-       Time-slicing (aka round-robin scheduling) defines a base
-       period that represents the duration of one tick; threads can
-       then be given a time credit to consume as a count of
-       ticks.
-
-       This parameter defines the duration of the base period
-       expressed as a count of micro-seconds.
+       This parameter defines the duration of the default round-robin
+       time quantum expressed as a count of micro-seconds. This value
+       may be overriden internally by Xenomai services which do
+       provide a round-robin interval.
 
 config XENO_OPT_TIMING_SCHEDLAT
        int "Scheduling latency (ns)"
@@ -248,6 +245,7 @@ config XENO_OPT_SYS_STACKPOOLSZ
        zero value for this option. The size is expressed in Kilobytes.
 
 if !XENO_GENERIC_STACKPOOL
+
 config XENO_OPT_SYS_STACKPOOLSZ
         int
        default 0
diff --git a/kernel/cobalt/nucleus/pod.c b/kernel/cobalt/nucleus/pod.c
index f7420ee..a2f2b28 100644
--- a/kernel/cobalt/nucleus/pod.c
+++ b/kernel/cobalt/nucleus/pod.c
@@ -66,8 +66,6 @@ u_long nktimerlat = 0;
 
 xnarch_cpumask_t nkaffinity = XNPOD_ALL_CPUS;
 
-xnticks_t nkvtick = CONFIG_XENO_OPT_TIMING_VIRTICK * 1000;
-
 #ifdef CONFIG_XENO_OPT_DEBUG
 struct xnvfile_directory debug_vfroot;
 EXPORT_SYMBOL_GPL(debug_vfroot);
@@ -278,11 +276,6 @@ void xnpod_schedule_deferred(void)
                xnpod_schedule();
 }
 
-static void xnpod_timeslice_handler(struct xntimer *timer)
-{
-       xnsched_tick(timer->sched->curr);
-}
-
 static void xnpod_flush_heap(xnheap_t *heap,
                             void *extaddr, u_long extsize, void *cookie)
 {
@@ -352,8 +345,6 @@ int xnpod_init(void)
        initq(&pod->tstartq);
        initq(&pod->tswitchq);
        initq(&pod->tdeleteq);
-       xntimer_init(&pod->tslicer, xnpod_timeslice_handler);
-       pod->tsliced = 0;
        xnarch_atomic_set(&pod->timerlck, 0);
 #ifdef __XENO_SIM__
        pod->schedhook = NULL;
@@ -456,8 +447,6 @@ void xnpod_shutdown(int xtype)
                return; /* No-op */
        }
 
-       xntimer_destroy(&nkpod->tslicer);
-
        /*
         * FIXME: We must release the lock before disabling the time
         * source, so we accept a potential race due to another skin
@@ -1097,6 +1086,7 @@ void xnpod_delete_thread(xnthread_t *thread)
 
        xntimer_destroy(&thread->rtimer);
        xntimer_destroy(&thread->ptimer);
+       xntimer_destroy(&thread->rrbtimer);
 
        if (thread->selector) {
                xnselector_destroy(thread->selector);
@@ -2910,11 +2900,11 @@ EXPORT_SYMBOL_GPL(xnpod_wait_thread_period);
  * @param thread The descriptor address of the affected thread.
  *
  * @param quantum The time quantum assigned to the thread expressed in
- * time-slicing ticks (see note). If @a quantum is different from
- * XN_INFINITE, the time-slice for the thread is set to that value and
- * its current time credit is refilled (i.e. the thread is given a
- * full time-slice to run next). Otherwise, if @a quantum equals
- * XN_INFINITE, time-slicing is stopped for that thread.
+ * nanoseconds. If @a quantum is different from XN_INFINITE, the
+ * time-slice for the thread is set to that value and its current time
+ * credit is refilled (i.e. the thread is given a full time-slice to
+ * run next). Otherwise, if @a quantum equals XN_INFINITE,
+ * time-slicing is stopped for that thread.
  *
  * @return 0 is returned upon success. Otherwise:
  *
@@ -2928,14 +2918,9 @@ EXPORT_SYMBOL_GPL(xnpod_wait_thread_period);
  * - Any kernel context.
  *
  * Rescheduling: never.
- *
- * @note A full time-slice will last: @a quantum *
- * CONFIG_XENO_OPT_TIMING_VIRTICK micro-seconds.
  */
-
 int xnpod_set_thread_tslice(struct xnthread *thread, xnticks_t quantum)
 {
-       unsigned long oldmode;
        spl_t s;
 
        xnlock_get_irqsave(&nklock, s);
@@ -2946,19 +2931,14 @@ int xnpod_set_thread_tslice(struct xnthread *thread, 
xnticks_t quantum)
        }
 
        thread->rrperiod = quantum;
-       thread->rrcredit = quantum;
-       oldmode = xnthread_test_state(thread, XNRRB);
+       xntimer_stop(&thread->rrbtimer);
 
        if (quantum != XN_INFINITE) {
                xnthread_set_state(thread, XNRRB);
-               if (!oldmode && nkpod->tsliced++ == 0)
-                       xntimer_start(&nkpod->tslicer,
-                                     nkvtick, nkvtick, XN_RELATIVE);
-       } else {
+               xntimer_start(&thread->rrbtimer,
+                             quantum, quantum, XN_RELATIVE);
+       } else
                xnthread_clear_state(thread, XNRRB);
-               if (oldmode && --nkpod->tsliced == 0)
-                       xntimer_stop(&nkpod->tslicer);
-       }
 
        xnlock_put_irqrestore(&nklock, s);
 
diff --git a/kernel/cobalt/nucleus/sched-rt.c b/kernel/cobalt/nucleus/sched-rt.c
index 6c111d4..71181b7 100644
--- a/kernel/cobalt/nucleus/sched-rt.c
+++ b/kernel/cobalt/nucleus/sched-rt.c
@@ -98,20 +98,11 @@ void xnsched_rt_tick(struct xnthread *curr)
        /*
         * The round-robin time credit is only consumed by a running
         * thread that neither holds the scheduler lock nor was
-        * blocked before entering this callback.
+        * blocked before entering this callback. As the time slice is
+        * exhausted for the running thread, move it back to the
+        * runnable queue at the end of its priority group.
         */
-       if (likely(curr->rrcredit > 1))
-               --curr->rrcredit;
-       else {
-               /*
-                * If the time slice is exhausted for the running
-                * thread, move it back to the runnable queue at the
-                * end of its priority group and reset its credit for
-                * the next run.
-                */
-               curr->rrcredit = curr->rrperiod;
-               xnsched_putback(curr);
-       }
+       xnsched_putback(curr);
 }
 
 void xnsched_rt_setparam(struct xnthread *thread,
diff --git a/kernel/cobalt/nucleus/sched.c b/kernel/cobalt/nucleus/sched.c
index 0c172e3..4bdfe0b 100644
--- a/kernel/cobalt/nucleus/sched.c
+++ b/kernel/cobalt/nucleus/sched.c
@@ -185,6 +185,7 @@ void xnsched_destroy(struct xnsched *sched)
        xntimer_destroy(&sched->htimer);
        xntimer_destroy(&sched->rootcb.ptimer);
        xntimer_destroy(&sched->rootcb.rtimer);
+       xntimer_destroy(&sched->rootcb.rrbtimer);
 #ifdef CONFIG_XENO_OPT_WATCHDOG
        xntimer_destroy(&sched->wdtimer);
 #endif /* CONFIG_XENO_OPT_WATCHDOG */
@@ -700,6 +701,7 @@ static int vfile_schedlist_next(struct 
xnvfile_snapshot_iterator *it,
        if (period > 0 && period < timeout &&
            !xntimer_running_p(&thread->rtimer))
                timeout = period;
+
        p->timeout = timeout;
 
        return 1;
diff --git a/kernel/cobalt/nucleus/thread.c b/kernel/cobalt/nucleus/thread.c
index f8dcaa7..f9e139f 100644
--- a/kernel/cobalt/nucleus/thread.c
+++ b/kernel/cobalt/nucleus/thread.c
@@ -21,6 +21,7 @@
 #include <nucleus/synch.h>
 #include <nucleus/heap.h>
 #include <nucleus/thread.h>
+#include <nucleus/sched.h>
 #include <nucleus/module.h>
 #include <asm/xenomai/bits/thread.h>
 
@@ -28,14 +29,15 @@ static unsigned idtags;
 
 static void xnthread_timeout_handler(xntimer_t *timer)
 {
-       xnthread_t *thread = container_of(timer, xnthread_t, rtimer);
+       struct xnthread *thread = container_of(timer, xnthread_t, rtimer);
+
        xnthread_set_info(thread, XNTIMEO);     /* Interrupts are off. */
        xnpod_resume_thread(thread, XNDELAY);
 }
 
 static void xnthread_periodic_handler(xntimer_t *timer)
 {
-       xnthread_t *thread = container_of(timer, xnthread_t, ptimer);
+       struct xnthread *thread = container_of(timer, xnthread_t, ptimer);
        /*
         * Prevent unwanted round-robin, and do not wake up threads
         * blocked on a resource.
@@ -44,6 +46,12 @@ static void xnthread_periodic_handler(xntimer_t *timer)
                xnpod_resume_thread(thread, XNDELAY);
 }
 
+static void xnthread_roundrobin_handler(xntimer_t *timer)
+{
+       struct xnthread *thread = container_of(timer, struct xnthread, 
rrbtimer);
+       xnsched_tick(thread);
+}
+
 int xnthread_init(struct xnthread *thread,
                  const struct xnthread_init_attr *attr,
                  struct xnsched *sched,
@@ -110,6 +118,9 @@ int xnthread_init(struct xnthread *thread,
        xntimer_init(&thread->ptimer, xnthread_periodic_handler);
        xntimer_set_name(&thread->ptimer, thread->name);
        xntimer_set_priority(&thread->ptimer, XNTIMER_HIPRIO);
+       xntimer_init(&thread->rrbtimer, xnthread_roundrobin_handler);
+       xntimer_set_name(&thread->rrbtimer, thread->name);
+       xntimer_set_priority(&thread->rrbtimer, XNTIMER_LOPRIO);
 
        thread->state = flags;
        thread->info = 0;
@@ -122,7 +133,6 @@ int xnthread_init(struct xnthread *thread,
 
        thread->ops = attr->ops;
        thread->rrperiod = XN_INFINITE;
-       thread->rrcredit = XN_INFINITE;
        thread->wchan = NULL;
        thread->wwake = NULL;
        thread->wcontext = NULL;


_______________________________________________
Xenomai-git mailing list
Xenomai-git@gna.org
https://mail.gna.org/listinfo/xenomai-git

Reply via email to