Basically, this patch enhances the statistics one can obtain via
rt_task_inquire. It adds the task's

 - accumulated execution time
 - context switches
 - mode switches
 - page faults

to RT_TASK_INFO. To provide this data, our existing exectime stats had
to be extended so that the collected data no longer gets reset upon dump
of /proc/xenomai/stat. At this change, the patch also removes the unused
xnthread::stime.

Credits go to Daniel Simon for writing the initial version and
contributing to the succeeding revisions I made.

Jan

PS: Patches and Changelog fragments can also be found at the usual
place: http://www.rts.uni-hannover.de/rtaddon/patches/xenomai
---
 include/native/task.h    |   19 +++++++++++++++----
 include/nucleus/stat.h   |   12 +++++++++++-
 include/nucleus/thread.h |    7 ++++---
 ksrc/nucleus/module.c    |    9 +++++----
 ksrc/nucleus/pod.c       |    6 +++---
 ksrc/nucleus/thread.c    |    1 -
 ksrc/skins/native/task.c |    9 +++++++++
 7 files changed, 47 insertions(+), 16 deletions(-)

Index: xenomai/include/native/task.h
===================================================================
--- xenomai.orig/include/native/task.h
+++ xenomai/include/native/task.h
@@ -77,19 +77,30 @@ struct rt_task;
 /** Structure containing task-information useful to users.
  *
  *  @see rt_task_inquire()
+ *
+ *  @note Marked (*) fields will be set to 0 by rt_task_inquire() if
+ *  statistics support is disabled in the nucleus.
  */
 typedef struct rt_task_info {
-    
+
     int bprio;  /**< Base priority. */
 
     int cprio; /**< Current priority. May change through Priority Inheritance.*/
-    
+
     unsigned status; /**< Task's status. @see native_task_status */ 
-    
+
     RTIME relpoint; /**< Time of next release.*/ 
-    
+
     char name[XNOBJECT_NAME_LEN];  /**< Symbolic name assigned at creation. */
 
+    RTIME exectime; /**< Execution time in primary mode in nanoseconds (*). */
+
+    int modeswitches; /**< Number of primary->secondary mode switches (*). */
+
+    int ctxswitches; /**< Number of context switches (*). */
+
+    int pagefaults; /**< Number of triggered page faults (*). */
+
 } RT_TASK_INFO;
 
 #define RT_MCB_FSTORE_LIMIT  64
Index: xenomai/include/nucleus/stat.h
===================================================================
--- xenomai.orig/include/nucleus/stat.h
+++ xenomai/include/nucleus/stat.h
@@ -67,6 +67,13 @@ do { \
 	(sched)->current_account = (new_account); \
 } while (0)
 
+/* Obtain content of xnstat_runtime_t */
+#define xnstat_runtime_get_start(account)	((account)->start)
+#define xnstat_runtime_get_total(account)	((account)->total)
+
+/* Obtain last account switch date of considered sched */
+#define xnstat_runtime_get_last_switch(sched)	((sched)->last_account_switch)
+
 /* Reset statistics from inside the accounted entity (e.g. after CPU
    migration). */
 #define xnstat_runtime_reset_stats(stat) \
@@ -104,9 +111,12 @@ typedef struct xnstat_runtime {
 
 #define xnstat_runtime_now()					({ 0; })
 #define xnstat_runtime_update(sched, date)			do { } while (0)
-#define xnstat_runtime_set_current(sched, new_account)	({ (void)sched; NULL; })
+#define xnstat_runtime_set_current(sched, new_account)		({ (void)sched; NULL; })
 #define xnstat_runtime_get_current(sched)			({ (void)sched; NULL; })
 #define xnstat_runtime_finalize(sched, new_account)		do { } while (0)
+#define xnstat_runtime_get_start(account)			({ 0; })
+#define xnstat_runtime_get_total(account)			({ 0; })
+#define xnstat_runtime_get_last_switch(sched)			({ 0; })
 #define xnstat_runtime_reset_stats(account)			do { } while (0)
 
 typedef struct xnstat_counter {
Index: xenomai/include/nucleus/thread.h
===================================================================
--- xenomai.orig/include/nucleus/thread.h
+++ xenomai/include/nucleus/thread.h
@@ -205,7 +205,8 @@ typedef struct xnthread {
 	xnstat_counter_t ssw;	/* Primary -> secondary mode switch count */
 	xnstat_counter_t csw;	/* Context switches (includes secondary -> primary switches) */
 	xnstat_counter_t pf;	/* Number of page faults */
-	xnstat_runtime_t account; /* Runtime accounting entity */
+	xnstat_runtime_t account; /* Execution time accounting entity */
+	xnstat_runtime_t lastperiod; /* Interval marker for execution time reports */
     } stat;
 
     int errcode;		/* Local errno */
@@ -235,8 +236,6 @@ typedef struct xnthread {
 
     char name[XNOBJECT_NAME_LEN]; /* Symbolic name of thread */
 
-    xnticks_t stime;		/* Start time */
-
     void (*entry)(void *cookie); /* Thread entry routine */
 
     void *cookie;		/* Cookie to pass to the entry routine */
@@ -294,6 +293,8 @@ typedef struct xnhook {
     0 : xnarch_user_pid(xnthread_archtcb(thread)))
 #define xnthread_affinity(thread)          ((thread)->affinity)
 #define xnthread_affine_p(thread, cpu)     xnarch_cpu_isset(cpu, (thread)->affinity)
+#define xnthread_get_exectime(thread)      xnstat_runtime_get_total(&(thread)->stat.account)
+#define xnthread_get_lastswitch(thread)    xnstat_runtime_get_last_switch((thread)->sched)
 
 /* Class-level operations for threads. */
 static inline int xnthread_get_denormalized_prio(xnthread_t *t)
Index: xenomai/ksrc/nucleus/module.c
===================================================================
--- xenomai.orig/ksrc/nucleus/module.c
+++ xenomai/ksrc/nucleus/module.c
@@ -421,16 +421,17 @@ static int stat_seq_open(struct inode *i
 		stat_info->csw = xnstat_counter_get(&thread->stat.csw);
 		stat_info->pf = xnstat_counter_get(&thread->stat.pf);
 
-		period = sched->last_account_switch - thread->stat.account.start;
+		period = sched->last_account_switch - thread->stat.lastperiod.start;
 		if (!period && thread == sched->runthread) {
 			stat_info->runtime = 1;
 			stat_info->account_period = 1;
 		} else {
-			stat_info->runtime = thread->stat.account.total;
+			stat_info->runtime = thread->stat.account.total -
+				thread->stat.lastperiod.total;
 			stat_info->account_period = period;
 		}
-		thread->stat.account.total = 0;
-		thread->stat.account.start = sched->last_account_switch;
+		thread->stat.lastperiod.total = thread->stat.account.total;
+		thread->stat.lastperiod.start = sched->last_account_switch;
 
 		holder = nextq(&nkpod->threadq, holder);
 
Index: xenomai/ksrc/nucleus/pod.c
===================================================================
--- xenomai.orig/ksrc/nucleus/pod.c
+++ xenomai/ksrc/nucleus/pod.c
@@ -832,7 +832,6 @@ int xnpod_start_thread(xnthread_t *threa
 	thread->imode = (mode & XNTHREAD_MODE_BITS);
 	thread->entry = entry;
 	thread->cookie = cookie;
-	thread->stime = xnarch_get_cpu_time();
 
 	if (xnthread_test_state(thread, XNRRB))
 		thread->rrcredit = thread->rrperiod;
@@ -1781,8 +1780,9 @@ int xnpod_migrate_thread(int cpu)
 
 	xnpod_schedule();
 
-	/* Reset execution time stats due to unsync'ed TSCs */
-	xnstat_runtime_reset_stats(&thread->stat.account);
+	/* Reset execution time measurement period so that we don't mess up
+	   per-CPU statistics. */
+	xnstat_runtime_reset_stats(&thread->stat.lastperiod);
 
       unlock_and_exit:
 
Index: xenomai/ksrc/nucleus/thread.c
===================================================================
--- xenomai.orig/ksrc/nucleus/thread.c
+++ xenomai/ksrc/nucleus/thread.c
@@ -103,7 +103,6 @@ int xnthread_init(xnthread_t *thread,
 	thread->imode = 0;
 	thread->entry = NULL;
 	thread->cookie = 0;
-	thread->stime = 0;
 	thread->ops = ops;
 
 	inith(&thread->glink);
Index: xenomai/ksrc/skins/native/task.c
===================================================================
--- xenomai.orig/ksrc/skins/native/task.c
+++ xenomai/ksrc/skins/native/task.c
@@ -1121,6 +1121,7 @@ int rt_task_unblock(RT_TASK *task)
 int rt_task_inquire(RT_TASK *task, RT_TASK_INFO *info)
 {
 	int err = 0;
+	xnticks_t raw_exectime;
 	spl_t s;
 
 	if (!task) {
@@ -1144,6 +1145,14 @@ int rt_task_inquire(RT_TASK *task, RT_TA
 	info->cprio = xnthread_current_priority(&task->thread_base);
 	info->status = xnthread_state_flags(&task->thread_base);
 	info->relpoint = xntimer_get_date(&task->thread_base.ptimer);
+	raw_exectime = xnthread_get_exectime(&task->thread_base);
+	if (task->thread_base.sched->runthread == &task->thread_base)
+		raw_exectime += xnstat_runtime_now() -
+			xnthread_get_lastswitch(&task->thread_base);
+	info->exectime = xnarch_tsc_to_ns(raw_exectime);
+	info->modeswitches = xnstat_counter_get(&task->thread_base.stat.ssw);
+	info->ctxswitches = xnstat_counter_get(&task->thread_base.stat.csw);
+	info->pagefaults = xnstat_counter_get(&task->thread_base.stat.pf);
 
       unlock_and_exit:
 

Attachment: signature.asc
Description: OpenPGP digital signature

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

Reply via email to