aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'kernel')
-rw-r--r--kernel/Makefile1
-rw-r--r--kernel/delayacct.c87
-rw-r--r--kernel/exit.c2
-rw-r--r--kernel/fork.c2
4 files changed, 92 insertions, 0 deletions
diff --git a/kernel/Makefile b/kernel/Makefile
index 47dbcd570cd..87bb34cc893 100644
--- a/kernel/Makefile
+++ b/kernel/Makefile
@@ -48,6 +48,7 @@ obj-$(CONFIG_GENERIC_HARDIRQS) += irq/
48obj-$(CONFIG_SECCOMP) += seccomp.o 48obj-$(CONFIG_SECCOMP) += seccomp.o
49obj-$(CONFIG_RCU_TORTURE_TEST) += rcutorture.o 49obj-$(CONFIG_RCU_TORTURE_TEST) += rcutorture.o
50obj-$(CONFIG_RELAY) += relay.o 50obj-$(CONFIG_RELAY) += relay.o
51obj-$(CONFIG_TASK_DELAY_ACCT) += delayacct.o
51 52
52ifneq ($(CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER),y) 53ifneq ($(CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER),y)
53# According to Alan Modra <alan@linuxcare.com.au>, the -fno-omit-frame-pointer is 54# According to Alan Modra <alan@linuxcare.com.au>, the -fno-omit-frame-pointer is
diff --git a/kernel/delayacct.c b/kernel/delayacct.c
new file mode 100644
index 00000000000..fbf7f228495
--- /dev/null
+++ b/kernel/delayacct.c
@@ -0,0 +1,87 @@
1/* delayacct.c - per-task delay accounting
2 *
3 * Copyright (C) Shailabh Nagar, IBM Corp. 2006
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it would be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
13 * the GNU General Public License for more details.
14 */
15
16#include <linux/sched.h>
17#include <linux/slab.h>
18#include <linux/time.h>
19#include <linux/sysctl.h>
20#include <linux/delayacct.h>
21
22int delayacct_on __read_mostly; /* Delay accounting turned on/off */
23kmem_cache_t *delayacct_cache;
24
25static int __init delayacct_setup_enable(char *str)
26{
27 delayacct_on = 1;
28 return 1;
29}
30__setup("delayacct", delayacct_setup_enable);
31
32void delayacct_init(void)
33{
34 delayacct_cache = kmem_cache_create("delayacct_cache",
35 sizeof(struct task_delay_info),
36 0,
37 SLAB_PANIC,
38 NULL, NULL);
39 delayacct_tsk_init(&init_task);
40}
41
42void __delayacct_tsk_init(struct task_struct *tsk)
43{
44 tsk->delays = kmem_cache_zalloc(delayacct_cache, SLAB_KERNEL);
45 if (tsk->delays)
46 spin_lock_init(&tsk->delays->lock);
47}
48
49void __delayacct_tsk_exit(struct task_struct *tsk)
50{
51 kmem_cache_free(delayacct_cache, tsk->delays);
52 tsk->delays = NULL;
53}
54
55/*
56 * Start accounting for a delay statistic using
57 * its starting timestamp (@start)
58 */
59
60static inline void delayacct_start(struct timespec *start)
61{
62 do_posix_clock_monotonic_gettime(start);
63}
64
65/*
66 * Finish delay accounting for a statistic using
67 * its timestamps (@start, @end), accumalator (@total) and @count
68 */
69
70static void delayacct_end(struct timespec *start, struct timespec *end,
71 u64 *total, u32 *count)
72{
73 struct timespec ts;
74 s64 ns;
75
76 do_posix_clock_monotonic_gettime(end);
77 ts = timespec_sub(*end, *start);
78 ns = timespec_to_ns(&ts);
79 if (ns < 0)
80 return;
81
82 spin_lock(&current->delays->lock);
83 *total += ns;
84 (*count)++;
85 spin_unlock(&current->delays->lock);
86}
87
diff --git a/kernel/exit.c b/kernel/exit.c
index 6664c084783..3c2cf91defa 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -25,6 +25,7 @@
25#include <linux/mount.h> 25#include <linux/mount.h>
26#include <linux/proc_fs.h> 26#include <linux/proc_fs.h>
27#include <linux/mempolicy.h> 27#include <linux/mempolicy.h>
28#include <linux/delayacct.h>
28#include <linux/cpuset.h> 29#include <linux/cpuset.h>
29#include <linux/syscalls.h> 30#include <linux/syscalls.h>
30#include <linux/signal.h> 31#include <linux/signal.h>
@@ -900,6 +901,7 @@ fastcall NORET_TYPE void do_exit(long code)
900#endif 901#endif
901 if (unlikely(tsk->audit_context)) 902 if (unlikely(tsk->audit_context))
902 audit_free(tsk); 903 audit_free(tsk);
904 delayacct_tsk_exit(tsk);
903 exit_mm(tsk); 905 exit_mm(tsk);
904 906
905 if (group_dead) 907 if (group_dead)
diff --git a/kernel/fork.c b/kernel/fork.c
index 926e5a68ea9..451cfd35bf2 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -43,6 +43,7 @@
43#include <linux/rmap.h> 43#include <linux/rmap.h>
44#include <linux/acct.h> 44#include <linux/acct.h>
45#include <linux/cn_proc.h> 45#include <linux/cn_proc.h>
46#include <linux/delayacct.h>
46 47
47#include <asm/pgtable.h> 48#include <asm/pgtable.h>
48#include <asm/pgalloc.h> 49#include <asm/pgalloc.h>
@@ -1000,6 +1001,7 @@ static struct task_struct *copy_process(unsigned long clone_flags,
1000 goto bad_fork_cleanup_put_domain; 1001 goto bad_fork_cleanup_put_domain;
1001 1002
1002 p->did_exec = 0; 1003 p->did_exec = 0;
1004 delayacct_tsk_init(p); /* Must remain after dup_task_struct() */
1003 copy_flags(clone_flags, p); 1005 copy_flags(clone_flags, p);
1004 p->pid = pid; 1006 p->pid = pid;
1005 retval = -EFAULT; 1007 retval = -EFAULT;