diff options
Diffstat (limited to 'include/linux')
-rw-r--r-- | include/linux/init_task.h | 11 | ||||
-rw-r--r-- | include/linux/kernel_stat.h | 8 | ||||
-rw-r--r-- | include/linux/perf_counter.h | 305 | ||||
-rw-r--r-- | include/linux/prctl.h | 3 | ||||
-rw-r--r-- | include/linux/sched.h | 14 | ||||
-rw-r--r-- | include/linux/syscalls.h | 5 |
6 files changed, 345 insertions, 1 deletions
diff --git a/include/linux/init_task.h b/include/linux/init_task.h index af1de95e711e..219748d00262 100644 --- a/include/linux/init_task.h +++ b/include/linux/init_task.h | |||
@@ -120,6 +120,16 @@ extern struct group_info init_groups; | |||
120 | 120 | ||
121 | extern struct cred init_cred; | 121 | extern struct cred init_cred; |
122 | 122 | ||
123 | #ifdef CONFIG_PERF_COUNTERS | ||
124 | # define INIT_PERF_COUNTERS(tsk) \ | ||
125 | .perf_counter_ctx.counter_list = \ | ||
126 | LIST_HEAD_INIT(tsk.perf_counter_ctx.counter_list), \ | ||
127 | .perf_counter_ctx.lock = \ | ||
128 | __SPIN_LOCK_UNLOCKED(tsk.perf_counter_ctx.lock), | ||
129 | #else | ||
130 | # define INIT_PERF_COUNTERS(tsk) | ||
131 | #endif | ||
132 | |||
123 | /* | 133 | /* |
124 | * INIT_TASK is used to set up the first task table, touch at | 134 | * INIT_TASK is used to set up the first task table, touch at |
125 | * your own risk!. Base=0, limit=0x1fffff (=2MB) | 135 | * your own risk!. Base=0, limit=0x1fffff (=2MB) |
@@ -185,6 +195,7 @@ extern struct cred init_cred; | |||
185 | INIT_IDS \ | 195 | INIT_IDS \ |
186 | INIT_TRACE_IRQFLAGS \ | 196 | INIT_TRACE_IRQFLAGS \ |
187 | INIT_LOCKDEP \ | 197 | INIT_LOCKDEP \ |
198 | INIT_PERF_COUNTERS(tsk) \ | ||
188 | } | 199 | } |
189 | 200 | ||
190 | 201 | ||
diff --git a/include/linux/kernel_stat.h b/include/linux/kernel_stat.h index 0c8b89f28a95..b6d2887a5d88 100644 --- a/include/linux/kernel_stat.h +++ b/include/linux/kernel_stat.h | |||
@@ -81,7 +81,15 @@ static inline unsigned int kstat_irqs(unsigned int irq) | |||
81 | return sum; | 81 | return sum; |
82 | } | 82 | } |
83 | 83 | ||
84 | |||
85 | /* | ||
86 | * Lock/unlock the current runqueue - to extract task statistics: | ||
87 | */ | ||
88 | extern void curr_rq_lock_irq_save(unsigned long *flags); | ||
89 | extern void curr_rq_unlock_irq_restore(unsigned long *flags); | ||
90 | extern unsigned long long __task_delta_exec(struct task_struct *tsk, int update); | ||
84 | extern unsigned long long task_delta_exec(struct task_struct *); | 91 | extern unsigned long long task_delta_exec(struct task_struct *); |
92 | |||
85 | extern void account_user_time(struct task_struct *, cputime_t, cputime_t); | 93 | extern void account_user_time(struct task_struct *, cputime_t, cputime_t); |
86 | extern void account_system_time(struct task_struct *, int, cputime_t, cputime_t); | 94 | extern void account_system_time(struct task_struct *, int, cputime_t, cputime_t); |
87 | extern void account_steal_time(cputime_t); | 95 | extern void account_steal_time(cputime_t); |
diff --git a/include/linux/perf_counter.h b/include/linux/perf_counter.h new file mode 100644 index 000000000000..dde564517b66 --- /dev/null +++ b/include/linux/perf_counter.h | |||
@@ -0,0 +1,305 @@ | |||
1 | /* | ||
2 | * Performance counters: | ||
3 | * | ||
4 | * Copyright(C) 2008, Thomas Gleixner <tglx@linutronix.de> | ||
5 | * Copyright(C) 2008, Red Hat, Inc., Ingo Molnar | ||
6 | * | ||
7 | * Data type definitions, declarations, prototypes. | ||
8 | * | ||
9 | * Started by: Thomas Gleixner and Ingo Molnar | ||
10 | * | ||
11 | * For licencing details see kernel-base/COPYING | ||
12 | */ | ||
13 | #ifndef _LINUX_PERF_COUNTER_H | ||
14 | #define _LINUX_PERF_COUNTER_H | ||
15 | |||
16 | #include <linux/types.h> | ||
17 | #include <linux/ioctl.h> | ||
18 | |||
19 | /* | ||
20 | * User-space ABI bits: | ||
21 | */ | ||
22 | |||
23 | /* | ||
24 | * Generalized performance counter event types, used by the hw_event.type | ||
25 | * parameter of the sys_perf_counter_open() syscall: | ||
26 | */ | ||
27 | enum hw_event_types { | ||
28 | /* | ||
29 | * Common hardware events, generalized by the kernel: | ||
30 | */ | ||
31 | PERF_COUNT_CPU_CYCLES = 0, | ||
32 | PERF_COUNT_INSTRUCTIONS = 1, | ||
33 | PERF_COUNT_CACHE_REFERENCES = 2, | ||
34 | PERF_COUNT_CACHE_MISSES = 3, | ||
35 | PERF_COUNT_BRANCH_INSTRUCTIONS = 4, | ||
36 | PERF_COUNT_BRANCH_MISSES = 5, | ||
37 | PERF_COUNT_BUS_CYCLES = 6, | ||
38 | |||
39 | PERF_HW_EVENTS_MAX = 7, | ||
40 | |||
41 | /* | ||
42 | * Special "software" counters provided by the kernel, even if | ||
43 | * the hardware does not support performance counters. These | ||
44 | * counters measure various physical and sw events of the | ||
45 | * kernel (and allow the profiling of them as well): | ||
46 | */ | ||
47 | PERF_COUNT_CPU_CLOCK = -1, | ||
48 | PERF_COUNT_TASK_CLOCK = -2, | ||
49 | PERF_COUNT_PAGE_FAULTS = -3, | ||
50 | PERF_COUNT_CONTEXT_SWITCHES = -4, | ||
51 | PERF_COUNT_CPU_MIGRATIONS = -5, | ||
52 | |||
53 | PERF_SW_EVENTS_MIN = -6, | ||
54 | }; | ||
55 | |||
56 | /* | ||
57 | * IRQ-notification data record type: | ||
58 | */ | ||
59 | enum perf_counter_record_type { | ||
60 | PERF_RECORD_SIMPLE = 0, | ||
61 | PERF_RECORD_IRQ = 1, | ||
62 | PERF_RECORD_GROUP = 2, | ||
63 | }; | ||
64 | |||
65 | /* | ||
66 | * Hardware event to monitor via a performance monitoring counter: | ||
67 | */ | ||
68 | struct perf_counter_hw_event { | ||
69 | __s64 type; | ||
70 | |||
71 | __u64 irq_period; | ||
72 | __u64 record_type; | ||
73 | __u64 read_format; | ||
74 | |||
75 | __u64 disabled : 1, /* off by default */ | ||
76 | nmi : 1, /* NMI sampling */ | ||
77 | raw : 1, /* raw event type */ | ||
78 | inherit : 1, /* children inherit it */ | ||
79 | pinned : 1, /* must always be on PMU */ | ||
80 | exclusive : 1, /* only group on PMU */ | ||
81 | exclude_user : 1, /* don't count user */ | ||
82 | exclude_kernel : 1, /* ditto kernel */ | ||
83 | exclude_hv : 1, /* ditto hypervisor */ | ||
84 | exclude_idle : 1, /* don't count when idle */ | ||
85 | |||
86 | __reserved_1 : 54; | ||
87 | |||
88 | __u32 extra_config_len; | ||
89 | __u32 __reserved_4; | ||
90 | |||
91 | __u64 __reserved_2; | ||
92 | __u64 __reserved_3; | ||
93 | }; | ||
94 | |||
95 | /* | ||
96 | * Ioctls that can be done on a perf counter fd: | ||
97 | */ | ||
98 | #define PERF_COUNTER_IOC_ENABLE _IO('$', 0) | ||
99 | #define PERF_COUNTER_IOC_DISABLE _IO('$', 1) | ||
100 | |||
101 | #ifdef __KERNEL__ | ||
102 | /* | ||
103 | * Kernel-internal data types and definitions: | ||
104 | */ | ||
105 | |||
106 | #ifdef CONFIG_PERF_COUNTERS | ||
107 | # include <asm/perf_counter.h> | ||
108 | #endif | ||
109 | |||
110 | #include <linux/list.h> | ||
111 | #include <linux/mutex.h> | ||
112 | #include <linux/rculist.h> | ||
113 | #include <linux/rcupdate.h> | ||
114 | #include <linux/spinlock.h> | ||
115 | #include <asm/atomic.h> | ||
116 | |||
117 | struct task_struct; | ||
118 | |||
119 | /** | ||
120 | * struct hw_perf_counter - performance counter hardware details: | ||
121 | */ | ||
122 | struct hw_perf_counter { | ||
123 | #ifdef CONFIG_PERF_COUNTERS | ||
124 | u64 config; | ||
125 | unsigned long config_base; | ||
126 | unsigned long counter_base; | ||
127 | int nmi; | ||
128 | unsigned int idx; | ||
129 | atomic64_t prev_count; | ||
130 | u64 irq_period; | ||
131 | atomic64_t period_left; | ||
132 | #endif | ||
133 | }; | ||
134 | |||
135 | /* | ||
136 | * Hardcoded buffer length limit for now, for IRQ-fed events: | ||
137 | */ | ||
138 | #define PERF_DATA_BUFLEN 2048 | ||
139 | |||
140 | /** | ||
141 | * struct perf_data - performance counter IRQ data sampling ... | ||
142 | */ | ||
143 | struct perf_data { | ||
144 | int len; | ||
145 | int rd_idx; | ||
146 | int overrun; | ||
147 | u8 data[PERF_DATA_BUFLEN]; | ||
148 | }; | ||
149 | |||
150 | struct perf_counter; | ||
151 | |||
152 | /** | ||
153 | * struct hw_perf_counter_ops - performance counter hw ops | ||
154 | */ | ||
155 | struct hw_perf_counter_ops { | ||
156 | int (*enable) (struct perf_counter *counter); | ||
157 | void (*disable) (struct perf_counter *counter); | ||
158 | void (*read) (struct perf_counter *counter); | ||
159 | }; | ||
160 | |||
161 | /** | ||
162 | * enum perf_counter_active_state - the states of a counter | ||
163 | */ | ||
164 | enum perf_counter_active_state { | ||
165 | PERF_COUNTER_STATE_ERROR = -2, | ||
166 | PERF_COUNTER_STATE_OFF = -1, | ||
167 | PERF_COUNTER_STATE_INACTIVE = 0, | ||
168 | PERF_COUNTER_STATE_ACTIVE = 1, | ||
169 | }; | ||
170 | |||
171 | struct file; | ||
172 | |||
173 | /** | ||
174 | * struct perf_counter - performance counter kernel representation: | ||
175 | */ | ||
176 | struct perf_counter { | ||
177 | #ifdef CONFIG_PERF_COUNTERS | ||
178 | struct list_head list_entry; | ||
179 | struct list_head sibling_list; | ||
180 | struct perf_counter *group_leader; | ||
181 | const struct hw_perf_counter_ops *hw_ops; | ||
182 | |||
183 | enum perf_counter_active_state state; | ||
184 | enum perf_counter_active_state prev_state; | ||
185 | atomic64_t count; | ||
186 | |||
187 | struct perf_counter_hw_event hw_event; | ||
188 | struct hw_perf_counter hw; | ||
189 | |||
190 | struct perf_counter_context *ctx; | ||
191 | struct task_struct *task; | ||
192 | struct file *filp; | ||
193 | |||
194 | struct perf_counter *parent; | ||
195 | struct list_head child_list; | ||
196 | |||
197 | /* | ||
198 | * Protect attach/detach and child_list: | ||
199 | */ | ||
200 | struct mutex mutex; | ||
201 | |||
202 | int oncpu; | ||
203 | int cpu; | ||
204 | |||
205 | /* read() / irq related data */ | ||
206 | wait_queue_head_t waitq; | ||
207 | /* optional: for NMIs */ | ||
208 | int wakeup_pending; | ||
209 | struct perf_data *irqdata; | ||
210 | struct perf_data *usrdata; | ||
211 | struct perf_data data[2]; | ||
212 | #endif | ||
213 | }; | ||
214 | |||
215 | /** | ||
216 | * struct perf_counter_context - counter context structure | ||
217 | * | ||
218 | * Used as a container for task counters and CPU counters as well: | ||
219 | */ | ||
220 | struct perf_counter_context { | ||
221 | #ifdef CONFIG_PERF_COUNTERS | ||
222 | /* | ||
223 | * Protect the states of the counters in the list, | ||
224 | * nr_active, and the list: | ||
225 | */ | ||
226 | spinlock_t lock; | ||
227 | /* | ||
228 | * Protect the list of counters. Locking either mutex or lock | ||
229 | * is sufficient to ensure the list doesn't change; to change | ||
230 | * the list you need to lock both the mutex and the spinlock. | ||
231 | */ | ||
232 | struct mutex mutex; | ||
233 | |||
234 | struct list_head counter_list; | ||
235 | int nr_counters; | ||
236 | int nr_active; | ||
237 | int is_active; | ||
238 | struct task_struct *task; | ||
239 | #endif | ||
240 | }; | ||
241 | |||
242 | /** | ||
243 | * struct perf_counter_cpu_context - per cpu counter context structure | ||
244 | */ | ||
245 | struct perf_cpu_context { | ||
246 | struct perf_counter_context ctx; | ||
247 | struct perf_counter_context *task_ctx; | ||
248 | int active_oncpu; | ||
249 | int max_pertask; | ||
250 | int exclusive; | ||
251 | }; | ||
252 | |||
253 | /* | ||
254 | * Set by architecture code: | ||
255 | */ | ||
256 | extern int perf_max_counters; | ||
257 | |||
258 | #ifdef CONFIG_PERF_COUNTERS | ||
259 | extern const struct hw_perf_counter_ops * | ||
260 | hw_perf_counter_init(struct perf_counter *counter); | ||
261 | |||
262 | extern void perf_counter_task_sched_in(struct task_struct *task, int cpu); | ||
263 | extern void perf_counter_task_sched_out(struct task_struct *task, int cpu); | ||
264 | extern void perf_counter_task_tick(struct task_struct *task, int cpu); | ||
265 | extern void perf_counter_init_task(struct task_struct *child); | ||
266 | extern void perf_counter_exit_task(struct task_struct *child); | ||
267 | extern void perf_counter_notify(struct pt_regs *regs); | ||
268 | extern void perf_counter_print_debug(void); | ||
269 | extern void perf_counter_unthrottle(void); | ||
270 | extern u64 hw_perf_save_disable(void); | ||
271 | extern void hw_perf_restore(u64 ctrl); | ||
272 | extern int perf_counter_task_disable(void); | ||
273 | extern int perf_counter_task_enable(void); | ||
274 | extern int hw_perf_group_sched_in(struct perf_counter *group_leader, | ||
275 | struct perf_cpu_context *cpuctx, | ||
276 | struct perf_counter_context *ctx, int cpu); | ||
277 | |||
278 | /* | ||
279 | * Return 1 for a software counter, 0 for a hardware counter | ||
280 | */ | ||
281 | static inline int is_software_counter(struct perf_counter *counter) | ||
282 | { | ||
283 | return !counter->hw_event.raw && counter->hw_event.type < 0; | ||
284 | } | ||
285 | |||
286 | #else | ||
287 | static inline void | ||
288 | perf_counter_task_sched_in(struct task_struct *task, int cpu) { } | ||
289 | static inline void | ||
290 | perf_counter_task_sched_out(struct task_struct *task, int cpu) { } | ||
291 | static inline void | ||
292 | perf_counter_task_tick(struct task_struct *task, int cpu) { } | ||
293 | static inline void perf_counter_init_task(struct task_struct *child) { } | ||
294 | static inline void perf_counter_exit_task(struct task_struct *child) { } | ||
295 | static inline void perf_counter_notify(struct pt_regs *regs) { } | ||
296 | static inline void perf_counter_print_debug(void) { } | ||
297 | static inline void perf_counter_unthrottle(void) { } | ||
298 | static inline void hw_perf_restore(u64 ctrl) { } | ||
299 | static inline u64 hw_perf_save_disable(void) { return 0; } | ||
300 | static inline int perf_counter_task_disable(void) { return -EINVAL; } | ||
301 | static inline int perf_counter_task_enable(void) { return -EINVAL; } | ||
302 | #endif | ||
303 | |||
304 | #endif /* __KERNEL__ */ | ||
305 | #endif /* _LINUX_PERF_COUNTER_H */ | ||
diff --git a/include/linux/prctl.h b/include/linux/prctl.h index 48d887e3c6e7..b00df4c79c63 100644 --- a/include/linux/prctl.h +++ b/include/linux/prctl.h | |||
@@ -85,4 +85,7 @@ | |||
85 | #define PR_SET_TIMERSLACK 29 | 85 | #define PR_SET_TIMERSLACK 29 |
86 | #define PR_GET_TIMERSLACK 30 | 86 | #define PR_GET_TIMERSLACK 30 |
87 | 87 | ||
88 | #define PR_TASK_PERF_COUNTERS_DISABLE 31 | ||
89 | #define PR_TASK_PERF_COUNTERS_ENABLE 32 | ||
90 | |||
88 | #endif /* _LINUX_PRCTL_H */ | 91 | #endif /* _LINUX_PRCTL_H */ |
diff --git a/include/linux/sched.h b/include/linux/sched.h index b94f3541f67b..75b2fc5306d8 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h | |||
@@ -71,6 +71,7 @@ struct sched_param { | |||
71 | #include <linux/path.h> | 71 | #include <linux/path.h> |
72 | #include <linux/compiler.h> | 72 | #include <linux/compiler.h> |
73 | #include <linux/completion.h> | 73 | #include <linux/completion.h> |
74 | #include <linux/perf_counter.h> | ||
74 | #include <linux/pid.h> | 75 | #include <linux/pid.h> |
75 | #include <linux/percpu.h> | 76 | #include <linux/percpu.h> |
76 | #include <linux/topology.h> | 77 | #include <linux/topology.h> |
@@ -137,6 +138,8 @@ extern unsigned long nr_running(void); | |||
137 | extern unsigned long nr_uninterruptible(void); | 138 | extern unsigned long nr_uninterruptible(void); |
138 | extern unsigned long nr_active(void); | 139 | extern unsigned long nr_active(void); |
139 | extern unsigned long nr_iowait(void); | 140 | extern unsigned long nr_iowait(void); |
141 | extern u64 cpu_nr_switches(int cpu); | ||
142 | extern u64 cpu_nr_migrations(int cpu); | ||
140 | 143 | ||
141 | extern unsigned long get_parent_ip(unsigned long addr); | 144 | extern unsigned long get_parent_ip(unsigned long addr); |
142 | 145 | ||
@@ -1048,9 +1051,10 @@ struct sched_entity { | |||
1048 | u64 last_wakeup; | 1051 | u64 last_wakeup; |
1049 | u64 avg_overlap; | 1052 | u64 avg_overlap; |
1050 | 1053 | ||
1054 | u64 nr_migrations; | ||
1055 | |||
1051 | u64 start_runtime; | 1056 | u64 start_runtime; |
1052 | u64 avg_wakeup; | 1057 | u64 avg_wakeup; |
1053 | u64 nr_migrations; | ||
1054 | 1058 | ||
1055 | #ifdef CONFIG_SCHEDSTATS | 1059 | #ifdef CONFIG_SCHEDSTATS |
1056 | u64 wait_start; | 1060 | u64 wait_start; |
@@ -1372,6 +1376,7 @@ struct task_struct { | |||
1372 | struct list_head pi_state_list; | 1376 | struct list_head pi_state_list; |
1373 | struct futex_pi_state *pi_state_cache; | 1377 | struct futex_pi_state *pi_state_cache; |
1374 | #endif | 1378 | #endif |
1379 | struct perf_counter_context perf_counter_ctx; | ||
1375 | #ifdef CONFIG_NUMA | 1380 | #ifdef CONFIG_NUMA |
1376 | struct mempolicy *mempolicy; | 1381 | struct mempolicy *mempolicy; |
1377 | short il_next; | 1382 | short il_next; |
@@ -2380,6 +2385,13 @@ static inline void inc_syscw(struct task_struct *tsk) | |||
2380 | #define TASK_SIZE_OF(tsk) TASK_SIZE | 2385 | #define TASK_SIZE_OF(tsk) TASK_SIZE |
2381 | #endif | 2386 | #endif |
2382 | 2387 | ||
2388 | /* | ||
2389 | * Call the function if the target task is executing on a CPU right now: | ||
2390 | */ | ||
2391 | extern void task_oncpu_function_call(struct task_struct *p, | ||
2392 | void (*func) (void *info), void *info); | ||
2393 | |||
2394 | |||
2383 | #ifdef CONFIG_MM_OWNER | 2395 | #ifdef CONFIG_MM_OWNER |
2384 | extern void mm_update_next_owner(struct mm_struct *mm); | 2396 | extern void mm_update_next_owner(struct mm_struct *mm); |
2385 | extern void mm_init_owner(struct mm_struct *mm, struct task_struct *p); | 2397 | extern void mm_init_owner(struct mm_struct *mm, struct task_struct *p); |
diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h index 6470f74074af..471143bf2aae 100644 --- a/include/linux/syscalls.h +++ b/include/linux/syscalls.h | |||
@@ -55,6 +55,7 @@ struct compat_timeval; | |||
55 | struct robust_list_head; | 55 | struct robust_list_head; |
56 | struct getcpu_cache; | 56 | struct getcpu_cache; |
57 | struct old_linux_dirent; | 57 | struct old_linux_dirent; |
58 | struct perf_counter_hw_event; | ||
58 | 59 | ||
59 | #include <linux/types.h> | 60 | #include <linux/types.h> |
60 | #include <linux/aio_abi.h> | 61 | #include <linux/aio_abi.h> |
@@ -754,4 +755,8 @@ asmlinkage long sys_pipe(int __user *); | |||
754 | 755 | ||
755 | int kernel_execve(const char *filename, char *const argv[], char *const envp[]); | 756 | int kernel_execve(const char *filename, char *const argv[], char *const envp[]); |
756 | 757 | ||
758 | |||
759 | asmlinkage long sys_perf_counter_open( | ||
760 | const struct perf_counter_hw_event __user *hw_event_uptr, | ||
761 | pid_t pid, int cpu, int group_fd, unsigned long flags); | ||
757 | #endif | 762 | #endif |