[Xenomai-core] [PATCH] Refactor nucleus timer IRQ path

2007-05-20 Thread Jan Kiszka
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 

Re: [Xenomai-core] [PATCH] Refactor nucleus timer IRQ path

2007-05-20 Thread Philippe Gerum
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
 @@