Enhanced xnthread & native task stats
PATCH 1/3 Enhanced xnthread & native task stats
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(-)
include/native/task.h +15 -4
@@ -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
include/nucleus/stat.h +11 -1
@@ -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 {
include/nucleus/thread.h +4 -3
@@ -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)
ksrc/nucleus/module.c +5 -4
@@ -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);
ksrc/nucleus/pod.c +3 -3
@@ -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:
ksrc/nucleus/thread.c +0 -1
@@ -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);
ksrc/skins/native/task.c +9 -0
@@ -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: