diff options
| author | Shailabh Nagar <nagar@watson.ibm.com> | 2006-07-14 03:24:41 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-07-15 00:53:56 -0400 |
| commit | 6f44993fe1d7b2b097f6ac60cd5835c6f5ca0874 (patch) | |
| tree | 0f349f4e6c28cc5d11b7083273543a294c437216 /kernel | |
| parent | c757249af152c59fd74b85e52e8c090acb33d9c0 (diff) | |
[PATCH] per-task-delay-accounting: delay accounting usage of taskstats interface
Usage of taskstats interface by delay accounting.
Signed-off-by: Shailabh Nagar <nagar@us.ibm.com>
Signed-off-by: Balbir Singh <balbir@in.ibm.com>
Cc: Jes Sorensen <jes@sgi.com>
Cc: Peter Chubb <peterc@gelato.unsw.edu.au>
Cc: Erich Focht <efocht@ess.nec.de>
Cc: Levent Serinol <lserinol@gmail.com>
Cc: Jay Lan <jlan@engr.sgi.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
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 | ||
