blob: 5dffe2444ffb02800949b07d97b32c3e53dc82f6 [file] [log] [blame]
The Android Open Source Project10e23ee2009-03-03 19:30:30 -08001/*
2 * Copyright 2008, The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17/*
18 * Binary implementation of the original opcontrol script due to missing tools
19 * like awk, test, etc.
20 */
21
22#include <unistd.h>
23#include <getopt.h>
24#include <stdio.h>
25#include <stdlib.h>
26#include <errno.h>
27#include <fcntl.h>
28#include <signal.h>
29#include <sys/stat.h>
30
31#include "op_config.h"
32
33#if 0
34#define verbose(fmt...) printf(fmt)
35#else
36#define verbose(fmt...)
37#endif
38
39/* Experiments found that using a small interval may hang the device, and the
40 * more events tracked simultaneously, the longer the interval has to be.
41 */
Ben Cheng5a4eb4e2009-09-14 16:00:41 -070042
43#if !defined(WITH_ARM_V7_A)
44#define MAX_EVENTS 3
Ben Cheng14345072009-09-16 11:31:39 -070045int min_count[MAX_EVENTS] = {150000, 200000, 250000};
Ben Cheng5a4eb4e2009-09-14 16:00:41 -070046#else
Ben Cheng14345072009-09-16 11:31:39 -070047#define MAX_EVENTS 5
Ben Chengafec5b92010-02-22 15:33:08 -080048int min_count[MAX_EVENTS] = {150000, 20000, 25000, 30000, 35000};
Ben Cheng5a4eb4e2009-09-14 16:00:41 -070049#endif
50
The Android Open Source Project10e23ee2009-03-03 19:30:30 -080051int list_events;
52int show_usage;
53int setup;
54int quick;
55int num_events;
56int start;
57int stop;
58int reset;
59
Ben Cheng5a4eb4e2009-09-14 16:00:41 -070060int selected_events[MAX_EVENTS];
61int selected_counts[MAX_EVENTS];
The Android Open Source Project10e23ee2009-03-03 19:30:30 -080062
63char kernel_range[512];
64char vmlinux[512];
65
66struct option long_options[] = {
67 {"help", 0, &show_usage, 1},
68 {"list-events", 0, &list_events, 1},
69 {"reset", 0, &reset, 1},
70 {"setup", 0, &setup, 1},
71 {"quick", 0, &quick, 1},
72 {"event", 1, 0, 'e'},
73 {"vmlinux", 1, 0, 'v'},
74 {"kernel-range", 1, 0, 'r'},
75 {"start", 0, &start, 1},
76 {"stop", 0, &stop, 1},
77 {"shutdown", 0, 0, 'h'},
78 {"status", 0, 0, 't'},
79 {0, 0, 0, 0},
80};
81
82struct event_info {
83 int id;
84 const char *name;
85 const char *explanation;
86} event_info[] = {
Ben Cheng5a4eb4e2009-09-14 16:00:41 -070087#if !defined(WITH_ARM_V7_A)
88 /* ARM V6 events */
The Android Open Source Project10e23ee2009-03-03 19:30:30 -080089 {0x00, "IFU_IFETCH_MISS",
90 "number of instruction fetch misses"},
91 {0x01, "CYCLES_IFU_MEM_STALL",
92 "cycles instruction fetch pipe is stalled"},
93 {0x02, "CYCLES_DATA_STALL",
94 "cycles stall occurs for due to data dependency"},
95 {0x03, "ITLB_MISS",
96 "number of Instruction MicroTLB misses"},
97 {0x04, "DTLB_MISS",
98 "number of Data MicroTLB misses"},
99 {0x05, "BR_INST_EXECUTED",
100 "branch instruction executed w/ or w/o program flow change"},
101 {0x06, "BR_INST_MISS_PRED",
102 "branch mispredicted"},
103 {0x07, "INSN_EXECUTED",
104 "instructions executed"},
105 {0x09, "DCACHE_ACCESS",
106 "data cache access, cacheable locations"},
107 {0x0a, "DCACHE_ACCESS_ALL",
108 "data cache access, all locations"},
109 {0x0b, "DCACHE_MISS",
110 "data cache miss"},
111 {0x0c, "DCACHE_WB",
112 "data cache writeback, 1 event for every half cacheline"},
113 {0x0d, "PC_CHANGE",
114 "number of times the program counter was changed without a mode switch"},
115 {0x0f, "TLB_MISS",
116 "Main TLB miss"},
117 {0x10, "EXP_EXTERNAL",
118 "Explicit external data access"},
119 {0x11, "LSU_STALL",
120 "cycles stalled because Load Store request queue is full"},
121 {0x12, "WRITE_DRAIN",
122 "Times write buffer was drained"},
123 {0xff, "CPU_CYCLES",
124 "clock cycles counter"},
Ben Cheng5a4eb4e2009-09-14 16:00:41 -0700125#else
126 /* ARM V7 events */
127 {0x00, "PMNC_SW_INCR",
128 "Software increment of PMNC registers"},
129 {0x01, "IFETCH_MISS",
130 "Instruction fetch misses from cache or normal cacheable memory"},
131 {0x02, "ITLB_MISS",
132 "Instruction fetch misses from TLB"},
133 {0x03, "DCACHE_REFILL",
134 "Data R/W operation that causes a refill from cache or normal cacheable"
135 "memory"},
136 {0x04, "DCACHE_ACCESS",
137 "Data R/W from cache"},
138 {0x05, "DTLB_REFILL",
139 "Data R/W that causes a TLB refill"},
140 {0x06, "DREAD",
141 "Data read architecturally executed (note: architecturally executed = for"
142 "instructions that are unconditional or that pass the condition code)"},
143 {0x07, "DWRITE",
144 "Data write architecturally executed"},
145 {0x08, "INSTR_EXECUTED",
146 "All executed instructions"},
147 {0x09, "EXC_TAKEN",
148 "Exception taken"},
149 {0x0A, "EXC_EXECUTED",
150 "Exception return architecturally executed"},
151 {0x0B, "CID_WRITE",
152 "Instruction that writes to the Context ID Register architecturally"
153 "executed"},
154 {0x0C, "PC_WRITE",
155 "SW change of PC, architecturally executed (not by exceptions)"},
156 {0x0D, "PC_IMM_BRANCH",
157 "Immediate branch instruction executed (taken or not)"},
158 {0x0E, "PC_PROC_RETURN",
159 "Procedure return architecturally executed (not by exceptions)"},
160 {0x0F, "UNALIGNED_ACCESS",
161 "Unaligned access architecturally executed"},
162 {0x10, "PC_BRANCH_MIS_PRED",
163 "Branch mispredicted or not predicted. Counts pipeline flushes because of"
164 "misprediction"},
165 {0x12, "PC_BRANCH_MIS_USED",
166 "Branch or change in program flow that could have been predicted"},
167 {0x40, "WRITE_BUFFER_FULL",
168 "Any write buffer full cycle"},
169 {0x41, "L2_STORE_MERGED",
170 "Any store that is merged in L2 cache"},
171 {0x42, "L2_STORE_BUFF",
172 "Any bufferable store from load/store to L2 cache"},
173 {0x43, "L2_ACCESS",
174 "Any access to L2 cache"},
175 {0x44, "L2_CACH_MISS",
176 "Any cacheable miss in L2 cache"},
177 {0x45, "AXI_READ_CYCLES",
178 "Number of cycles for an active AXI read"},
179 {0x46, "AXI_WRITE_CYCLES",
180 "Number of cycles for an active AXI write"},
181 {0x47, "MEMORY_REPLAY",
182 "Any replay event in the memory subsystem"},
183 {0x48, "UNALIGNED_ACCESS_REPLAY",
184 "Unaligned access that causes a replay"},
185 {0x49, "L1_DATA_MISS",
186 "L1 data cache miss as a result of the hashing algorithm"},
187 {0x4A, "L1_INST_MISS",
188 "L1 instruction cache miss as a result of the hashing algorithm"},
189 {0x4B, "L1_DATA_COLORING",
190 "L1 data access in which a page coloring alias occurs"},
191 {0x4C, "L1_NEON_DATA",
192 "NEON data access that hits L1 cache"},
193 {0x4D, "L1_NEON_CACH_DATA",
194 "NEON cacheable data access that hits L1 cache"},
195 {0x4E, "L2_NEON",
196 "L2 access as a result of NEON memory access"},
197 {0x4F, "L2_NEON_HIT",
198 "Any NEON hit in L2 cache"},
199 {0x50, "L1_INST",
200 "Any L1 instruction cache access, excluding CP15 cache accesses"},
201 {0x51, "PC_RETURN_MIS_PRED",
202 "Return stack misprediction at return stack pop"
203 "(incorrect target address)"},
204 {0x52, "PC_BRANCH_FAILED",
205 "Branch prediction misprediction"},
206 {0x53, "PC_BRANCH_TAKEN",
207 "Any predicted branch that is taken"},
208 {0x54, "PC_BRANCH_EXECUTED",
209 "Any taken branch that is executed"},
210 {0x55, "OP_EXECUTED",
211 "Number of operations executed"
212 "(in instruction or mutli-cycle instruction)"},
213 {0x56, "CYCLES_INST_STALL",
214 "Cycles where no instruction available"},
215 {0x57, "CYCLES_INST",
216 "Number of instructions issued in a cycle"},
217 {0x58, "CYCLES_NEON_DATA_STALL",
218 "Number of cycles the processor waits on MRC data from NEON"},
219 {0x59, "CYCLES_NEON_INST_STALL",
220 "Number of cycles the processor waits on NEON instruction queue or"
221 "NEON load queue"},
222 {0x5A, "NEON_CYCLES",
223 "Number of cycles NEON and integer processors are not idle"},
224 {0x70, "PMU0_EVENTS",
225 "Number of events from external input source PMUEXTIN[0]"},
226 {0x71, "PMU1_EVENTS",
227 "Number of events from external input source PMUEXTIN[1]"},
228 {0x72, "PMU_EVENTS",
229 "Number of events from both external input sources PMUEXTIN[0]"
230 "and PMUEXTIN[1]"},
231 {0xFF, "CPU_CYCLES",
232 "Number of CPU cycles"},
233#endif
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800234};
235
Ben Cheng14345072009-09-16 11:31:39 -0700236void usage()
237{
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800238 printf("\nopcontrol: usage:\n"
239 " --list-events list event types\n"
240 " --help this message\n"
241 " --setup setup directories\n"
242 " --quick setup and select CPU_CYCLES:150000\n"
243 " --status show configuration\n"
244 " --start start data collection\n"
245 " --stop stop data collection\n"
246 " --reset clears out data from current session\n"
247 " --shutdown kill the oprofile daeman\n"
248 " --event=eventspec\n"
249 " Choose an event. May be specified multiple times.\n"
250 " eventspec is in the form of name[:count], where :\n"
251 " name: event name, see \"opcontrol --list-events\"\n"
252 " count: reset counter value\n"
253 " --vmlinux=file vmlinux kernel image\n"
254 " --kernel-range=start,end\n"
255 " kernel range vma address in hexadecimal\n"
256 );
257}
258
Ben Cheng14345072009-09-16 11:31:39 -0700259void setup_session_dir()
260{
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800261 int fd;
262
263 fd = open(OP_DATA_DIR, O_RDONLY);
264 if (fd != -1) {
265 system("rm -r "OP_DATA_DIR);
266 close(fd);
267 }
268
269 if (mkdir(OP_DATA_DIR, 755)) {
270 fprintf(stderr, "Cannot create directory \"%s\": %s\n",
271 OP_DATA_DIR, strerror(errno));
272 }
273 if (mkdir(OP_DATA_DIR"/samples", 644)) {
274 fprintf(stderr, "Cannot create directory \"%s\": %s\n",
275 OP_DATA_DIR"/samples", strerror(errno));
276 }
277}
278
Ben Cheng14345072009-09-16 11:31:39 -0700279int do_setup()
280{
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800281 char dir[1024];
282
283 setup_session_dir();
284
285 if (mkdir(OP_DRIVER_BASE, 644)) {
286 fprintf(stderr, "Cannot create directory "OP_DRIVER_BASE": %s\n",
287 strerror(errno));
288 return -1;
289 }
290 if (system("mount -t oprofilefs nodev "OP_DRIVER_BASE)) {
291 return -1;
292 }
293 return 0;
294}
295
296void do_list_events()
297{
298 unsigned int i;
299
300 printf("%-20s: %s\n", "name", "meaning");
301 printf("----------------------------------------"
302 "--------------------------------------\n");
303 for (i = 0; i < sizeof(event_info)/sizeof(struct event_info); i++) {
304 printf("%-20s: %s\n", event_info[i].name, event_info[i].explanation);
305 }
306}
307
Ben Cheng14345072009-09-16 11:31:39 -0700308int find_event_idx_from_name(const char *name)
309{
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800310 unsigned int i;
311
312 for (i = 0; i < sizeof(event_info)/sizeof(struct event_info); i++) {
313 if (!strcmp(name, event_info[i].name)) {
314 return i;
315 }
316 }
317 return -1;
318}
319
Ben Cheng14345072009-09-16 11:31:39 -0700320const char * find_event_name_from_id(int id)
321{
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800322 unsigned int i;
323
324 for (i = 0; i < sizeof(event_info)/sizeof(struct event_info); i++) {
325 if (event_info[i].id == id) {
326 return event_info[i].name;
327 }
328 }
329 return NULL;
330}
331
Ben Cheng14345072009-09-16 11:31:39 -0700332int process_event(const char *event_spec)
333{
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800334 char event_name[512];
335 char count_name[512];
336 unsigned int i;
Ben Cheng14345072009-09-16 11:31:39 -0700337 int event_idx;
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800338 int count_val;
339
340 strncpy(event_name, event_spec, 512);
341 count_name[0] = 0;
342
343 /* First, check if the name is followed by ":" */
344 for (i = 0; i < strlen(event_name); i++) {
345 if (event_name[i] == 0) {
346 break;
347 }
348 if (event_name[i] == ':') {
349 strncpy(count_name, event_name+i+1, 512);
350 event_name[i] = 0;
351 break;
352 }
353 }
Ben Cheng14345072009-09-16 11:31:39 -0700354 event_idx = find_event_idx_from_name(event_name);
355 if (event_idx == -1) {
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800356 fprintf(stderr, "Unknown event name: %s\n", event_name);
357 return -1;
358 }
359
360 /* Use defualt count */
361 if (count_name[0] == 0) {
362 count_val = min_count[0];
363 } else {
364 count_val = atoi(count_name);
365 }
366
Ben Cheng14345072009-09-16 11:31:39 -0700367 selected_events[num_events] = event_idx;
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800368 selected_counts[num_events++] = count_val;
Ben Cheng14345072009-09-16 11:31:39 -0700369 verbose("event_id is %d\n", event_info[event_idx].id);
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800370 verbose("count_val is %d\n", count_val);
371 return 0;
372}
373
374int echo_dev(const char* str, int val, const char* file, int counter)
375{
376 char fullname[512];
377 char content[128];
378 int fd;
379
380 if (counter >= 0) {
381 snprintf(fullname, 512, OP_DRIVER_BASE"/%d/%s", counter, file);
382 }
383 else {
384 snprintf(fullname, 512, OP_DRIVER_BASE"/%s", file);
385 }
386 fd = open(fullname, O_WRONLY);
387 if (fd<0) {
388 fprintf(stderr, "Cannot open %s: %s\n", fullname, strerror(errno));
389 return fd;
390 }
391 if (str == 0) {
392 sprintf(content, "%d", val);
393 }
394 else {
395 strncpy(content, str, 128);
396 }
397 verbose("Configure %s (%s)\n", fullname, content);
398 write(fd, content, strlen(content));
399 close(fd);
400 return 0;
401}
402
403int read_num(const char* file)
404{
405 char buffer[256];
406 int fd = open(file, O_RDONLY);
407 if (fd<0) return -1;
408 int rd = read(fd, buffer, sizeof(buffer)-1);
409 buffer[rd] = 0;
410 return atoi(buffer);
411}
412
413void do_status()
414{
415 int num;
416 char fullname[512];
417 int i;
418
419 printf("Driver directory: %s\n", OP_DRIVER_BASE);
420 printf("Session directory: %s\n", OP_DATA_DIR);
Ben Cheng5a4eb4e2009-09-14 16:00:41 -0700421 for (i = 0; i < MAX_EVENTS; i++) {
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800422 sprintf(fullname, OP_DRIVER_BASE"/%d/enabled", i);
423 num = read_num(fullname);
424 if (num > 0) {
425 printf("Counter %d:\n", i);
426
427 /* event name */
428 sprintf(fullname, OP_DRIVER_BASE"/%d/event", i);
429 num = read_num(fullname);
430 printf(" name: %s\n", find_event_name_from_id(num));
431
432 /* profile interval */
433 sprintf(fullname, OP_DRIVER_BASE"/%d/count", i);
434 num = read_num(fullname);
435 printf(" count: %d\n", num);
436 }
437 else {
438 printf("Counter %d disabled\n", i);
439 }
440 }
441
442 num = read_num(OP_DATA_DIR"/lock");
443 if (num >= 0) {
444 int fd;
445 /* Still needs to check if this lock is left-over */
446 sprintf(fullname, "/proc/%d", num);
447 fd = open(fullname, O_RDONLY);
448 if (fd == -1) {
449 printf("Session directory is not clean - do \"opcontrol --setup\""
450 " before you continue\n");
451 return;
452 }
453 else {
454 close(fd);
455 printf("oprofiled pid: %d\n", num);
456 num = read_num(OP_DRIVER_BASE"/enable");
457 printf("profiler is%s running\n", num == 0 ? " not" : "");
458 num = read_num(OP_DRIVER_BASE"/stats/cpu0/sample_received");
459 printf(" %9u samples received\n", num);
460 num = read_num(OP_DRIVER_BASE"/stats/cpu0/sample_lost_overflow");
461 printf(" %9u samples lost overflow\n", num);
462#if 0
463 /* FIXME - backtrace seems broken */
464 num = read_num(OP_DRIVER_BASE"/stats/cpu0/backtrace_aborted");
465 printf(" %9u backtrace aborted\n", num);
466 num = read_num(OP_DRIVER_BASE"/backtrace_depth");
467 printf(" %9u backtrace_depth\n", num);
468#endif
469 }
470 }
471 else {
472 printf("oprofiled is not running\n");
473 }
474}
475
476void do_reset()
477{
478 int fd;
479
480 fd = open(OP_DATA_DIR"/samples/current", O_RDONLY);
481 if (fd == -1) {
482 return;
483 }
484 close(fd);
485 system("rm -r "OP_DATA_DIR"/samples/current");
486}
487
488int main(int argc, char * const argv[])
489{
490 int option_index;
491 char command[1024];
492
493 /* Initialize default strings */
494 strcpy(vmlinux, "--no-vmlinux");
495 strcpy(kernel_range, "");
496
497 while (1) {
498 int c = getopt_long(argc, argv, "", long_options, &option_index);
499 if (c == -1) {
500 break;
501 }
502 switch (c) {
503 case 0:
504 break;
505 /* --event */
506 case 'e':
Ben Cheng5a4eb4e2009-09-14 16:00:41 -0700507 if (num_events == MAX_EVENTS) {
508 fprintf(stderr, "More than %d events specified\n",
509 MAX_EVENTS);
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800510 exit(1);
511 }
512 if (process_event(optarg)) {
513 exit(1);
514 }
515 break;
516 /* --vmlinux */
517 case 'v':
518 sprintf(vmlinux, "-k %s", optarg);
519 break;
520 /* --kernel-range */
521 case 'r':
522 sprintf(kernel_range, "-r %s", optarg);
523 break;
524 /* --shutdown */
525 case 'h': {
526 int pid = read_num(OP_DATA_DIR"/lock");
527 if (pid >= 0) {
528 kill(pid, SIGKILL);
529 }
530 setup_session_dir();
531 break;
532 }
533 /* --status */
534 case 't':
535 do_status();
536 break;
537 default:
538 usage();
539 exit(1);
540 }
541 }
542 verbose("list_events = %d\n", list_events);
543 verbose("setup = %d\n", setup);
544
545 if (list_events) {
546 do_list_events();
547 }
548
549 if (quick) {
550 process_event("CPU_CYCLES");
551 setup = 1;
552 }
553
554 if (reset) {
555 do_reset();
556 }
557
558 if (show_usage) {
559 usage();
560 }
561
562 if (setup) {
563 if (do_setup()) {
564 fprintf(stderr, "do_setup failed");
565 exit(1);
566 }
567 }
568
569 if (num_events != 0) {
570 int i;
571
572 strcpy(command, "oprofiled --session-dir="OP_DATA_DIR);
573
Ben Cheng5a4eb4e2009-09-14 16:00:41 -0700574#if !defined(WITH_ARM_V7_A)
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800575 /* Since counter #3 can only handle CPU_CYCLES, check and shuffle the
576 * order a bit so that the maximal number of events can be profiled
577 * simultaneously
578 */
579 if (num_events == 3) {
580 for (i = 0; i < num_events; i++) {
581 int event_idx = selected_events[i];
582
583 if (event_info[event_idx].id == 0xff) {
584 break;
585 }
586 }
587
588 /* No CPU_CYCLES is found */
589 if (i == 3) {
590 fprintf(stderr, "You can only specify three events if one of "
591 "them is CPU_CYCLES\n");
592 exit(1);
593 }
594 /* Swap CPU_CYCLES to counter #2 (starting from #0)*/
595 else if (i != 2) {
596 int temp;
597
598 temp = selected_events[2];
599 selected_events[2] = selected_events[i];
600 selected_events[i] = temp;
601
602 temp = selected_counts[2];
603 selected_counts[2] = selected_counts[i];
604 selected_counts[i] = temp;
605 }
606 }
Ben Cheng5a4eb4e2009-09-14 16:00:41 -0700607#endif
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800608
609
610 /* Configure the counters and enable them */
611 for (i = 0; i < num_events; i++) {
612 int event_idx = selected_events[i];
613 int setup_result = 0;
614
615 if (i == 0) {
616 snprintf(command+strlen(command), 1024 - strlen(command),
617 " --events=");
618 }
619 else {
620 snprintf(command+strlen(command), 1024 - strlen(command),
621 ",");
622 }
623 /* Compose name:id:count:unit_mask:kernel:user, something like
624 * --events=CYCLES_DATA_STALL:2:0:200000:0:1:1,....
625 */
626 snprintf(command+strlen(command), 1024 - strlen(command),
627 "%s:%d:%d:%d:0:1:1",
628 event_info[event_idx].name,
629 event_info[event_idx].id,
630 i,
631 selected_counts[i]);
632
633 setup_result |= echo_dev("1", 0, "user", i);
634 setup_result |= echo_dev("1", 0, "kernel", i);
635 setup_result |= echo_dev("0", 0, "unit_mask", i);
636 setup_result |= echo_dev("1", 0, "enabled", i);
637 setup_result |= echo_dev(NULL, selected_counts[i], "count", i);
638 setup_result |= echo_dev(NULL, event_info[event_idx].id,
639 "event", i);
640 if (setup_result) {
641 fprintf(stderr, "Counter configuration failed for %s\n",
642 event_info[event_idx].name);
643 fprintf(stderr, "Did you do \"opcontrol --setup\" first?\n");
644 exit(1);
645 }
646 }
647
648 /* Disable the unused counters */
Ben Cheng5a4eb4e2009-09-14 16:00:41 -0700649 for (i = num_events; i < MAX_EVENTS; i++) {
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800650 echo_dev("0", 0, "enabled", i);
651 }
652
653 snprintf(command+strlen(command), 1024 - strlen(command), " %s",
654 vmlinux);
655 if (kernel_range[0]) {
656 snprintf(command+strlen(command), 1024 - strlen(command), " %s",
657 kernel_range);
658 }
659 verbose("command: %s\n", command);
660 system(command);
661 }
662
663 if (start) {
664 echo_dev("1", 0, "enable", -1);
665 }
666
667 if (stop) {
Ben Chengafec5b92010-02-22 15:33:08 -0800668 echo_dev("1", 0, "dump", -1);
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800669 echo_dev("0", 0, "enable", -1);
670 }
671}