Linux Kernel
3.7.1
Main Page
Related Pages
Modules
Namespaces
Data Structures
Files
File List
Globals
All
Data Structures
Namespaces
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Macros
Groups
Pages
drivers
oprofile
oprof.c
Go to the documentation of this file.
1
10
#include <linux/kernel.h>
11
#include <linux/module.h>
12
#include <
linux/init.h
>
13
#include <
linux/oprofile.h
>
14
#include <
linux/moduleparam.h
>
15
#include <
linux/workqueue.h
>
16
#include <linux/time.h>
17
#include <
linux/mutex.h
>
18
19
#include "
oprof.h
"
20
#include "
event_buffer.h
"
21
#include "
cpu_buffer.h
"
22
#include "
buffer_sync.h
"
23
#include "
oprofile_stats.h
"
24
25
struct
oprofile_operations
oprofile_ops
;
26
27
unsigned
long
oprofile_started
;
28
unsigned
long
oprofile_backtrace_depth
;
29
static
unsigned
long
is_setup;
30
static
DEFINE_MUTEX
(start_mutex);
31
32
/* timer
33
0 - use performance monitoring hardware if available
34
1 - use the timer int mechanism regardless
35
*/
36
static
int
timer
= 0;
37
38
int
oprofile_setup
(
void
)
39
{
40
int
err
;
41
42
mutex_lock
(&start_mutex);
43
44
if
((err =
alloc_cpu_buffers
()))
45
goto
out
;
46
47
if
((err =
alloc_event_buffer
()))
48
goto
out1;
49
50
if
(
oprofile_ops
.setup && (err =
oprofile_ops
.setup()))
51
goto
out2;
52
53
/* Note even though this starts part of the
54
* profiling overhead, it's necessary to prevent
55
* us missing task deaths and eventually oopsing
56
* when trying to process the event buffer.
57
*/
58
if
(
oprofile_ops
.sync_start) {
59
int
sync_ret =
oprofile_ops
.sync_start();
60
switch
(sync_ret) {
61
case
0:
62
goto
post_sync;
63
case
1:
64
goto
do_generic;
65
case
-1:
66
goto
out3;
67
default
:
68
goto
out3;
69
}
70
}
71
do_generic:
72
if
((err =
sync_start
()))
73
goto
out3;
74
75
post_sync:
76
is_setup = 1;
77
mutex_unlock
(&start_mutex);
78
return
0;
79
80
out3:
81
if
(
oprofile_ops
.shutdown)
82
oprofile_ops
.shutdown();
83
out2:
84
free_event_buffer
();
85
out1:
86
free_cpu_buffers
();
87
out
:
88
mutex_unlock
(&start_mutex);
89
return
err
;
90
}
91
92
#ifdef CONFIG_OPROFILE_EVENT_MULTIPLEX
93
94
static
void
switch_worker(
struct
work_struct
*
work
);
95
static
DECLARE_DELAYED_WORK
(switch_work, switch_worker);
96
97
static
void
start_switch_worker(
void
)
98
{
99
if
(
oprofile_ops
.switch_events)
100
schedule_delayed_work
(&switch_work,
oprofile_time_slice
);
101
}
102
103
static
void
stop_switch_worker(
void
)
104
{
105
cancel_delayed_work_sync
(&switch_work);
106
}
107
108
static
void
switch_worker(
struct
work_struct
*
work
)
109
{
110
if
(
oprofile_ops
.switch_events())
111
return
;
112
113
atomic_inc
(&
oprofile_stats
.multiplex_counter);
114
start_switch_worker();
115
}
116
117
/* User inputs in ms, converts to jiffies */
118
int
oprofile_set_timeout
(
unsigned
long
val_msec)
119
{
120
int
err
= 0;
121
unsigned
long
time_slice;
122
123
mutex_lock
(&start_mutex);
124
125
if
(
oprofile_started
) {
126
err = -
EBUSY
;
127
goto
out
;
128
}
129
130
if
(!
oprofile_ops
.switch_events) {
131
err = -
EINVAL
;
132
goto
out
;
133
}
134
135
time_slice =
msecs_to_jiffies
(val_msec);
136
if
(time_slice ==
MAX_JIFFY_OFFSET
) {
137
err = -
EINVAL
;
138
goto
out
;
139
}
140
141
oprofile_time_slice
= time_slice;
142
143
out
:
144
mutex_unlock
(&start_mutex);
145
return
err
;
146
147
}
148
149
#else
150
151
static
inline
void
start_switch_worker(
void
) { }
152
static
inline
void
stop_switch_worker(
void
) { }
153
154
#endif
155
156
/* Actually start profiling (echo 1>/dev/oprofile/enable) */
157
int
oprofile_start
(
void
)
158
{
159
int
err = -
EINVAL
;
160
161
mutex_lock
(&start_mutex);
162
163
if
(!is_setup)
164
goto
out
;
165
166
err = 0;
167
168
if
(
oprofile_started
)
169
goto
out
;
170
171
oprofile_reset_stats
();
172
173
if
((err =
oprofile_ops
.start()))
174
goto
out
;
175
176
start_switch_worker();
177
178
oprofile_started
= 1;
179
out
:
180
mutex_unlock
(&start_mutex);
181
return
err
;
182
}
183
184
185
/* echo 0>/dev/oprofile/enable */
186
void
oprofile_stop
(
void
)
187
{
188
mutex_lock
(&start_mutex);
189
if
(!
oprofile_started
)
190
goto
out
;
191
oprofile_ops
.stop();
192
oprofile_started
= 0;
193
194
stop_switch_worker();
195
196
/* wake up the daemon to read what remains */
197
wake_up_buffer_waiter
();
198
out
:
199
mutex_unlock
(&start_mutex);
200
}
201
202
203
void
oprofile_shutdown
(
void
)
204
{
205
mutex_lock
(&start_mutex);
206
if
(
oprofile_ops
.sync_stop) {
207
int
sync_ret =
oprofile_ops
.sync_stop();
208
switch
(sync_ret) {
209
case
0:
210
goto
post_sync;
211
case
1:
212
goto
do_generic;
213
default
:
214
goto
post_sync;
215
}
216
}
217
do_generic:
218
sync_stop
();
219
post_sync:
220
if
(
oprofile_ops
.shutdown)
221
oprofile_ops
.shutdown();
222
is_setup = 0;
223
free_event_buffer
();
224
free_cpu_buffers
();
225
mutex_unlock
(&start_mutex);
226
}
227
228
int
oprofile_set_ulong
(
unsigned
long
*
addr
,
unsigned
long
val
)
229
{
230
int
err = -
EBUSY
;
231
232
mutex_lock
(&start_mutex);
233
if
(!
oprofile_started
) {
234
*addr =
val
;
235
err = 0;
236
}
237
mutex_unlock
(&start_mutex);
238
239
return
err
;
240
}
241
242
static
int
timer_mode
;
243
244
static
int
__init
oprofile_init(
void
)
245
{
246
int
err
;
247
248
/* always init architecture to setup backtrace support */
249
timer_mode = 0;
250
err =
oprofile_arch_init
(&
oprofile_ops
);
251
if
(!err) {
252
if
(!
timer
&& !
oprofilefs_register
())
253
return
0;
254
oprofile_arch_exit
();
255
}
256
257
/* setup timer mode: */
258
timer_mode = 1;
259
/* no nmi timer mode if oprofile.timer is set */
260
if
(
timer
|| op_nmi_timer_init(&
oprofile_ops
)) {
261
err =
oprofile_timer_init
(&
oprofile_ops
);
262
if
(err)
263
return
err
;
264
}
265
266
return
oprofilefs_register
();
267
}
268
269
270
static
void
__exit
oprofile_exit(
void
)
271
{
272
oprofilefs_unregister
();
273
if
(!timer_mode)
274
oprofile_arch_exit
();
275
}
276
277
278
module_init
(oprofile_init);
279
module_exit
(oprofile_exit);
280
281
module_param_named
(
timer
,
timer
,
int
, 0644);
282
MODULE_PARM_DESC
(
timer
,
"force use of timer interrupt"
);
283
284
MODULE_LICENSE
(
"GPL"
);
285
MODULE_AUTHOR
(
"John Levon <
[email protected]
>"
);
286
MODULE_DESCRIPTION
(
"OProfile system profiler"
);
Generated on Thu Jan 10 2013 14:13:39 for Linux Kernel by
1.8.2