diff options
Diffstat (limited to 'kernel/delayacct.c')
-rw-r--r-- | kernel/delayacct.c | 87 |
1 files changed, 87 insertions, 0 deletions
diff --git a/kernel/delayacct.c b/kernel/delayacct.c new file mode 100644 index 000000000000..fbf7f2284952 --- /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 | |||
22 | int delayacct_on __read_mostly; /* Delay accounting turned on/off */ | ||
23 | kmem_cache_t *delayacct_cache; | ||
24 | |||
25 | static int __init delayacct_setup_enable(char *str) | ||
26 | { | ||
27 | delayacct_on = 1; | ||
28 | return 1; | ||
29 | } | ||
30 | __setup("delayacct", delayacct_setup_enable); | ||
31 | |||
32 | void 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 | |||
42 | void __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 | |||
49 | void __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 | |||
60 | static 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 | |||
70 | static 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(¤t->delays->lock); | ||
83 | *total += ns; | ||
84 | (*count)++; | ||
85 | spin_unlock(¤t->delays->lock); | ||
86 | } | ||
87 | |||