Skip to content

Commit

Permalink
taskstats: add context-switch counters
Browse files Browse the repository at this point in the history
Make available to the user the following task and process performance
statistics:

	* Involuntary Context Switches (task_struct->nivcsw)
	* Voluntary Context Switches (task_struct->nvcsw)

Statistics information is available from:
	1. taskstats interface (Documentation/accounting/)
	2. /proc/PID/status (task only).

This data is useful for detecting hyperactivity patterns between processes.

[[email protected]: cleanup]
Signed-off-by: Maxim Uvarov <[email protected]>
Cc: Shailabh Nagar <[email protected]>
Cc: Balbir Singh <[email protected]>
Cc: Jay Lan <[email protected]>
Cc: Jonathan Lim <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
  • Loading branch information
Maxim Uvarov authored and Linus Torvalds committed Jul 16, 2007
1 parent a6c15c2 commit b663a79
Show file tree
Hide file tree
Showing 5 changed files with 41 additions and 3 deletions.
19 changes: 17 additions & 2 deletions Documentation/accounting/getdelays.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ char name[100];
int dbg;
int print_delays;
int print_io_accounting;
int print_task_context_switch_counts;
__u64 stime, utime;

#define PRINTF(fmt, arg...) { \
Expand Down Expand Up @@ -195,7 +196,7 @@ void print_delayacct(struct taskstats *t)
"IO %15s%15s\n"
" %15llu%15llu\n"
"MEM %15s%15s\n"
" %15llu%15llu\n\n",
" %15llu%15llu\n"
"count", "real total", "virtual total", "delay total",
t->cpu_count, t->cpu_run_real_total, t->cpu_run_virtual_total,
t->cpu_delay_total,
Expand All @@ -204,6 +205,14 @@ void print_delayacct(struct taskstats *t)
"count", "delay total", t->swapin_count, t->swapin_delay_total);
}

void task_context_switch_counts(struct taskstats *t)
{
printf("\n\nTask %15s%15s\n"
" %15lu%15lu\n",
"voluntary", "nonvoluntary",
t->nvcsw, t->nivcsw);
}

void print_ioacct(struct taskstats *t)
{
printf("%s: read=%llu, write=%llu, cancelled_write=%llu\n",
Expand Down Expand Up @@ -235,7 +244,7 @@ int main(int argc, char *argv[])
struct msgtemplate msg;

while (1) {
c = getopt(argc, argv, "diw:r:m:t:p:vl");
c = getopt(argc, argv, "qdiw:r:m:t:p:vl");
if (c < 0)
break;

Expand All @@ -248,6 +257,10 @@ int main(int argc, char *argv[])
printf("printing IO accounting\n");
print_io_accounting = 1;
break;
case 'q':
printf("printing task/process context switch rates\n");
print_task_context_switch_counts = 1;
break;
case 'w':
logfile = strdup(optarg);
printf("write to file %s\n", logfile);
Expand Down Expand Up @@ -389,6 +402,8 @@ int main(int argc, char *argv[])
print_delayacct((struct taskstats *) NLA_DATA(na));
if (print_io_accounting)
print_ioacct((struct taskstats *) NLA_DATA(na));
if (print_task_context_switch_counts)
task_context_switch_counts((struct taskstats *) NLA_DATA(na));
if (fd) {
if (write(fd, NLA_DATA(na), na->nla_len) < 0) {
err(1,"write error\n");
Expand Down
6 changes: 6 additions & 0 deletions Documentation/accounting/taskstats-struct.txt
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ There are three different groups of fields in the struct taskstats:
/* Extended accounting fields end */
Their values are collected if CONFIG_TASK_XACCT is set.

4) Per-task and per-thread context switch count statistics

Future extension should add fields to the end of the taskstats struct, and
should not change the relative position of each field within the struct.

Expand Down Expand Up @@ -158,4 +160,8 @@ struct taskstats {

/* Extended accounting fields end */

4) Per-task and per-thread statistics
__u64 nvcsw; /* Context voluntary switch counter */
__u64 nivcsw; /* Context involuntary switch counter */

}
10 changes: 10 additions & 0 deletions fs/proc/array.c
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,15 @@ static inline char *task_cap(struct task_struct *p, char *buffer)
cap_t(p->cap_effective));
}

static inline char *task_context_switch_counts(struct task_struct *p,
char *buffer)
{
return buffer + sprintf(buffer, "voluntary_ctxt_switches:\t%lu\n"
"nonvoluntary_ctxt_switches:\t%lu\n",
p->nvcsw,
p->nivcsw);
}

int proc_pid_status(struct task_struct *task, char * buffer)
{
char * orig = buffer;
Expand All @@ -307,6 +316,7 @@ int proc_pid_status(struct task_struct *task, char * buffer)
#if defined(CONFIG_S390)
buffer = task_show_regs(task, buffer);
#endif
buffer = task_context_switch_counts(task, buffer);
return buffer - orig;
}

Expand Down
5 changes: 4 additions & 1 deletion include/linux/taskstats.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
*/


#define TASKSTATS_VERSION 4
#define TASKSTATS_VERSION 5
#define TS_COMM_LEN 32 /* should be >= TASK_COMM_LEN
* in linux/sched.h */

Expand Down Expand Up @@ -149,6 +149,9 @@ struct taskstats {
__u64 read_bytes; /* bytes of read I/O */
__u64 write_bytes; /* bytes of write I/O */
__u64 cancelled_write_bytes; /* bytes of cancelled write I/O */

__u64 nvcsw; /* voluntary_ctxt_switches */
__u64 nivcsw; /* nonvoluntary_ctxt_switches */
};


Expand Down
4 changes: 4 additions & 0 deletions kernel/taskstats.c
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,8 @@ static int fill_pid(pid_t pid, struct task_struct *tsk,

/* fill in basic acct fields */
stats->version = TASKSTATS_VERSION;
stats->nvcsw = tsk->nvcsw;
stats->nivcsw = tsk->nivcsw;
bacct_add_tsk(stats, tsk);

/* fill in extended acct fields */
Expand Down Expand Up @@ -242,6 +244,8 @@ static int fill_tgid(pid_t tgid, struct task_struct *first,
*/
delayacct_add_tsk(stats, tsk);

stats->nvcsw += tsk->nvcsw;
stats->nivcsw += tsk->nivcsw;
} while_each_thread(first, tsk);

unlock_task_sighand(first, &flags);
Expand Down

0 comments on commit b663a79

Please sign in to comment.