aboutsummaryrefslogtreecommitdiffstats
path: root/include/linux
diff options
context:
space:
mode:
authorShailabh Nagar <nagar@watson.ibm.com>2006-07-14 03:24:47 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2006-07-15 00:53:57 -0400
commitf9fd8914c1acca0d98b69d831b128d5b52f03c51 (patch)
tree18c2506bb31e49a9e2c4a483d37b0394c815fe9d /include/linux
parentc8924363da07aec213e5d359f23eeae1fff91951 (diff)
[PATCH] per-task delay accounting taskstats interface: control exit data through cpumasks
On systems with a large number of cpus, with even a modest rate of tasks exiting per cpu, the volume of taskstats data sent on thread exit can overflow a userspace listener's buffers. One approach to avoiding overflow is to allow listeners to get data for a limited and specific set of cpus. By scaling the number of listeners and/or the cpus they monitor, userspace can handle the statistical data overload more gracefully. In this patch, each listener registers to listen to a specific set of cpus by specifying a cpumask. The interest is recorded per-cpu. When a task exits on a cpu, its taskstats data is unicast to each listener interested in that cpu. Thanks to Andrew Morton for pointing out the various scalability and general concerns of previous attempts and for suggesting this design. [akpm@osdl.org: build fix] Signed-off-by: Shailabh Nagar <nagar@watson.ibm.com> Signed-off-by: Balbir Singh <balbir@in.ibm.com> Signed-off-by: Chandra Seetharaman <sekharan@us.ibm.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'include/linux')
-rw-r--r--include/linux/taskstats.h4
-rw-r--r--include/linux/taskstats_kern.h27
2 files changed, 6 insertions, 25 deletions
diff --git a/include/linux/taskstats.h b/include/linux/taskstats.h
index c6aeca32348e..f1cb6cddd19d 100644
--- a/include/linux/taskstats.h
+++ b/include/linux/taskstats.h
@@ -91,8 +91,6 @@ struct taskstats {
91}; 91};
92 92
93 93
94#define TASKSTATS_LISTEN_GROUP 0x1
95
96/* 94/*
97 * Commands sent from userspace 95 * Commands sent from userspace
98 * Not versioned. New commands should only be inserted at the enum's end 96 * Not versioned. New commands should only be inserted at the enum's end
@@ -124,6 +122,8 @@ enum {
124 TASKSTATS_CMD_ATTR_UNSPEC = 0, 122 TASKSTATS_CMD_ATTR_UNSPEC = 0,
125 TASKSTATS_CMD_ATTR_PID, 123 TASKSTATS_CMD_ATTR_PID,
126 TASKSTATS_CMD_ATTR_TGID, 124 TASKSTATS_CMD_ATTR_TGID,
125 TASKSTATS_CMD_ATTR_REGISTER_CPUMASK,
126 TASKSTATS_CMD_ATTR_DEREGISTER_CPUMASK,
127 __TASKSTATS_CMD_ATTR_MAX, 127 __TASKSTATS_CMD_ATTR_MAX,
128}; 128};
129 129
diff --git a/include/linux/taskstats_kern.h b/include/linux/taskstats_kern.h
index 2b6adec3a2e4..16894b7edcc8 100644
--- a/include/linux/taskstats_kern.h
+++ b/include/linux/taskstats_kern.h
@@ -11,30 +11,10 @@
11#include <linux/sched.h> 11#include <linux/sched.h>
12#include <net/genetlink.h> 12#include <net/genetlink.h>
13 13
14enum {
15 TASKSTATS_MSG_UNICAST, /* send data only to requester */
16 TASKSTATS_MSG_MULTICAST, /* send data to a group */
17};
18
19#ifdef CONFIG_TASKSTATS 14#ifdef CONFIG_TASKSTATS
20extern kmem_cache_t *taskstats_cache; 15extern kmem_cache_t *taskstats_cache;
21extern struct mutex taskstats_exit_mutex; 16extern struct mutex taskstats_exit_mutex;
22 17
23static inline int taskstats_has_listeners(void)
24{
25 if (!genl_sock)
26 return 0;
27 return netlink_has_listeners(genl_sock, TASKSTATS_LISTEN_GROUP);
28}
29
30
31static inline void taskstats_exit_alloc(struct taskstats **ptidstats)
32{
33 *ptidstats = NULL;
34 if (taskstats_has_listeners())
35 *ptidstats = kmem_cache_zalloc(taskstats_cache, SLAB_KERNEL);
36}
37
38static inline void taskstats_exit_free(struct taskstats *tidstats) 18static inline void taskstats_exit_free(struct taskstats *tidstats)
39{ 19{
40 if (tidstats) 20 if (tidstats)
@@ -82,17 +62,18 @@ static inline void taskstats_tgid_free(struct signal_struct *sig)
82 kmem_cache_free(taskstats_cache, stats); 62 kmem_cache_free(taskstats_cache, stats);
83} 63}
84 64
85extern void taskstats_exit_send(struct task_struct *, struct taskstats *, int); 65extern void taskstats_exit_alloc(struct taskstats **, unsigned int *);
66extern void taskstats_exit_send(struct task_struct *, struct taskstats *, int, unsigned int);
86extern void taskstats_init_early(void); 67extern void taskstats_init_early(void);
87extern void taskstats_tgid_alloc(struct signal_struct *); 68extern void taskstats_tgid_alloc(struct signal_struct *);
88#else 69#else
89static inline void taskstats_exit_alloc(struct taskstats **ptidstats) 70static inline void taskstats_exit_alloc(struct taskstats **ptidstats, unsigned int *mycpu)
90{} 71{}
91static inline void taskstats_exit_free(struct taskstats *ptidstats) 72static inline void taskstats_exit_free(struct taskstats *ptidstats)
92{} 73{}
93static inline void taskstats_exit_send(struct task_struct *tsk, 74static inline void taskstats_exit_send(struct task_struct *tsk,
94 struct taskstats *tidstats, 75 struct taskstats *tidstats,
95 int group_dead) 76 int group_dead, unsigned int cpu)
96{} 77{}
97static inline void taskstats_tgid_init(struct signal_struct *sig) 78static inline void taskstats_tgid_init(struct signal_struct *sig)
98{} 79{}