Module: xenomai-forge Branch: master Commit: 6d3e789670abd9eec7a6596c94cf9a991434816c URL: http://git.xenomai.org/?p=xenomai-forge.git;a=commit;h=6d3e789670abd9eec7a6596c94cf9a991434816c
Author: Philippe Gerum <[email protected]> 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("[email protected]"); 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 [email protected] https://mail.gna.org/listinfo/xenomai-git
