* [Xenomai-core] [PATCH 1/3] Introduce xnstat subsystem
@ 2006-10-12 19:43 Jan Kiszka
2006-10-19 6:05 ` Jan Kiszka
0 siblings, 1 reply; 2+ messages in thread
From: Jan Kiszka @ 2006-10-12 19:43 UTC (permalink / raw)
To: Dmitry Adamushko, xenomai-core
[-- Attachment #1: Type: text/plain, Size: 360 bytes --]
This patch adds the new abstraction xnstat_counter (event counter) and
xnstat_runtime (runtime accumulator) and related services to maintain
and query this data. The whole subsystem evaluates to void if
XENO_OPT_STATS is not selected.
Moreover, the patch moves the existing thread statistics (exec_time and
various counters) over the new infrastructure.
Jan
[-- Attachment #2: introduce_xnstat.patch --]
[-- Type: text/plain, Size: 15053 bytes --]
---
include/nucleus/pod.h | 38 +---------------
include/nucleus/stat.h | 106 +++++++++++++++++++++++++++++++++++++++++++++++
include/nucleus/thread.h | 24 ++--------
ksrc/nucleus/module.c | 59 ++++++++++++--------------
ksrc/nucleus/pod.c | 18 ++++---
ksrc/nucleus/shadow.c | 3 -
ksrc/nucleus/thread.c | 9 ---
7 files changed, 157 insertions(+), 100 deletions(-)
Index: xenomai/include/nucleus/pod.h
===================================================================
--- xenomai.orig/include/nucleus/pod.h
+++ xenomai/include/nucleus/pod.h
@@ -146,7 +146,9 @@ typedef struct xnsched {
xnthread_t rootcb; /*!< Root thread control block. */
#ifdef CONFIG_XENO_OPT_STATS
- xnticks_t last_csw; /*!< Last context switch (ticks). */
+ xnticks_t last_account_switch; /*!< Last account switch date (ticks). */
+
+ xnstat_runtime_t *current_account; /*!< Currently active account */
#endif /* CONFIG_XENO_OPT_STATS */
} xnsched_t;
@@ -544,40 +546,6 @@ 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(xnsched_t *sched, xnthread_t *thread)
-{
- xnticks_t now = xnarch_get_cpu_tsc();
-
- thread->stat.exec_time += now - sched->last_csw;
- sched->last_csw = now;
-}
-
-static inline void xnpod_reset_exec_stats(xnthread_t *thread)
-{
- thread->stat.exec_time = 0;
- thread->stat.exec_start = xnarch_get_cpu_tsc();
-}
-
-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(xnsched_t *sched, xnthread_t *thread)
-{
-}
-
-static inline void xnpod_reset_exec_stats(xnthread_t *thread)
-{
-}
-
-static inline void xnpod_update_csw_date(xnsched_t *sched)
-{
-}
-#endif /* CONFIG_XENO_OPT_STATS */
-
#ifdef __cplusplus
}
#endif
Index: xenomai/include/nucleus/stat.h
===================================================================
--- /dev/null
+++ xenomai/include/nucleus/stat.h
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2006 Jan Kiszka <jan.kiszka@domain.hid>.
+ * Copyright (C) 2006 Dmitry Adamushko <dmitry.adamushko@domain.hid>.
+ *
+ * Xenomai is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2 of the License,
+ * or (at your option) any later version.
+ *
+ * Xenomai is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Xenomai; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#ifndef _XENO_NUCLEUS_STAT_H
+#define _XENO_NUCLEUS_STAT_H
+
+#ifdef CONFIG_XENO_OPT_STATS
+
+typedef struct xnstat_runtime {
+
+ xnticks_t start; /* Start of execution time accumulation */
+
+ xnticks_t total; /* Accumulated execution time */
+
+} xnstat_runtime_t;
+
+/* Account runtime of current account up to now, but don't set a new
+ account yet. */
+#define xnstat_runtime_update(sched) \
+do { \
+ xnticks_t now = xnarch_get_cpu_tsc(); \
+ (sched)->current_account->total += \
+ now - (sched)->last_account_switch; \
+ (sched)->last_account_switch = now; \
+} while (0)
+
+/* Update the current account reference, returning the previous one. */
+#define xnstat_runtime_set_current(sched, new_account) \
+({ \
+ xnstat_runtime_t *__prev; \
+ __prev = xchg(&(sched)->current_account, (new_account)); \
+ __prev; \
+})
+
+/* Return the currently active accounting entity. */
+#define xnstat_runtime_get_current(sched) ((sched)->current_account)
+
+/* Finalize an account (no need to do further accounting, just mark the
+ switch date). */
+#define xnstat_runtime_finalize(sched) \
+ (sched)->last_account_switch = xnarch_get_cpu_tsc()
+
+/* Reset statistics from inside the accounted entity (e.g. after CPU
+ migration). */
+#define xnstat_runtime_reset_stats(stat) \
+do { \
+ (stat)->total = 0; \
+ (stat)->start = xnarch_get_cpu_tsc(); \
+} while (0)
+
+
+typedef struct xnstat_counter {
+ int counter;
+} xnstat_counter_t;
+
+static inline int xnstat_counter_inc(xnstat_counter_t *c) {
+ return c->counter++;
+}
+
+static inline int xnstat_counter_get(xnstat_counter_t *c) {
+ return c->counter;
+}
+
+#else /* !CONFIG_XENO_OPT_STATS */
+typedef struct xnstat_runtime {
+} xnstat_runtime_t;
+
+#define xnstat_runtime_update(sched) do { } while (0)
+#define xnstat_runtime_set_current(sched, new_account) ({ NULL; })
+#define xnstat_runtime_get_current(sched) ({ NULL; })
+#define xnstat_runtime_finalize(sched) do { } while (0)
+#define xnstat_runtime_reset_stats(account) do { } while (0)
+
+typedef struct xnstat_counter {
+} xnstat_counter_t;
+
+static inline int xnstat_counter_inc(xnstat_counter_t *c) { return 0; }
+static inline int xnstat_counter_get(xnstat_counter_t *c) { return 0; }
+#endif /* CONFIG_XENO_OPT_STATS */
+
+/* Switch to new_account, accounting the runtime of the current one until now
+ and returning the previous account. */
+#define xnstat_runtime_switch(sched, new_account) \
+({ \
+ xnstat_runtime_update(sched); \
+ xnstat_runtime_set_current(sched, new_account); \
+})
+
+#endif /* !_XENO_NUCLEUS_STAT_H */
Index: xenomai/include/nucleus/thread.h
===================================================================
--- xenomai.orig/include/nucleus/thread.h
+++ xenomai/include/nucleus/thread.h
@@ -105,6 +105,8 @@
#if defined(__KERNEL__) || defined(__XENO_SIM__)
+#include <nucleus/stat.h>
+
#ifdef __XENO_SIM__
/* Pseudo-status (must not conflict with other bits) */
#define XNRUNNING XNTHREAD_SPARE0
@@ -158,16 +160,12 @@ typedef struct xnthread {
xnticks_t rrcredit; /* Remaining round-robin time credit (ticks) */
-#ifdef CONFIG_XENO_OPT_STATS
struct {
- unsigned long ssw; /* Primary -> secondary mode switch count */
- unsigned long csw; /* Context switches (includes
- secondary -> primary switches) */
- unsigned long pf; /* Number of page faults */
- xnticks_t exec_time; /* Accumulated execution time (tsc) */
- xnticks_t exec_start; /* Start of execution time accumulation (tsc) */
+ 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 */
} stat;
-#endif /* CONFIG_XENO_OPT_STATS */
int errcode; /* Local errno */
@@ -248,16 +246,6 @@ typedef struct xnhook {
(testbits((thread)->status,XNROOT) || !xnthread_user_task(thread) ? \
0 : xnarch_user_pid(xnthread_archtcb(thread)))
-#ifdef CONFIG_XENO_OPT_STATS
-#define xnthread_inc_ssw(thread) ++(thread)->stat.ssw
-#define xnthread_inc_csw(thread) ++(thread)->stat.csw
-#define xnthread_inc_pf(thread) ++(thread)->stat.pf
-#else /* CONFIG_XENO_OPT_STATS */
-#define xnthread_inc_ssw(thread) do { } while(0)
-#define xnthread_inc_csw(thread) do { } while(0)
-#define xnthread_inc_pf(thread) do { } while(0)
-#endif /* CONFIG_XENO_OPT_STATS */
-
#ifdef __cplusplus
extern "C" {
#endif
Index: xenomai/ksrc/nucleus/module.c
===================================================================
--- xenomai.orig/ksrc/nucleus/module.c
+++ xenomai/ksrc/nucleus/module.c
@@ -269,8 +269,8 @@ struct stat_seq_iterator {
unsigned long ssw;
unsigned long csw;
unsigned long pf;
- xnticks_t exec_time;
- xnticks_t exec_period;
+ xnticks_t runtime;
+ xnticks_t account_period;
} stat_info[1];
};
@@ -319,15 +319,15 @@ static int stat_seq_show(struct seq_file
struct stat_seq_info *p = (struct stat_seq_info *)v;
int usage = 0;
- if (p->exec_period) {
- while (p->exec_period > 0xFFFFFFFF) {
- p->exec_time >>= 16;
- p->exec_period >>= 16;
+ if (p->account_period) {
+ while (p->account_period > 0xFFFFFFFF) {
+ p->runtime >>= 16;
+ p->account_period >>= 16;
}
usage =
- xnarch_ulldiv(p->exec_time * 1000LL +
- (p->exec_period >> 1), p->exec_period,
- NULL);
+ xnarch_ulldiv(p->runtime * 1000LL +
+ (p->account_period >> 1),
+ p->account_period, NULL);
}
seq_printf(seq, "%3u %-6d %-10lu %-10lu %-4lu %.8lx %3u.%u"
" %s\n",
@@ -350,7 +350,8 @@ static int stat_seq_open(struct inode *i
struct stat_seq_iterator *iter = NULL;
struct seq_file *seq;
xnholder_t *holder;
- int err, count, rev;
+ struct stat_seq_info *stat_info;
+ int err, count, thrq_rev;
spl_t s;
if (!nkpod)
@@ -359,9 +360,9 @@ static int stat_seq_open(struct inode *i
restart:
xnlock_get_irqsave(&nklock, s);
- rev = nkpod->threadq_rev;
count = countq(&nkpod->threadq); /* Cannot be empty (ROOT) */
holder = getheadq(&nkpod->threadq);
+ thrq_rev = nkpod->threadq_rev;
xnlock_put_irqrestore(&nklock, s);
@@ -389,37 +390,35 @@ static int stat_seq_open(struct inode *i
xnthread_t *thread;
xnsched_t *sched;
xnticks_t period;
- int n;
xnlock_get_irqsave(&nklock, s);
- if (nkpod->threadq_rev != rev)
+ if (nkpod->threadq_rev != thrq_rev)
goto restart;
- rev = nkpod->threadq_rev;
thread = link2thread(holder, glink);
- n = iter->nentries++;
+ stat_info = &iter->stat_info[iter->nentries++];
sched = thread->sched;
- iter->stat_info[n].cpu = xnsched_cpu(sched);
- iter->stat_info[n].pid = xnthread_user_pid(thread);
- memcpy(iter->stat_info[n].name, thread->name,
- sizeof(iter->stat_info[n].name));
- iter->stat_info[n].status = thread->status;
- iter->stat_info[n].ssw = thread->stat.ssw;
- iter->stat_info[n].csw = thread->stat.csw;
- iter->stat_info[n].pf = thread->stat.pf;
+ stat_info->cpu = xnsched_cpu(sched);
+ stat_info->pid = xnthread_user_pid(thread);
+ memcpy(stat_info->name, thread->name,
+ sizeof(stat_info->name));
+ stat_info->status = thread->status;
+ stat_info->ssw = xnstat_counter_get(&thread->stat.ssw);
+ stat_info->csw = xnstat_counter_get(&thread->stat.csw);
+ stat_info->pf = xnstat_counter_get(&thread->stat.pf);
- period = sched->last_csw - thread->stat.exec_start;
+ period = sched->last_account_switch - thread->stat.account.start;
if (!period && thread == sched->runthread) {
- iter->stat_info[n].exec_time = 1;
- iter->stat_info[n].exec_period = 1;
+ stat_info->runtime = 1;
+ stat_info->account_period = 1;
} else {
- iter->stat_info[n].exec_time = thread->stat.exec_time;
- iter->stat_info[n].exec_period = period;
+ stat_info->runtime = thread->stat.account.total;
+ stat_info->account_period = period;
}
- thread->stat.exec_time = 0;
- thread->stat.exec_start = sched->last_csw;
+ thread->stat.account.total = 0;
+ thread->stat.account.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
@@ -41,6 +41,7 @@
#include <nucleus/registry.h>
#include <nucleus/module.h>
#include <nucleus/ltt.h>
+#include <nucleus/stat.h>
#include <asm/xenomai/bits/pod.h>
/* NOTE: We need to initialize the globals: remember that this code
@@ -213,7 +214,7 @@ static int xnpod_fault_handler(xnarch_fl
/* The page fault counter is not SMP-safe, but it's a
simple indicator that something went wrong wrt memory
locking anyway. */
- xnthread_inc_pf(thread);
+ xnstat_counter_inc(&thread->stat.pf);
xnshadow_relax(xnarch_fault_notify(fltinfo));
}
@@ -503,6 +504,8 @@ int xnpod_init(xnpod_t *pod, int minpri,
sched->rootcb.sched = sched;
sched->rootcb.affinity = xnarch_cpumask_of_cpu(cpu);
+
+ xnstat_runtime_set_current(sched, &sched->rootcb.stat.account);
}
xnarch_hook_ipi(&xnpod_schedule_handler);
@@ -668,8 +671,7 @@ static inline void xnpod_switch_zombie(x
xnthread_cleanup_tcb(threadout);
- /* no need to update stats of dying thread */
- xnpod_update_csw_date(sched);
+ xnstat_runtime_finalize(sched);
xnarch_finalize_and_switch(xnthread_archtcb(threadout),
xnthread_archtcb(threadin));
@@ -1896,7 +1898,7 @@ int xnpod_migrate_thread(int cpu)
xnpod_schedule();
/* Reset execution time stats due to unsync'ed TSCs */
- xnpod_reset_exec_stats(thread);
+ xnstat_runtime_reset_stats(&thread->stat.account);
unlock_and_exit:
@@ -2435,8 +2437,8 @@ void xnpod_schedule(void)
xnarch_enter_root(xnthread_archtcb(threadin));
}
- xnpod_acc_exec_time(sched, threadout);
- xnthread_inc_csw(threadin);
+ xnstat_runtime_switch(sched, &threadin->stat.account);
+ xnstat_counter_inc(&threadin->stat.csw);
xnarch_switch_to(xnthread_archtcb(threadout),
xnthread_archtcb(threadin));
@@ -2607,8 +2609,8 @@ void xnpod_schedule_runnable(xnthread_t
nkpod->schedhook(runthread, XNREADY);
#endif /* __XENO_SIM__ */
- xnpod_acc_exec_time(sched, runthread);
- xnthread_inc_csw(threadin);
+ xnstat_runtime_switch(sched, &threadin->stat.account);
+ xnstat_counter_inc(&threadin->stat.csw);
xnarch_switch_to(xnthread_archtcb(runthread),
xnthread_archtcb(threadin));
Index: xenomai/ksrc/nucleus/shadow.c
===================================================================
--- xenomai.orig/ksrc/nucleus/shadow.c
+++ xenomai/ksrc/nucleus/shadow.c
@@ -50,6 +50,7 @@
#include <nucleus/jhash.h>
#include <nucleus/ppd.h>
#include <nucleus/trace.h>
+#include <nucleus/stat.h>
#include <asm/xenomai/features.h>
#include <asm/xenomai/syscall.h>
#include <asm/xenomai/bits/shadow.h>
@@ -727,7 +728,7 @@ void xnshadow_relax(int notify)
rthal_reenter_root(get_switch_lock_owner(),
cprio ? SCHED_FIFO : SCHED_NORMAL, cprio);
- xnthread_inc_ssw(thread); /* Account for secondary mode switch. */
+ xnstat_counter_inc(&thread->stat.ssw); /* Account for secondary mode switch. */
if (notify && testbits(thread->status, XNTRAPSW))
/* Help debugging spurious relaxes. */
Index: xenomai/ksrc/nucleus/thread.c
===================================================================
--- xenomai.orig/ksrc/nucleus/thread.c
+++ xenomai/ksrc/nucleus/thread.c
@@ -86,14 +86,7 @@ int xnthread_init(xnthread_t *thread,
thread->registry.handle = XN_NO_HANDLE;
thread->registry.waitkey = NULL;
#endif /* CONFIG_XENO_OPT_REGISTRY */
-
-#ifdef CONFIG_XENO_OPT_STATS
- thread->stat.ssw = 0;
- thread->stat.csw = 0;
- thread->stat.pf = 0;
- thread->stat.exec_time = 0;
- thread->stat.exec_start = 0;
-#endif /* CONFIG_XENO_OPT_STATS */
+ memset(&thread->stat, 0, sizeof(thread->stat));
/* These will be filled by xnpod_start_thread() */
thread->imask = 0;
^ permalink raw reply [flat|nested] 2+ messages in thread* Re: [Xenomai-core] [PATCH 1/3] Introduce xnstat subsystem
2006-10-12 19:43 [Xenomai-core] [PATCH 1/3] Introduce xnstat subsystem Jan Kiszka
@ 2006-10-19 6:05 ` Jan Kiszka
0 siblings, 0 replies; 2+ messages in thread
From: Jan Kiszka @ 2006-10-19 6:05 UTC (permalink / raw)
To: Dmitry Adamushko, xenomai-core
[-- Attachment #1.1: Type: text/plain, Size: 580 bytes --]
Jan Kiszka wrote:
> This patch adds the new abstraction xnstat_counter (event counter) and
> xnstat_runtime (runtime accumulator) and related services to maintain
> and query this data. The whole subsystem evaluates to void if
> XENO_OPT_STATS is not selected.
>
> Moreover, the patch moves the existing thread statistics (exec_time and
> various counters) over the new infrastructure.
>
Here was the bug I thought to have found in the second patch: as
assumed, the current account was not updated on thread termination.
Attached is a corrected revision.
Jan
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1.2: introduce_xnstat-v2.patch --]
[-- Type: text/x-patch; name="introduce_xnstat-v2.patch", Size: 15644 bytes --]
---
include/nucleus/pod.h | 38 +---------------
include/nucleus/stat.h | 109 +++++++++++++++++++++++++++++++++++++++++++++++
include/nucleus/thread.h | 24 ++--------
ksrc/nucleus/module.c | 59 ++++++++++++-------------
ksrc/nucleus/pod.c | 18 ++++---
ksrc/nucleus/shadow.c | 3 -
ksrc/nucleus/thread.c | 9 ---
7 files changed, 160 insertions(+), 100 deletions(-)
Index: xenomai/include/nucleus/pod.h
===================================================================
--- xenomai.orig/include/nucleus/pod.h
+++ xenomai/include/nucleus/pod.h
@@ -146,7 +146,9 @@ typedef struct xnsched {
xnthread_t rootcb; /*!< Root thread control block. */
#ifdef CONFIG_XENO_OPT_STATS
- xnticks_t last_csw; /*!< Last context switch (ticks). */
+ xnticks_t last_account_switch; /*!< Last account switch date (ticks). */
+
+ xnstat_runtime_t *current_account; /*!< Currently active account */
#endif /* CONFIG_XENO_OPT_STATS */
} xnsched_t;
@@ -544,40 +546,6 @@ 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(xnsched_t *sched, xnthread_t *thread)
-{
- xnticks_t now = xnarch_get_cpu_tsc();
-
- thread->stat.exec_time += now - sched->last_csw;
- sched->last_csw = now;
-}
-
-static inline void xnpod_reset_exec_stats(xnthread_t *thread)
-{
- thread->stat.exec_time = 0;
- thread->stat.exec_start = xnarch_get_cpu_tsc();
-}
-
-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(xnsched_t *sched, xnthread_t *thread)
-{
-}
-
-static inline void xnpod_reset_exec_stats(xnthread_t *thread)
-{
-}
-
-static inline void xnpod_update_csw_date(xnsched_t *sched)
-{
-}
-#endif /* CONFIG_XENO_OPT_STATS */
-
#ifdef __cplusplus
}
#endif
Index: xenomai/include/nucleus/stat.h
===================================================================
--- /dev/null
+++ xenomai/include/nucleus/stat.h
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2006 Jan Kiszka <jan.kiszka@domain.hid>.
+ * Copyright (C) 2006 Dmitry Adamushko <dmitry.adamushko@domain.hid>.
+ *
+ * Xenomai is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2 of the License,
+ * or (at your option) any later version.
+ *
+ * Xenomai is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Xenomai; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#ifndef _XENO_NUCLEUS_STAT_H
+#define _XENO_NUCLEUS_STAT_H
+
+#ifdef CONFIG_XENO_OPT_STATS
+
+typedef struct xnstat_runtime {
+
+ xnticks_t start; /* Start of execution time accumulation */
+
+ xnticks_t total; /* Accumulated execution time */
+
+} xnstat_runtime_t;
+
+/* Account runtime of current account up to now, but don't set a new
+ account yet. */
+#define xnstat_runtime_update(sched) \
+do { \
+ xnticks_t now = xnarch_get_cpu_tsc(); \
+ (sched)->current_account->total += \
+ now - (sched)->last_account_switch; \
+ (sched)->last_account_switch = now; \
+} while (0)
+
+/* Update the current account reference, returning the previous one. */
+#define xnstat_runtime_set_current(sched, new_account) \
+({ \
+ xnstat_runtime_t *__prev; \
+ __prev = xchg(&(sched)->current_account, (new_account)); \
+ __prev; \
+})
+
+/* Return the currently active accounting entity. */
+#define xnstat_runtime_get_current(sched) ((sched)->current_account)
+
+/* Finalize an account (no need to accumulate the runtime, just mark the
+ switch date and set the new account). */
+#define xnstat_runtime_finalize(sched, new_account) \
+do { \
+ (sched)->last_account_switch = xnarch_get_cpu_tsc(); \
+ (sched)->current_account = (new_account); \
+} while (0)
+
+/* Reset statistics from inside the accounted entity (e.g. after CPU
+ migration). */
+#define xnstat_runtime_reset_stats(stat) \
+do { \
+ (stat)->total = 0; \
+ (stat)->start = xnarch_get_cpu_tsc(); \
+} while (0)
+
+
+typedef struct xnstat_counter {
+ int counter;
+} xnstat_counter_t;
+
+static inline int xnstat_counter_inc(xnstat_counter_t *c) {
+ return c->counter++;
+}
+
+static inline int xnstat_counter_get(xnstat_counter_t *c) {
+ return c->counter;
+}
+
+#else /* !CONFIG_XENO_OPT_STATS */
+typedef struct xnstat_runtime {
+} xnstat_runtime_t;
+
+#define xnstat_runtime_update(sched) do { } while (0)
+#define xnstat_runtime_set_current(sched, new_account) ({ NULL; })
+#define xnstat_runtime_get_current(sched) ({ NULL; })
+#define xnstat_runtime_finalize(sched, new_account) do { } while (0)
+#define xnstat_runtime_reset_stats(account) do { } while (0)
+
+typedef struct xnstat_counter {
+} xnstat_counter_t;
+
+static inline int xnstat_counter_inc(xnstat_counter_t *c) { return 0; }
+static inline int xnstat_counter_get(xnstat_counter_t *c) { return 0; }
+#endif /* CONFIG_XENO_OPT_STATS */
+
+/* Switch to new_account, accounting the runtime of the current one until now
+ and returning the previous account. */
+#define xnstat_runtime_switch(sched, new_account) \
+({ \
+ xnstat_runtime_update(sched); \
+ xnstat_runtime_set_current(sched, new_account); \
+})
+
+#endif /* !_XENO_NUCLEUS_STAT_H */
Index: xenomai/include/nucleus/thread.h
===================================================================
--- xenomai.orig/include/nucleus/thread.h
+++ xenomai/include/nucleus/thread.h
@@ -105,6 +105,8 @@
#if defined(__KERNEL__) || defined(__XENO_SIM__)
+#include <nucleus/stat.h>
+
#ifdef __XENO_SIM__
/* Pseudo-status (must not conflict with other bits) */
#define XNRUNNING XNTHREAD_SPARE0
@@ -158,16 +160,12 @@ typedef struct xnthread {
xnticks_t rrcredit; /* Remaining round-robin time credit (ticks) */
-#ifdef CONFIG_XENO_OPT_STATS
struct {
- unsigned long ssw; /* Primary -> secondary mode switch count */
- unsigned long csw; /* Context switches (includes
- secondary -> primary switches) */
- unsigned long pf; /* Number of page faults */
- xnticks_t exec_time; /* Accumulated execution time (tsc) */
- xnticks_t exec_start; /* Start of execution time accumulation (tsc) */
+ 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 */
} stat;
-#endif /* CONFIG_XENO_OPT_STATS */
int errcode; /* Local errno */
@@ -248,16 +246,6 @@ typedef struct xnhook {
(testbits((thread)->status,XNROOT) || !xnthread_user_task(thread) ? \
0 : xnarch_user_pid(xnthread_archtcb(thread)))
-#ifdef CONFIG_XENO_OPT_STATS
-#define xnthread_inc_ssw(thread) ++(thread)->stat.ssw
-#define xnthread_inc_csw(thread) ++(thread)->stat.csw
-#define xnthread_inc_pf(thread) ++(thread)->stat.pf
-#else /* CONFIG_XENO_OPT_STATS */
-#define xnthread_inc_ssw(thread) do { } while(0)
-#define xnthread_inc_csw(thread) do { } while(0)
-#define xnthread_inc_pf(thread) do { } while(0)
-#endif /* CONFIG_XENO_OPT_STATS */
-
#ifdef __cplusplus
extern "C" {
#endif
Index: xenomai/ksrc/nucleus/module.c
===================================================================
--- xenomai.orig/ksrc/nucleus/module.c
+++ xenomai/ksrc/nucleus/module.c
@@ -269,8 +269,8 @@ struct stat_seq_iterator {
unsigned long ssw;
unsigned long csw;
unsigned long pf;
- xnticks_t exec_time;
- xnticks_t exec_period;
+ xnticks_t runtime;
+ xnticks_t account_period;
} stat_info[1];
};
@@ -319,15 +319,15 @@ static int stat_seq_show(struct seq_file
struct stat_seq_info *p = (struct stat_seq_info *)v;
int usage = 0;
- if (p->exec_period) {
- while (p->exec_period > 0xFFFFFFFF) {
- p->exec_time >>= 16;
- p->exec_period >>= 16;
+ if (p->account_period) {
+ while (p->account_period > 0xFFFFFFFF) {
+ p->runtime >>= 16;
+ p->account_period >>= 16;
}
usage =
- xnarch_ulldiv(p->exec_time * 1000LL +
- (p->exec_period >> 1), p->exec_period,
- NULL);
+ xnarch_ulldiv(p->runtime * 1000LL +
+ (p->account_period >> 1),
+ p->account_period, NULL);
}
seq_printf(seq, "%3u %-6d %-10lu %-10lu %-4lu %.8lx %3u.%u"
" %s\n",
@@ -350,7 +350,8 @@ static int stat_seq_open(struct inode *i
struct stat_seq_iterator *iter = NULL;
struct seq_file *seq;
xnholder_t *holder;
- int err, count, rev;
+ struct stat_seq_info *stat_info;
+ int err, count, thrq_rev;
spl_t s;
if (!nkpod)
@@ -359,9 +360,9 @@ static int stat_seq_open(struct inode *i
restart:
xnlock_get_irqsave(&nklock, s);
- rev = nkpod->threadq_rev;
count = countq(&nkpod->threadq); /* Cannot be empty (ROOT) */
holder = getheadq(&nkpod->threadq);
+ thrq_rev = nkpod->threadq_rev;
xnlock_put_irqrestore(&nklock, s);
@@ -389,37 +390,35 @@ static int stat_seq_open(struct inode *i
xnthread_t *thread;
xnsched_t *sched;
xnticks_t period;
- int n;
xnlock_get_irqsave(&nklock, s);
- if (nkpod->threadq_rev != rev)
+ if (nkpod->threadq_rev != thrq_rev)
goto restart;
- rev = nkpod->threadq_rev;
thread = link2thread(holder, glink);
- n = iter->nentries++;
+ stat_info = &iter->stat_info[iter->nentries++];
sched = thread->sched;
- iter->stat_info[n].cpu = xnsched_cpu(sched);
- iter->stat_info[n].pid = xnthread_user_pid(thread);
- memcpy(iter->stat_info[n].name, thread->name,
- sizeof(iter->stat_info[n].name));
- iter->stat_info[n].status = thread->status;
- iter->stat_info[n].ssw = thread->stat.ssw;
- iter->stat_info[n].csw = thread->stat.csw;
- iter->stat_info[n].pf = thread->stat.pf;
+ stat_info->cpu = xnsched_cpu(sched);
+ stat_info->pid = xnthread_user_pid(thread);
+ memcpy(stat_info->name, thread->name,
+ sizeof(stat_info->name));
+ stat_info->status = thread->status;
+ stat_info->ssw = xnstat_counter_get(&thread->stat.ssw);
+ stat_info->csw = xnstat_counter_get(&thread->stat.csw);
+ stat_info->pf = xnstat_counter_get(&thread->stat.pf);
- period = sched->last_csw - thread->stat.exec_start;
+ period = sched->last_account_switch - thread->stat.account.start;
if (!period && thread == sched->runthread) {
- iter->stat_info[n].exec_time = 1;
- iter->stat_info[n].exec_period = 1;
+ stat_info->runtime = 1;
+ stat_info->account_period = 1;
} else {
- iter->stat_info[n].exec_time = thread->stat.exec_time;
- iter->stat_info[n].exec_period = period;
+ stat_info->runtime = thread->stat.account.total;
+ stat_info->account_period = period;
}
- thread->stat.exec_time = 0;
- thread->stat.exec_start = sched->last_csw;
+ thread->stat.account.total = 0;
+ thread->stat.account.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
@@ -41,6 +41,7 @@
#include <nucleus/registry.h>
#include <nucleus/module.h>
#include <nucleus/ltt.h>
+#include <nucleus/stat.h>
#include <asm/xenomai/bits/pod.h>
/* NOTE: We need to initialize the globals: remember that this code
@@ -213,7 +214,7 @@ static int xnpod_fault_handler(xnarch_fl
/* The page fault counter is not SMP-safe, but it's a
simple indicator that something went wrong wrt memory
locking anyway. */
- xnthread_inc_pf(thread);
+ xnstat_counter_inc(&thread->stat.pf);
xnshadow_relax(xnarch_fault_notify(fltinfo));
}
@@ -503,6 +504,8 @@ int xnpod_init(xnpod_t *pod, int minpri,
sched->rootcb.sched = sched;
sched->rootcb.affinity = xnarch_cpumask_of_cpu(cpu);
+
+ xnstat_runtime_set_current(sched, &sched->rootcb.stat.account);
}
xnarch_hook_ipi(&xnpod_schedule_handler);
@@ -668,8 +671,7 @@ static inline void xnpod_switch_zombie(x
xnthread_cleanup_tcb(threadout);
- /* no need to update stats of dying thread */
- xnpod_update_csw_date(sched);
+ xnstat_runtime_finalize(sched, &threadin->stat.account);
xnarch_finalize_and_switch(xnthread_archtcb(threadout),
xnthread_archtcb(threadin));
@@ -1896,7 +1898,7 @@ int xnpod_migrate_thread(int cpu)
xnpod_schedule();
/* Reset execution time stats due to unsync'ed TSCs */
- xnpod_reset_exec_stats(thread);
+ xnstat_runtime_reset_stats(&thread->stat.account);
unlock_and_exit:
@@ -2435,8 +2437,8 @@ void xnpod_schedule(void)
xnarch_enter_root(xnthread_archtcb(threadin));
}
- xnpod_acc_exec_time(sched, threadout);
- xnthread_inc_csw(threadin);
+ xnstat_runtime_switch(sched, &threadin->stat.account);
+ xnstat_counter_inc(&threadin->stat.csw);
xnarch_switch_to(xnthread_archtcb(threadout),
xnthread_archtcb(threadin));
@@ -2607,8 +2609,8 @@ void xnpod_schedule_runnable(xnthread_t
nkpod->schedhook(runthread, XNREADY);
#endif /* __XENO_SIM__ */
- xnpod_acc_exec_time(sched, runthread);
- xnthread_inc_csw(threadin);
+ xnstat_runtime_switch(sched, &threadin->stat.account);
+ xnstat_counter_inc(&threadin->stat.csw);
xnarch_switch_to(xnthread_archtcb(runthread),
xnthread_archtcb(threadin));
Index: xenomai/ksrc/nucleus/shadow.c
===================================================================
--- xenomai.orig/ksrc/nucleus/shadow.c
+++ xenomai/ksrc/nucleus/shadow.c
@@ -50,6 +50,7 @@
#include <nucleus/jhash.h>
#include <nucleus/ppd.h>
#include <nucleus/trace.h>
+#include <nucleus/stat.h>
#include <asm/xenomai/features.h>
#include <asm/xenomai/syscall.h>
#include <asm/xenomai/bits/shadow.h>
@@ -727,7 +728,7 @@ void xnshadow_relax(int notify)
rthal_reenter_root(get_switch_lock_owner(),
cprio ? SCHED_FIFO : SCHED_NORMAL, cprio);
- xnthread_inc_ssw(thread); /* Account for secondary mode switch. */
+ xnstat_counter_inc(&thread->stat.ssw); /* Account for secondary mode switch. */
if (notify && testbits(thread->status, XNTRAPSW))
/* Help debugging spurious relaxes. */
Index: xenomai/ksrc/nucleus/thread.c
===================================================================
--- xenomai.orig/ksrc/nucleus/thread.c
+++ xenomai/ksrc/nucleus/thread.c
@@ -86,14 +86,7 @@ int xnthread_init(xnthread_t *thread,
thread->registry.handle = XN_NO_HANDLE;
thread->registry.waitkey = NULL;
#endif /* CONFIG_XENO_OPT_REGISTRY */
-
-#ifdef CONFIG_XENO_OPT_STATS
- thread->stat.ssw = 0;
- thread->stat.csw = 0;
- thread->stat.pf = 0;
- thread->stat.exec_time = 0;
- thread->stat.exec_start = 0;
-#endif /* CONFIG_XENO_OPT_STATS */
+ memset(&thread->stat, 0, sizeof(thread->stat));
/* These will be filled by xnpod_start_thread() */
thread->imask = 0;
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 249 bytes --]
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2006-10-19 6:05 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-10-12 19:43 [Xenomai-core] [PATCH 1/3] Introduce xnstat subsystem Jan Kiszka
2006-10-19 6:05 ` Jan Kiszka
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.