diff options
author | Shailabh Nagar <nagar@watson.ibm.com> | 2006-07-14 03:24:47 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-07-15 00:53:57 -0400 |
commit | f9fd8914c1acca0d98b69d831b128d5b52f03c51 (patch) | |
tree | 18c2506bb31e49a9e2c4a483d37b0394c815fe9d /include/linux | |
parent | c8924363da07aec213e5d359f23eeae1fff91951 (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.h | 4 | ||||
-rw-r--r-- | include/linux/taskstats_kern.h | 27 |
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 | ||
14 | enum { | ||
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 |
20 | extern kmem_cache_t *taskstats_cache; | 15 | extern kmem_cache_t *taskstats_cache; |
21 | extern struct mutex taskstats_exit_mutex; | 16 | extern struct mutex taskstats_exit_mutex; |
22 | 17 | ||
23 | static 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 | |||
31 | static 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 | |||
38 | static inline void taskstats_exit_free(struct taskstats *tidstats) | 18 | static 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 | ||
85 | extern void taskstats_exit_send(struct task_struct *, struct taskstats *, int); | 65 | extern void taskstats_exit_alloc(struct taskstats **, unsigned int *); |
66 | extern void taskstats_exit_send(struct task_struct *, struct taskstats *, int, unsigned int); | ||
86 | extern void taskstats_init_early(void); | 67 | extern void taskstats_init_early(void); |
87 | extern void taskstats_tgid_alloc(struct signal_struct *); | 68 | extern void taskstats_tgid_alloc(struct signal_struct *); |
88 | #else | 69 | #else |
89 | static inline void taskstats_exit_alloc(struct taskstats **ptidstats) | 70 | static inline void taskstats_exit_alloc(struct taskstats **ptidstats, unsigned int *mycpu) |
90 | {} | 71 | {} |
91 | static inline void taskstats_exit_free(struct taskstats *ptidstats) | 72 | static inline void taskstats_exit_free(struct taskstats *ptidstats) |
92 | {} | 73 | {} |
93 | static inline void taskstats_exit_send(struct task_struct *tsk, | 74 | static 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 | {} |
97 | static inline void taskstats_tgid_init(struct signal_struct *sig) | 78 | static inline void taskstats_tgid_init(struct signal_struct *sig) |
98 | {} | 79 | {} |