All of lore.kernel.org
 help / color / mirror / Atom feed
* [Xenomai-core] [PATCH] Refactor nucleus timer IRQ path
@ 2007-05-20 11:28 Jan Kiszka
  2007-05-20 13:37 ` Philippe Gerum
  0 siblings, 1 reply; 2+ messages in thread
From: Jan Kiszka @ 2007-05-20 11:28 UTC (permalink / raw)
  To: xenomai-core

[-- Attachment #1: Type: text/plain, Size: 8304 bytes --]

The timer IRQ currently goes through a dedicated trampoline
(xnintr_clock_handler), the generic xnintr_irq_handler which handles it
via a special nkclock xnintr_t object, then xnpod_announce_tick, until
it finally ends in xntimer_tick_aperiodic.

This patch refactors this path so that we now have only a specialised
xnintr_clock_handler which incorporates all previously scattered steps.
Furthermore, tick-specific handling is removed from xnintr_irq_handler
and nkclock is now only required when statistic are generated. This
refactoring results in a tiny, but measurable performance gain on i386,
other archs with small caches may benefit more significantly.

[Note that the patch also contains some LTT-related changes around the
tick IRQ. They only serve as a reminder, the final LTTng marker
format and the probe modules will look differently.]

Jan


---
 include/nucleus/pod.h   |    2 -
 ksrc/nucleus/intr.c     |   51 +++++++++++++++++++++++++++++++----------
 ksrc/nucleus/ltt.c      |    4 +--
 ksrc/nucleus/pod.c      |   59 ++++--------------------------------------------
 ksrc/nucleus/timebase.c |    3 ++
 5 files changed, 50 insertions(+), 69 deletions(-)

Index: xenomai/ksrc/nucleus/intr.c
===================================================================
--- xenomai.orig/ksrc/nucleus/intr.c
+++ xenomai/ksrc/nucleus/intr.c
@@ -41,9 +41,8 @@
 
 DEFINE_PRIVATE_XNLOCK(intrlock);
 
-xnintr_t nkclock;
-
 #ifdef CONFIG_XENO_OPT_STATS
+xnintr_t nkclock;	/* Only for statistics */
 int xnintr_count = 1;	/* Number of attached xnintr objects + nkclock */
 int xnintr_list_rev;	/* Modification counter of xnintr list */
 
@@ -113,6 +112,42 @@ static void xnintr_irq_handler(unsigned 
 	if (--sched->inesting == 0 && xnsched_resched_p())
 		xnpod_schedule();
 
+	xnltt_log_event(xeno_ev_iexit, irq);
+	xnstat_runtime_switch(sched, prev);
+}
+
+/* Low-level clock irq handler. */
+
+void xnintr_clock_handler(void)
+{
+	xnsched_t *sched = xnpod_current_sched();
+	xnstat_runtime_t *prev;
+	xnticks_t start;
+
+	xnarch_memory_barrier();
+
+	prev  = xnstat_runtime_get_current(sched);
+	start = xnstat_runtime_now();
+
+	xnarch_announce_tick();
+
+	xnltt_log_event(xeno_ev_ienter, XNARCH_TIMER_IRQ);
+	xnltt_log_event(xeno_ev_tstick, nktbase.name,
+			xnpod_current_thread()->name);
+
+	++sched->inesting;
+
+	xnlock_get(&nklock);
+	xntimer_tick_aperiodic();
+	xnlock_put(&nklock);
+
+	xnstat_counter_inc(&nkclock.stat[xnsched_cpu(sched)].hits);
+	xnstat_runtime_lazy_switch(sched,
+		&nkclock.stat[xnsched_cpu(sched)].account, start);
+
+	if (--sched->inesting == 0 && xnsched_resched_p())
+		xnpod_schedule();
+
 	/* Since the host tick is low priority, we can wait for returning
 	   from the rescheduling procedure before actually calling the
 	   propagation service, if it is pending. */
@@ -122,18 +157,10 @@ static void xnintr_irq_handler(unsigned 
 		xnarch_relay_tick();
 	}
 
-	xnltt_log_event(xeno_ev_iexit, irq);
+	xnltt_log_event(xeno_ev_iexit, XNARCH_TIMER_IRQ);
 	xnstat_runtime_switch(sched, prev);
 }
 
-/* Low-level clock irq handler. */
-
-void xnintr_clock_handler(void)
-{
-	xnarch_announce_tick();
-	xnintr_irq_handler(nkclock.irq, &nkclock);
-}
-
 /* Optional support for shared interrupts. */
 
 #if defined(CONFIG_XENO_OPT_SHIRQ_LEVEL) || defined(CONFIG_XENO_OPT_SHIRQ_EDGE)
@@ -809,7 +836,7 @@ int xnintr_irq_proc(unsigned int irq, ch
 		p += sprintf(p, "         [virtual]");
 		return p - str;
 	} else if (irq == XNARCH_TIMER_IRQ) {
-		p += sprintf(p, "         %s", nkclock.name);
+		p += sprintf(p, "         [timer]");
 		return p - str;
 	}
 
Index: xenomai/include/nucleus/pod.h
===================================================================
--- xenomai.orig/include/nucleus/pod.h
+++ xenomai/include/nucleus/pod.h
@@ -438,8 +438,6 @@ static inline void xnpod_unlock_sched(vo
 	xnlock_put_irqrestore(&nklock, s);
 }
 
-int xnpod_announce_tick(struct xnintr *intr);
-
 void xnpod_activate_rr(xnticks_t quantum);
 
 void xnpod_deactivate_rr(void);
Index: xenomai/ksrc/nucleus/pod.c
===================================================================
--- xenomai.orig/ksrc/nucleus/pod.c
+++ xenomai/ksrc/nucleus/pod.c
@@ -3004,12 +3004,11 @@ int xnpod_enable_timesource(void)
 
 	xnltt_log_event(xeno_ev_tsenable);
 
-	/* The clock interrupt does not need to be attached since the
-	   timer service will handle the arch-dependent setup. The IRQ
-	   source will be attached directly by the arch-dependent layer
-	   (xnarch_start_timer). */
-
-	xnintr_init(&nkclock, "[timer]", XNARCH_TIMER_IRQ, &xnpod_announce_tick, NULL, 0);
+#ifdef CONFIG_XENO_OPT_STATS
+	/* Only for statistical purpose, the clock interrupt will be attached
+	   directly by the arch-dependent layer (xnarch_start_timer). */
+	xnintr_init(&nkclock, "[timer]", XNARCH_TIMER_IRQ, NULL, NULL, 0);
+#endif /* CONFIG_XENO_OPT_STATS */
 
 	nktbase.status = XNTBRUN;
 
@@ -3109,51 +3108,7 @@ void xnpod_disable_timesource(void)
 	   resource is associated with this object. */
 }
 
-/*! 
- * \fn int xnpod_announce_tick(xnintr_t *intr)
- *
- * \brief Announce a new clock tick.
- *
- * This is the default service routine for clock ticks which performs
- * the necessary housekeeping chores for time-related services managed
- * by the nucleus. In a way or another, this routine must be called
- * to announce each incoming clock tick to the nucleus.
- *
- * @param intr The descriptor address of the interrupt object
- * associated to the timer interrupt.
- *
- * Side-effect: Since this routine manages the round-robin scheduling,
- * the running thread (which has been preempted by the timer
- * interrupt) can be switched out as a result of its time credit being
- * exhausted. The nucleus always calls the rescheduling procedure
- * after the outer interrupt has been processed.
- *
- * @return XN_ISR_HANDLED|XN_ISR_NOENABLE is always returned.
- *
- * Environments:
- *
- * This service can be called from:
- *
- * - Interrupt service routine, must be called with interrupts off.
- *
- * Rescheduling: possible.
- *
- */
-
-int xnpod_announce_tick(xnintr_t *intr)
-{
-	xnlock_get(&nklock);
-
-	xnltt_log_event(xeno_ev_tstick, xnpod_current_thread()->name);
-
-	xntimer_tick_aperiodic(); /* Update the master time base. */
-
-	xnlock_put(&nklock);
-
-	return XN_ISR_HANDLED | XN_ISR_NOENABLE;
-}
-
-/*! 
+/*!
  * \fn int xnpod_set_thread_periodic(xnthread_t *thread,xnticks_t idate,xnticks_t period)
  * \brief Make a thread periodic.
  *
@@ -3368,7 +3323,6 @@ int xnpod_wait_thread_period(unsigned lo
 
 EXPORT_SYMBOL(xnpod_activate_rr);
 EXPORT_SYMBOL(xnpod_add_hook);
-EXPORT_SYMBOL(xnpod_announce_tick);
 EXPORT_SYMBOL(xnpod_check_context);
 EXPORT_SYMBOL(xnpod_deactivate_rr);
 EXPORT_SYMBOL(xnpod_delete_thread);
@@ -3395,7 +3349,6 @@ EXPORT_SYMBOL(xnpod_unblock_thread);
 EXPORT_SYMBOL(xnpod_wait_thread_period);
 EXPORT_SYMBOL(xnpod_welcome_thread);
 
-EXPORT_SYMBOL(nkclock);
 EXPORT_SYMBOL(nkpod);
 
 #ifdef CONFIG_SMP
Index: xenomai/ksrc/nucleus/ltt.c
===================================================================
--- xenomai.orig/ksrc/nucleus/ltt.c
+++ xenomai/ksrc/nucleus/ltt.c
@@ -123,8 +123,8 @@ struct xnltt_evmap xnltt_evtable[] = {
 	    {"Xenomai sigdispatch", "thread=%s, sigpend=0x%x", -1, xeno_evall},
 	[xeno_ev_thrboot] =
 	    {"Xenomai thread begin", "thread=%s", -1, xeno_evthr},
-	[xeno_ev_tstick] =
-	    {"Xenomai time source tick", "runthread=%s", -1, xeno_evirq},
+	[xeno_ev_tstick] = {"Xenomai time source tick",
+			    "base=%s, runthread=%s", -1, xeno_evirq},
 	[xeno_ev_sleepon] =
 	    {"Xenomai sleepon", "thread=%s, sync=%p", -1, xeno_evthr},
 	[xeno_ev_wakeup1] =
Index: xenomai/ksrc/nucleus/timebase.c
===================================================================
--- xenomai.orig/ksrc/nucleus/timebase.c
+++ xenomai/ksrc/nucleus/timebase.c
@@ -433,6 +433,9 @@ void xntbase_tick(xntbase_t *base)
 
 	xnlock_get_irqsave(&nklock, s);
 
+	xnltt_log_event(xeno_ev_tstick, base->name,
+			xnpod_current_thread()->name);
+
 	if (base == &nktbase)
 		xntimer_tick_aperiodic();
 	else {


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 249 bytes --]

^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: [Xenomai-core] [PATCH] Refactor nucleus timer IRQ path
  2007-05-20 11:28 [Xenomai-core] [PATCH] Refactor nucleus timer IRQ path Jan Kiszka
@ 2007-05-20 13:37 ` Philippe Gerum
  0 siblings, 0 replies; 2+ messages in thread
From: Philippe Gerum @ 2007-05-20 13:37 UTC (permalink / raw)
  To: Jan Kiszka; +Cc: xenomai-core

On Sun, 2007-05-20 at 13:28 +0200, Jan Kiszka wrote:
> The timer IRQ currently goes through a dedicated trampoline
> (xnintr_clock_handler), the generic xnintr_irq_handler which handles it
> via a special nkclock xnintr_t object, then xnpod_announce_tick, until
> it finally ends in xntimer_tick_aperiodic.
> 
> This patch refactors this path so that we now have only a specialised
> xnintr_clock_handler which incorporates all previously scattered steps.
> Furthermore, tick-specific handling is removed from xnintr_irq_handler
> and nkclock is now only required when statistic are generated. This
> refactoring results in a tiny, but measurable performance gain on i386,
> other archs with small caches may benefit more significantly.
> 

Ok, I like this, primarily because aside of saving a few cycles by being
I-cache friendly, it does express the fact that there is something
special about the timer interrupt, and conversely that not every IRQ
source might fit as a time source, e.g. wrt host tick relay and such.

I'm going to queue this for a later merge (before -rc1 though); please
people give this hell during this grace period.

> [Note that the patch also contains some LTT-related changes around the
> tick IRQ. They only serve as a reminder, the final LTTng marker
> format and the probe modules will look differently.]
> 
> Jan
> 
> 
> ---
>  include/nucleus/pod.h   |    2 -
>  ksrc/nucleus/intr.c     |   51 +++++++++++++++++++++++++++++++----------
>  ksrc/nucleus/ltt.c      |    4 +--
>  ksrc/nucleus/pod.c      |   59 ++++--------------------------------------------
>  ksrc/nucleus/timebase.c |    3 ++
>  5 files changed, 50 insertions(+), 69 deletions(-)
> 
> Index: xenomai/ksrc/nucleus/intr.c
> ===================================================================
> --- xenomai.orig/ksrc/nucleus/intr.c
> +++ xenomai/ksrc/nucleus/intr.c
> @@ -41,9 +41,8 @@
>  
>  DEFINE_PRIVATE_XNLOCK(intrlock);
>  
> -xnintr_t nkclock;
> -
>  #ifdef CONFIG_XENO_OPT_STATS
> +xnintr_t nkclock;	/* Only for statistics */
>  int xnintr_count = 1;	/* Number of attached xnintr objects + nkclock */
>  int xnintr_list_rev;	/* Modification counter of xnintr list */
>  
> @@ -113,6 +112,42 @@ static void xnintr_irq_handler(unsigned 
>  	if (--sched->inesting == 0 && xnsched_resched_p())
>  		xnpod_schedule();
>  
> +	xnltt_log_event(xeno_ev_iexit, irq);
> +	xnstat_runtime_switch(sched, prev);
> +}
> +
> +/* Low-level clock irq handler. */
> +
> +void xnintr_clock_handler(void)
> +{
> +	xnsched_t *sched = xnpod_current_sched();
> +	xnstat_runtime_t *prev;
> +	xnticks_t start;
> +
> +	xnarch_memory_barrier();
> +
> +	prev  = xnstat_runtime_get_current(sched);
> +	start = xnstat_runtime_now();
> +
> +	xnarch_announce_tick();
> +
> +	xnltt_log_event(xeno_ev_ienter, XNARCH_TIMER_IRQ);
> +	xnltt_log_event(xeno_ev_tstick, nktbase.name,
> +			xnpod_current_thread()->name);
> +
> +	++sched->inesting;
> +
> +	xnlock_get(&nklock);
> +	xntimer_tick_aperiodic();
> +	xnlock_put(&nklock);
> +
> +	xnstat_counter_inc(&nkclock.stat[xnsched_cpu(sched)].hits);
> +	xnstat_runtime_lazy_switch(sched,
> +		&nkclock.stat[xnsched_cpu(sched)].account, start);
> +
> +	if (--sched->inesting == 0 && xnsched_resched_p())
> +		xnpod_schedule();
> +
>  	/* Since the host tick is low priority, we can wait for returning
>  	   from the rescheduling procedure before actually calling the
>  	   propagation service, if it is pending. */
> @@ -122,18 +157,10 @@ static void xnintr_irq_handler(unsigned 
>  		xnarch_relay_tick();
>  	}
>  
> -	xnltt_log_event(xeno_ev_iexit, irq);
> +	xnltt_log_event(xeno_ev_iexit, XNARCH_TIMER_IRQ);
>  	xnstat_runtime_switch(sched, prev);
>  }
>  
> -/* Low-level clock irq handler. */
> -
> -void xnintr_clock_handler(void)
> -{
> -	xnarch_announce_tick();
> -	xnintr_irq_handler(nkclock.irq, &nkclock);
> -}
> -
>  /* Optional support for shared interrupts. */
>  
>  #if defined(CONFIG_XENO_OPT_SHIRQ_LEVEL) || defined(CONFIG_XENO_OPT_SHIRQ_EDGE)
> @@ -809,7 +836,7 @@ int xnintr_irq_proc(unsigned int irq, ch
>  		p += sprintf(p, "         [virtual]");
>  		return p - str;
>  	} else if (irq == XNARCH_TIMER_IRQ) {
> -		p += sprintf(p, "         %s", nkclock.name);
> +		p += sprintf(p, "         [timer]");
>  		return p - str;
>  	}
>  
> Index: xenomai/include/nucleus/pod.h
> ===================================================================
> --- xenomai.orig/include/nucleus/pod.h
> +++ xenomai/include/nucleus/pod.h
> @@ -438,8 +438,6 @@ static inline void xnpod_unlock_sched(vo
>  	xnlock_put_irqrestore(&nklock, s);
>  }
>  
> -int xnpod_announce_tick(struct xnintr *intr);
> -
>  void xnpod_activate_rr(xnticks_t quantum);
>  
>  void xnpod_deactivate_rr(void);
> Index: xenomai/ksrc/nucleus/pod.c
> ===================================================================
> --- xenomai.orig/ksrc/nucleus/pod.c
> +++ xenomai/ksrc/nucleus/pod.c
> @@ -3004,12 +3004,11 @@ int xnpod_enable_timesource(void)
>  
>  	xnltt_log_event(xeno_ev_tsenable);
>  
> -	/* The clock interrupt does not need to be attached since the
> -	   timer service will handle the arch-dependent setup. The IRQ
> -	   source will be attached directly by the arch-dependent layer
> -	   (xnarch_start_timer). */
> -
> -	xnintr_init(&nkclock, "[timer]", XNARCH_TIMER_IRQ, &xnpod_announce_tick, NULL, 0);
> +#ifdef CONFIG_XENO_OPT_STATS
> +	/* Only for statistical purpose, the clock interrupt will be attached
> +	   directly by the arch-dependent layer (xnarch_start_timer). */
> +	xnintr_init(&nkclock, "[timer]", XNARCH_TIMER_IRQ, NULL, NULL, 0);
> +#endif /* CONFIG_XENO_OPT_STATS */
>  
>  	nktbase.status = XNTBRUN;
>  
> @@ -3109,51 +3108,7 @@ void xnpod_disable_timesource(void)
>  	   resource is associated with this object. */
>  }
>  
> -/*! 
> - * \fn int xnpod_announce_tick(xnintr_t *intr)
> - *
> - * \brief Announce a new clock tick.
> - *
> - * This is the default service routine for clock ticks which performs
> - * the necessary housekeeping chores for time-related services managed
> - * by the nucleus. In a way or another, this routine must be called
> - * to announce each incoming clock tick to the nucleus.
> - *
> - * @param intr The descriptor address of the interrupt object
> - * associated to the timer interrupt.
> - *
> - * Side-effect: Since this routine manages the round-robin scheduling,
> - * the running thread (which has been preempted by the timer
> - * interrupt) can be switched out as a result of its time credit being
> - * exhausted. The nucleus always calls the rescheduling procedure
> - * after the outer interrupt has been processed.
> - *
> - * @return XN_ISR_HANDLED|XN_ISR_NOENABLE is always returned.
> - *
> - * Environments:
> - *
> - * This service can be called from:
> - *
> - * - Interrupt service routine, must be called with interrupts off.
> - *
> - * Rescheduling: possible.
> - *
> - */
> -
> -int xnpod_announce_tick(xnintr_t *intr)
> -{
> -	xnlock_get(&nklock);
> -
> -	xnltt_log_event(xeno_ev_tstick, xnpod_current_thread()->name);
> -
> -	xntimer_tick_aperiodic(); /* Update the master time base. */
> -
> -	xnlock_put(&nklock);
> -
> -	return XN_ISR_HANDLED | XN_ISR_NOENABLE;
> -}
> -
> -/*! 
> +/*!
>   * \fn int xnpod_set_thread_periodic(xnthread_t *thread,xnticks_t idate,xnticks_t period)
>   * \brief Make a thread periodic.
>   *
> @@ -3368,7 +3323,6 @@ int xnpod_wait_thread_period(unsigned lo
>  
>  EXPORT_SYMBOL(xnpod_activate_rr);
>  EXPORT_SYMBOL(xnpod_add_hook);
> -EXPORT_SYMBOL(xnpod_announce_tick);
>  EXPORT_SYMBOL(xnpod_check_context);
>  EXPORT_SYMBOL(xnpod_deactivate_rr);
>  EXPORT_SYMBOL(xnpod_delete_thread);
> @@ -3395,7 +3349,6 @@ EXPORT_SYMBOL(xnpod_unblock_thread);
>  EXPORT_SYMBOL(xnpod_wait_thread_period);
>  EXPORT_SYMBOL(xnpod_welcome_thread);
>  
> -EXPORT_SYMBOL(nkclock);
>  EXPORT_SYMBOL(nkpod);
>  
>  #ifdef CONFIG_SMP
> Index: xenomai/ksrc/nucleus/ltt.c
> ===================================================================
> --- xenomai.orig/ksrc/nucleus/ltt.c
> +++ xenomai/ksrc/nucleus/ltt.c
> @@ -123,8 +123,8 @@ struct xnltt_evmap xnltt_evtable[] = {
>  	    {"Xenomai sigdispatch", "thread=%s, sigpend=0x%x", -1, xeno_evall},
>  	[xeno_ev_thrboot] =
>  	    {"Xenomai thread begin", "thread=%s", -1, xeno_evthr},
> -	[xeno_ev_tstick] =
> -	    {"Xenomai time source tick", "runthread=%s", -1, xeno_evirq},
> +	[xeno_ev_tstick] = {"Xenomai time source tick",
> +			    "base=%s, runthread=%s", -1, xeno_evirq},
>  	[xeno_ev_sleepon] =
>  	    {"Xenomai sleepon", "thread=%s, sync=%p", -1, xeno_evthr},
>  	[xeno_ev_wakeup1] =
> Index: xenomai/ksrc/nucleus/timebase.c
> ===================================================================
> --- xenomai.orig/ksrc/nucleus/timebase.c
> +++ xenomai/ksrc/nucleus/timebase.c
> @@ -433,6 +433,9 @@ void xntbase_tick(xntbase_t *base)
>  
>  	xnlock_get_irqsave(&nklock, s);
>  
> +	xnltt_log_event(xeno_ev_tstick, base->name,
> +			xnpod_current_thread()->name);
> +
>  	if (base == &nktbase)
>  		xntimer_tick_aperiodic();
>  	else {
> 
-- 
Philippe.




^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2007-05-20 13:37 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-05-20 11:28 [Xenomai-core] [PATCH] Refactor nucleus timer IRQ path Jan Kiszka
2007-05-20 13:37 ` Philippe Gerum

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.