Jan Kiszka wrote: > Here is such a patch + a reworked version of the exec-time stats. Compiles > and boots, > doesn't cause obvious troubles when running in a loop while threads are > created and > destroyed in parallel. Nevertheless, a quick hack which may contain bugs.
As expected, there were bugs. This version of the exec-time patch always uses TSC for timestamping and the related correct conversion function. And it doesn't try to update the exec-time across CPUs as the TSCs may not be in sync. Thus, when there is no scheduling activity on some CPU, we may not see progress in /stat. But this is the least invasive way, and we typically DO have activity anyway. Jan --- include/nucleus/pod.h | 28 ++++++++++++++++++++++++++++ include/nucleus/thread.h | 1 + ksrc/nucleus/module.c | 20 ++++++++++++++++---- ksrc/nucleus/pod.c | 5 +++++ ksrc/nucleus/thread.c | 1 + 5 files changed, 51 insertions(+), 4 deletions(-) Index: include/nucleus/thread.h =================================================================== --- include/nucleus/thread.h.orig +++ include/nucleus/thread.h @@ -152,6 +152,7 @@ typedef struct xnthread { unsigned long csw; /* Context switches (includes secondary -> primary switches) */ unsigned long pf; /* Number of page faults */ + xnticks_t exec_time; /* Accumulated execution time (ticks) */ } stat; #endif /* CONFIG_XENO_OPT_STATS */ Index: include/nucleus/pod.h =================================================================== --- include/nucleus/pod.h.orig +++ include/nucleus/pod.h @@ -145,6 +145,10 @@ typedef struct xnsched { xnthread_t rootcb; /*!< Root thread control block. */ +#ifdef CONFIG_XENO_OPT_STATS + xnticks_t last_csw; /*!< Last context switch (ticks). */ +#endif /* CONFIG_XENO_OPT_STATS */ + } xnsched_t; #ifdef CONFIG_SMP @@ -545,6 +549,30 @@ static inline void xnpod_delete_self (vo xnpod_delete_thread(xnpod_current_thread()); } +#ifdef CONFIG_XENO_OPT_STATS +static inline void xnpod_acc_exec_time(xnthread_t *thread) +{ + xnsched_t *sched = thread->sched; + xnticks_t now = xnarch_get_cpu_tsc(); + + thread->stat.exec_time += now - sched->last_csw; + sched->last_csw = now; +} + +static inline void xnpod_update_csw_date(xnsched_t *sched) +{ + sched->last_csw = xnarch_get_cpu_tsc(); +} +#else /* !CONFIG_XENO_OPT_STATS */ +static inline void xnpod_acc_exec_time(xnthread_t *thread) +{ +} + +static inline void xnpod_update_csw_date(xnsched_t *sched) +{ +} +#endif /* CONFIG_XENO_OPT_STATS */ + #ifdef __cplusplus } #endif Index: ksrc/nucleus/thread.c =================================================================== --- ksrc/nucleus/thread.c.orig +++ ksrc/nucleus/thread.c @@ -90,6 +90,7 @@ int xnthread_init(xnthread_t *thread, thread->stat.ssw = 0; thread->stat.csw = 0; thread->stat.pf = 0; + thread->stat.exec_time = 0; #endif /* CONFIG_XENO_OPT_STATS */ /* These will be filled by xnpod_start_thread() */ Index: ksrc/nucleus/pod.c =================================================================== --- ksrc/nucleus/pod.c.orig +++ ksrc/nucleus/pod.c @@ -669,6 +669,9 @@ static inline void xnpod_switch_zombie(x xnthread_cleanup_tcb(threadout); + /* no need to update stats of dying thread */ + xnpod_update_csw_date(sched); + xnarch_finalize_and_switch(xnthread_archtcb(threadout), xnthread_archtcb(threadin)); @@ -2433,6 +2436,7 @@ void xnpod_schedule(void) xnarch_enter_root(xnthread_archtcb(threadin)); } + xnpod_acc_exec_time(threadout); xnthread_inc_csw(threadin); xnarch_switch_to(xnthread_archtcb(threadout), @@ -2604,6 +2608,7 @@ void xnpod_schedule_runnable(xnthread_t nkpod->schedhook(runthread, XNREADY); #endif /* __XENO_SIM__ */ + xnpod_acc_exec_time(runthread); xnthread_inc_csw(threadin); xnarch_switch_to(xnthread_archtcb(runthread), Index: ksrc/nucleus/module.c =================================================================== --- ksrc/nucleus/module.c.orig +++ ksrc/nucleus/module.c @@ -269,6 +269,7 @@ struct stat_seq_iterator { unsigned long ssw; unsigned long csw; unsigned long pf; + xnticks_t exec_time; } stat_info[1]; }; @@ -309,13 +310,17 @@ static void stat_seq_stop(struct seq_fil static int stat_seq_show(struct seq_file *seq, void *v) { if (v == SEQ_START_TOKEN) - seq_printf(seq, "%-3s %-6s %-10s %-10s %-4s %-8s %s\n", - "CPU", "PID", "MSW", "CSW", "PF", "STAT", "NAME"); + seq_printf(seq, "%-3s %-6s %-10s %-10s %-4s %-8s %12s" + " %s\n", + "CPU", "PID", "MSW", "CSW", "PF", "STAT", "TIME", + "NAME"); else { struct stat_seq_info *p = (struct stat_seq_info *)v; - seq_printf(seq, "%3u %-6d %-10lu %-10lu %-4lu %.8lx %s\n", + unsigned long long exec_time = xnarch_tsc_to_ns(p->exec_time); + seq_printf(seq, "%3u %-6d %-10lu %-10lu %-4lu %.8lx %12llu" + " %s\n", p->cpu, p->pid, p->ssw, p->csw, p->pf, p->status, - p->name); + xnarch_ulldiv(exec_time, 1000, NULL), p->name); } return 0; @@ -365,6 +370,12 @@ static int stat_seq_open(struct inode *i iter->nentries = 0; + /* Update exec-time stats at least on current CPU, unsync'ed TSCs + prevent cross-CPU update yet. */ + xnlock_get_irqsave(&nklock, s); + xnpod_acc_exec_time(xnpod_current_thread()); + xnlock_put_irqrestore(&nklock, s); + /* Take a snapshot element-wise, restart if something changes underneath us. */ @@ -389,6 +400,7 @@ static int stat_seq_open(struct inode *i iter->stat_info[n].ssw = thread->stat.ssw; iter->stat_info[n].csw = thread->stat.csw; iter->stat_info[n].pf = thread->stat.pf; + iter->stat_info[n].exec_time = thread->stat.exec_time; holder = nextq(&nkpod->threadq, holder);
signature.asc
Description: OpenPGP digital signature
_______________________________________________ Xenomai-core mailing list Xenomai-core@gna.org https://mail.gna.org/listinfo/xenomai-core