diff options
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/delayacct.c | 62 | ||||
-rw-r--r-- | kernel/taskstats.c | 16 |
2 files changed, 72 insertions, 6 deletions
diff --git a/kernel/delayacct.c b/kernel/delayacct.c index 3546b0800f9f..1be274a462ca 100644 --- a/kernel/delayacct.c +++ b/kernel/delayacct.c | |||
@@ -41,6 +41,10 @@ void delayacct_init(void) | |||
41 | 41 | ||
42 | void __delayacct_tsk_init(struct task_struct *tsk) | 42 | void __delayacct_tsk_init(struct task_struct *tsk) |
43 | { | 43 | { |
44 | spin_lock_init(&tsk->delays_lock); | ||
45 | /* No need to acquire tsk->delays_lock for allocation here unless | ||
46 | __delayacct_tsk_init called after tsk is attached to tasklist | ||
47 | */ | ||
44 | tsk->delays = kmem_cache_zalloc(delayacct_cache, SLAB_KERNEL); | 48 | tsk->delays = kmem_cache_zalloc(delayacct_cache, SLAB_KERNEL); |
45 | if (tsk->delays) | 49 | if (tsk->delays) |
46 | spin_lock_init(&tsk->delays->lock); | 50 | spin_lock_init(&tsk->delays->lock); |
@@ -48,8 +52,11 @@ void __delayacct_tsk_init(struct task_struct *tsk) | |||
48 | 52 | ||
49 | void __delayacct_tsk_exit(struct task_struct *tsk) | 53 | void __delayacct_tsk_exit(struct task_struct *tsk) |
50 | { | 54 | { |
51 | kmem_cache_free(delayacct_cache, tsk->delays); | 55 | struct task_delay_info *delays = tsk->delays; |
56 | spin_lock(&tsk->delays_lock); | ||
52 | tsk->delays = NULL; | 57 | tsk->delays = NULL; |
58 | spin_unlock(&tsk->delays_lock); | ||
59 | kmem_cache_free(delayacct_cache, delays); | ||
53 | } | 60 | } |
54 | 61 | ||
55 | /* | 62 | /* |
@@ -104,3 +111,56 @@ void __delayacct_blkio_end(void) | |||
104 | ¤t->delays->blkio_delay, | 111 | ¤t->delays->blkio_delay, |
105 | ¤t->delays->blkio_count); | 112 | ¤t->delays->blkio_count); |
106 | } | 113 | } |
114 | |||
115 | int __delayacct_add_tsk(struct taskstats *d, struct task_struct *tsk) | ||
116 | { | ||
117 | s64 tmp; | ||
118 | struct timespec ts; | ||
119 | unsigned long t1,t2,t3; | ||
120 | |||
121 | spin_lock(&tsk->delays_lock); | ||
122 | |||
123 | /* Though tsk->delays accessed later, early exit avoids | ||
124 | * unnecessary returning of other data | ||
125 | */ | ||
126 | if (!tsk->delays) | ||
127 | goto done; | ||
128 | |||
129 | tmp = (s64)d->cpu_run_real_total; | ||
130 | cputime_to_timespec(tsk->utime + tsk->stime, &ts); | ||
131 | tmp += timespec_to_ns(&ts); | ||
132 | d->cpu_run_real_total = (tmp < (s64)d->cpu_run_real_total) ? 0 : tmp; | ||
133 | |||
134 | /* | ||
135 | * No locking available for sched_info (and too expensive to add one) | ||
136 | * Mitigate by taking snapshot of values | ||
137 | */ | ||
138 | t1 = tsk->sched_info.pcnt; | ||
139 | t2 = tsk->sched_info.run_delay; | ||
140 | t3 = tsk->sched_info.cpu_time; | ||
141 | |||
142 | d->cpu_count += t1; | ||
143 | |||
144 | jiffies_to_timespec(t2, &ts); | ||
145 | tmp = (s64)d->cpu_delay_total + timespec_to_ns(&ts); | ||
146 | d->cpu_delay_total = (tmp < (s64)d->cpu_delay_total) ? 0 : tmp; | ||
147 | |||
148 | tmp = (s64)d->cpu_run_virtual_total + (s64)jiffies_to_usecs(t3) * 1000; | ||
149 | d->cpu_run_virtual_total = | ||
150 | (tmp < (s64)d->cpu_run_virtual_total) ? 0 : tmp; | ||
151 | |||
152 | /* zero XXX_total, non-zero XXX_count implies XXX stat overflowed */ | ||
153 | |||
154 | spin_lock(&tsk->delays->lock); | ||
155 | tmp = d->blkio_delay_total + tsk->delays->blkio_delay; | ||
156 | d->blkio_delay_total = (tmp < d->blkio_delay_total) ? 0 : tmp; | ||
157 | tmp = d->swapin_delay_total + tsk->delays->swapin_delay; | ||
158 | d->swapin_delay_total = (tmp < d->swapin_delay_total) ? 0 : tmp; | ||
159 | d->blkio_count += tsk->delays->blkio_count; | ||
160 | d->swapin_count += tsk->delays->swapin_count; | ||
161 | spin_unlock(&tsk->delays->lock); | ||
162 | |||
163 | done: | ||
164 | spin_unlock(&tsk->delays_lock); | ||
165 | return 0; | ||
166 | } | ||
diff --git a/kernel/taskstats.c b/kernel/taskstats.c index 82ec9137d908..ea9506de3b85 100644 --- a/kernel/taskstats.c +++ b/kernel/taskstats.c | |||
@@ -18,13 +18,13 @@ | |||
18 | 18 | ||
19 | #include <linux/kernel.h> | 19 | #include <linux/kernel.h> |
20 | #include <linux/taskstats_kern.h> | 20 | #include <linux/taskstats_kern.h> |
21 | #include <linux/delayacct.h> | ||
21 | #include <net/genetlink.h> | 22 | #include <net/genetlink.h> |
22 | #include <asm/atomic.h> | 23 | #include <asm/atomic.h> |
23 | 24 | ||
24 | static DEFINE_PER_CPU(__u32, taskstats_seqnum) = { 0 }; | 25 | static DEFINE_PER_CPU(__u32, taskstats_seqnum) = { 0 }; |
25 | static int family_registered; | 26 | static int family_registered; |
26 | kmem_cache_t *taskstats_cache; | 27 | kmem_cache_t *taskstats_cache; |
27 | static DEFINE_MUTEX(taskstats_exit_mutex); | ||
28 | 28 | ||
29 | static struct genl_family family = { | 29 | static struct genl_family family = { |
30 | .id = GENL_ID_GENERATE, | 30 | .id = GENL_ID_GENERATE, |
@@ -120,7 +120,10 @@ static int fill_pid(pid_t pid, struct task_struct *pidtsk, | |||
120 | * goto err; | 120 | * goto err; |
121 | */ | 121 | */ |
122 | 122 | ||
123 | err: | 123 | rc = delayacct_add_tsk(stats, tsk); |
124 | stats->version = TASKSTATS_VERSION; | ||
125 | |||
126 | /* Define err: label here if needed */ | ||
124 | put_task_struct(tsk); | 127 | put_task_struct(tsk); |
125 | return rc; | 128 | return rc; |
126 | 129 | ||
@@ -152,8 +155,14 @@ static int fill_tgid(pid_t tgid, struct task_struct *tgidtsk, | |||
152 | * break; | 155 | * break; |
153 | */ | 156 | */ |
154 | 157 | ||
158 | rc = delayacct_add_tsk(stats, tsk); | ||
159 | if (rc) | ||
160 | break; | ||
161 | |||
155 | } while_each_thread(first, tsk); | 162 | } while_each_thread(first, tsk); |
156 | read_unlock(&tasklist_lock); | 163 | read_unlock(&tasklist_lock); |
164 | stats->version = TASKSTATS_VERSION; | ||
165 | |||
157 | 166 | ||
158 | /* | 167 | /* |
159 | * Accounting subsytems can also add calls here if they don't | 168 | * Accounting subsytems can also add calls here if they don't |
@@ -233,8 +242,6 @@ void taskstats_exit_send(struct task_struct *tsk, struct taskstats *tidstats, | |||
233 | if (!family_registered || !tidstats) | 242 | if (!family_registered || !tidstats) |
234 | return; | 243 | return; |
235 | 244 | ||
236 | mutex_lock(&taskstats_exit_mutex); | ||
237 | |||
238 | is_thread_group = !thread_group_empty(tsk); | 245 | is_thread_group = !thread_group_empty(tsk); |
239 | rc = 0; | 246 | rc = 0; |
240 | 247 | ||
@@ -292,7 +299,6 @@ nla_put_failure: | |||
292 | err_skb: | 299 | err_skb: |
293 | nlmsg_free(rep_skb); | 300 | nlmsg_free(rep_skb); |
294 | ret: | 301 | ret: |
295 | mutex_unlock(&taskstats_exit_mutex); | ||
296 | return; | 302 | return; |
297 | } | 303 | } |
298 | 304 | ||