aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/taskstats.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/taskstats.c')
-rw-r--r--kernel/taskstats.c98
1 files changed, 66 insertions, 32 deletions
diff --git a/kernel/taskstats.c b/kernel/taskstats.c
index ea9506de3b85..4a0a5022b299 100644
--- a/kernel/taskstats.c
+++ b/kernel/taskstats.c
@@ -132,46 +132,79 @@ static int fill_pid(pid_t pid, struct task_struct *pidtsk,
132static int fill_tgid(pid_t tgid, struct task_struct *tgidtsk, 132static int fill_tgid(pid_t tgid, struct task_struct *tgidtsk,
133 struct taskstats *stats) 133 struct taskstats *stats)
134{ 134{
135 int rc;
136 struct task_struct *tsk, *first; 135 struct task_struct *tsk, *first;
136 unsigned long flags;
137 137
138 /*
139 * Add additional stats from live tasks except zombie thread group
140 * leaders who are already counted with the dead tasks
141 */
138 first = tgidtsk; 142 first = tgidtsk;
139 read_lock(&tasklist_lock);
140 if (!first) { 143 if (!first) {
144 read_lock(&tasklist_lock);
141 first = find_task_by_pid(tgid); 145 first = find_task_by_pid(tgid);
142 if (!first) { 146 if (!first) {
143 read_unlock(&tasklist_lock); 147 read_unlock(&tasklist_lock);
144 return -ESRCH; 148 return -ESRCH;
145 } 149 }
146 } 150 get_task_struct(first);
151 read_unlock(&tasklist_lock);
152 } else
153 get_task_struct(first);
154
155 /* Start with stats from dead tasks */
156 spin_lock_irqsave(&first->signal->stats_lock, flags);
157 if (first->signal->stats)
158 memcpy(stats, first->signal->stats, sizeof(*stats));
159 spin_unlock_irqrestore(&first->signal->stats_lock, flags);
160
147 tsk = first; 161 tsk = first;
162 read_lock(&tasklist_lock);
148 do { 163 do {
164 if (tsk->exit_state == EXIT_ZOMBIE && thread_group_leader(tsk))
165 continue;
149 /* 166 /*
150 * Each accounting subsystem adds calls its functions to 167 * Accounting subsystem can call its functions here to
151 * fill in relevant parts of struct taskstsats as follows 168 * fill in relevant parts of struct taskstsats as follows
152 * 169 *
153 * rc = per-task-foo(stats, tsk); 170 * per-task-foo(stats, tsk);
154 * if (rc)
155 * break;
156 */ 171 */
157 172 delayacct_add_tsk(stats, tsk);
158 rc = delayacct_add_tsk(stats, tsk);
159 if (rc)
160 break;
161 173
162 } while_each_thread(first, tsk); 174 } while_each_thread(first, tsk);
163 read_unlock(&tasklist_lock); 175 read_unlock(&tasklist_lock);
164 stats->version = TASKSTATS_VERSION; 176 stats->version = TASKSTATS_VERSION;
165 177
166
167 /* 178 /*
168 * Accounting subsytems can also add calls here if they don't 179 * Accounting subsytems can also add calls here to modify
169 * wish to aggregate statistics for per-tgid stats 180 * fields of taskstats.
170 */ 181 */
171 182
172 return rc; 183 return 0;
184}
185
186
187static void fill_tgid_exit(struct task_struct *tsk)
188{
189 unsigned long flags;
190
191 spin_lock_irqsave(&tsk->signal->stats_lock, flags);
192 if (!tsk->signal->stats)
193 goto ret;
194
195 /*
196 * Each accounting subsystem calls its functions here to
197 * accumalate its per-task stats for tsk, into the per-tgid structure
198 *
199 * per-task-foo(tsk->signal->stats, tsk);
200 */
201 delayacct_add_tsk(tsk->signal->stats, tsk);
202ret:
203 spin_unlock_irqrestore(&tsk->signal->stats_lock, flags);
204 return;
173} 205}
174 206
207
175static int taskstats_send_stats(struct sk_buff *skb, struct genl_info *info) 208static int taskstats_send_stats(struct sk_buff *skb, struct genl_info *info)
176{ 209{
177 int rc = 0; 210 int rc = 0;
@@ -230,7 +263,7 @@ err:
230 263
231/* Send pid data out on exit */ 264/* Send pid data out on exit */
232void taskstats_exit_send(struct task_struct *tsk, struct taskstats *tidstats, 265void taskstats_exit_send(struct task_struct *tsk, struct taskstats *tidstats,
233 struct taskstats *tgidstats) 266 int group_dead)
234{ 267{
235 int rc; 268 int rc;
236 struct sk_buff *rep_skb; 269 struct sk_buff *rep_skb;
@@ -238,13 +271,16 @@ void taskstats_exit_send(struct task_struct *tsk, struct taskstats *tidstats,
238 size_t size; 271 size_t size;
239 int is_thread_group; 272 int is_thread_group;
240 struct nlattr *na; 273 struct nlattr *na;
274 unsigned long flags;
241 275
242 if (!family_registered || !tidstats) 276 if (!family_registered || !tidstats)
243 return; 277 return;
244 278
245 is_thread_group = !thread_group_empty(tsk); 279 spin_lock_irqsave(&tsk->signal->stats_lock, flags);
246 rc = 0; 280 is_thread_group = tsk->signal->stats ? 1 : 0;
281 spin_unlock_irqrestore(&tsk->signal->stats_lock, flags);
247 282
283 rc = 0;
248 /* 284 /*
249 * Size includes space for nested attributes 285 * Size includes space for nested attributes
250 */ 286 */
@@ -268,30 +304,28 @@ void taskstats_exit_send(struct task_struct *tsk, struct taskstats *tidstats,
268 *tidstats); 304 *tidstats);
269 nla_nest_end(rep_skb, na); 305 nla_nest_end(rep_skb, na);
270 306
271 if (!is_thread_group || !tgidstats) { 307 if (!is_thread_group)
272 send_reply(rep_skb, 0, TASKSTATS_MSG_MULTICAST); 308 goto send;
273 goto ret;
274 }
275 309
276 rc = fill_tgid(tsk->pid, tsk, tgidstats);
277 /* 310 /*
278 * If fill_tgid() failed then one probable reason could be that the 311 * tsk has/had a thread group so fill the tsk->signal->stats structure
279 * thread group leader has exited. fill_tgid() will fail, send out 312 * Doesn't matter if tsk is the leader or the last group member leaving
280 * the pid statistics collected earlier.
281 */ 313 */
282 if (rc < 0) { 314
283 send_reply(rep_skb, 0, TASKSTATS_MSG_MULTICAST); 315 fill_tgid_exit(tsk);
284 goto ret; 316 if (!group_dead)
285 } 317 goto send;
286 318
287 na = nla_nest_start(rep_skb, TASKSTATS_TYPE_AGGR_TGID); 319 na = nla_nest_start(rep_skb, TASKSTATS_TYPE_AGGR_TGID);
288 NLA_PUT_U32(rep_skb, TASKSTATS_TYPE_TGID, (u32)tsk->tgid); 320 NLA_PUT_U32(rep_skb, TASKSTATS_TYPE_TGID, (u32)tsk->tgid);
321 /* No locking needed for tsk->signal->stats since group is dead */
289 NLA_PUT_TYPE(rep_skb, struct taskstats, TASKSTATS_TYPE_STATS, 322 NLA_PUT_TYPE(rep_skb, struct taskstats, TASKSTATS_TYPE_STATS,
290 *tgidstats); 323 *tsk->signal->stats);
291 nla_nest_end(rep_skb, na); 324 nla_nest_end(rep_skb, na);
292 325
326send:
293 send_reply(rep_skb, 0, TASKSTATS_MSG_MULTICAST); 327 send_reply(rep_skb, 0, TASKSTATS_MSG_MULTICAST);
294 goto ret; 328 return;
295 329
296nla_put_failure: 330nla_put_failure:
297 genlmsg_cancel(rep_skb, reply); 331 genlmsg_cancel(rep_skb, reply);