diff options
Diffstat (limited to 'kernel/tsacct.c')
-rw-r--r-- | kernel/tsacct.c | 124 |
1 files changed, 124 insertions, 0 deletions
diff --git a/kernel/tsacct.c b/kernel/tsacct.c new file mode 100644 index 000000000000..db443221ba5b --- /dev/null +++ b/kernel/tsacct.c | |||
@@ -0,0 +1,124 @@ | |||
1 | /* | ||
2 | * tsacct.c - System accounting over taskstats interface | ||
3 | * | ||
4 | * Copyright (C) Jay Lan, <jlan@sgi.com> | ||
5 | * | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | */ | ||
18 | |||
19 | #include <linux/kernel.h> | ||
20 | #include <linux/sched.h> | ||
21 | #include <linux/tsacct_kern.h> | ||
22 | #include <linux/acct.h> | ||
23 | #include <linux/jiffies.h> | ||
24 | |||
25 | |||
26 | #define USEC_PER_TICK (USEC_PER_SEC/HZ) | ||
27 | /* | ||
28 | * fill in basic accounting fields | ||
29 | */ | ||
30 | void bacct_add_tsk(struct taskstats *stats, struct task_struct *tsk) | ||
31 | { | ||
32 | struct timespec uptime, ts; | ||
33 | s64 ac_etime; | ||
34 | |||
35 | BUILD_BUG_ON(TS_COMM_LEN < TASK_COMM_LEN); | ||
36 | |||
37 | /* calculate task elapsed time in timespec */ | ||
38 | do_posix_clock_monotonic_gettime(&uptime); | ||
39 | ts = timespec_sub(uptime, current->group_leader->start_time); | ||
40 | /* rebase elapsed time to usec */ | ||
41 | ac_etime = timespec_to_ns(&ts); | ||
42 | do_div(ac_etime, NSEC_PER_USEC); | ||
43 | stats->ac_etime = ac_etime; | ||
44 | stats->ac_btime = xtime.tv_sec - ts.tv_sec; | ||
45 | if (thread_group_leader(tsk)) { | ||
46 | stats->ac_exitcode = tsk->exit_code; | ||
47 | if (tsk->flags & PF_FORKNOEXEC) | ||
48 | stats->ac_flag |= AFORK; | ||
49 | } | ||
50 | if (tsk->flags & PF_SUPERPRIV) | ||
51 | stats->ac_flag |= ASU; | ||
52 | if (tsk->flags & PF_DUMPCORE) | ||
53 | stats->ac_flag |= ACORE; | ||
54 | if (tsk->flags & PF_SIGNALED) | ||
55 | stats->ac_flag |= AXSIG; | ||
56 | stats->ac_nice = task_nice(tsk); | ||
57 | stats->ac_sched = tsk->policy; | ||
58 | stats->ac_uid = tsk->uid; | ||
59 | stats->ac_gid = tsk->gid; | ||
60 | stats->ac_pid = tsk->pid; | ||
61 | stats->ac_ppid = (tsk->parent) ? tsk->parent->pid : 0; | ||
62 | stats->ac_utime = cputime_to_msecs(tsk->utime) * USEC_PER_MSEC; | ||
63 | stats->ac_stime = cputime_to_msecs(tsk->stime) * USEC_PER_MSEC; | ||
64 | stats->ac_minflt = tsk->min_flt; | ||
65 | stats->ac_majflt = tsk->maj_flt; | ||
66 | |||
67 | strncpy(stats->ac_comm, tsk->comm, sizeof(stats->ac_comm)); | ||
68 | } | ||
69 | |||
70 | |||
71 | #ifdef CONFIG_TASK_XACCT | ||
72 | |||
73 | #define KB 1024 | ||
74 | #define MB (1024*KB) | ||
75 | /* | ||
76 | * fill in extended accounting fields | ||
77 | */ | ||
78 | void xacct_add_tsk(struct taskstats *stats, struct task_struct *p) | ||
79 | { | ||
80 | /* convert pages-jiffies to Mbyte-usec */ | ||
81 | stats->coremem = jiffies_to_usecs(p->acct_rss_mem1) * PAGE_SIZE / MB; | ||
82 | stats->virtmem = jiffies_to_usecs(p->acct_vm_mem1) * PAGE_SIZE / MB; | ||
83 | if (p->mm) { | ||
84 | /* adjust to KB unit */ | ||
85 | stats->hiwater_rss = p->mm->hiwater_rss * PAGE_SIZE / KB; | ||
86 | stats->hiwater_vm = p->mm->hiwater_vm * PAGE_SIZE / KB; | ||
87 | } | ||
88 | stats->read_char = p->rchar; | ||
89 | stats->write_char = p->wchar; | ||
90 | stats->read_syscalls = p->syscr; | ||
91 | stats->write_syscalls = p->syscw; | ||
92 | } | ||
93 | #undef KB | ||
94 | #undef MB | ||
95 | |||
96 | /** | ||
97 | * acct_update_integrals - update mm integral fields in task_struct | ||
98 | * @tsk: task_struct for accounting | ||
99 | */ | ||
100 | void acct_update_integrals(struct task_struct *tsk) | ||
101 | { | ||
102 | if (likely(tsk->mm)) { | ||
103 | long delta = cputime_to_jiffies( | ||
104 | cputime_sub(tsk->stime, tsk->acct_stimexpd)); | ||
105 | |||
106 | if (delta == 0) | ||
107 | return; | ||
108 | tsk->acct_stimexpd = tsk->stime; | ||
109 | tsk->acct_rss_mem1 += delta * get_mm_rss(tsk->mm); | ||
110 | tsk->acct_vm_mem1 += delta * tsk->mm->total_vm; | ||
111 | } | ||
112 | } | ||
113 | |||
114 | /** | ||
115 | * acct_clear_integrals - clear the mm integral fields in task_struct | ||
116 | * @tsk: task_struct whose accounting fields are cleared | ||
117 | */ | ||
118 | void acct_clear_integrals(struct task_struct *tsk) | ||
119 | { | ||
120 | tsk->acct_stimexpd = 0; | ||
121 | tsk->acct_rss_mem1 = 0; | ||
122 | tsk->acct_vm_mem1 = 0; | ||
123 | } | ||
124 | #endif | ||