1 /* 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 <string.h> 27 #include <errno.h> 28 #include <fcntl.h> 29 #include <signal.h> 30 #include <dirent.h> 31 #include <sys/stat.h> 32 #include <sys/types.h> 33 #include <sys/wait.h> 34 35 #include "op_config.h" 36 37 #define verbose(fmt...) if (verbose_print) printf(fmt) 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 */ 42 43 #if defined(__i386__) || defined(__x86_64__) 44 #define MAX_EVENTS 2 45 int min_count[MAX_EVENTS] = {60000, 100000}; 46 #elif !defined(WITH_ARM_V7_A) 47 #define MAX_EVENTS 3 48 int min_count[MAX_EVENTS] = {150000, 200000, 250000}; 49 #else 50 #define MAX_EVENTS 5 51 int min_count[MAX_EVENTS] = {150000, 20000, 25000, 30000, 35000}; 52 #endif 53 54 int verbose_print; 55 int list_events; 56 int show_usage; 57 int setup; 58 int quick; 59 int timer; 60 int num_events; 61 int start; 62 int stop; 63 int reset; 64 65 int selected_events[MAX_EVENTS]; 66 int selected_counts[MAX_EVENTS]; 67 68 char callgraph[8]; 69 char kernel_range[512]; 70 char vmlinux[512]; 71 72 struct option long_options[] = { 73 {"help", 0, &show_usage, 1}, 74 {"list-events", 0, &list_events, 1}, 75 {"reset", 0, &reset, 1}, 76 {"setup", 0, &setup, 1}, 77 {"quick", 0, &quick, 1}, 78 {"timer", 0, &timer, 1}, 79 {"callgraph", 1, 0, 'c'}, 80 {"event", 1, 0, 'e'}, 81 {"vmlinux", 1, 0, 'v'}, 82 {"kernel-range", 1, 0, 'r'}, 83 {"start", 0, &start, 1}, 84 {"stop", 0, &stop, 1}, 85 {"dump", 0, 0, 'd'}, 86 {"shutdown", 0, 0, 'h'}, 87 {"status", 0, 0, 't'}, 88 {"verbose", 0, 0, 'V'}, 89 {"verbose-log", 1, 0, 'l'}, 90 {0, 0, 0, 0}, 91 }; 92 93 struct event_info { 94 int id; 95 int um; 96 const char *name; 97 const char *explanation; 98 } event_info[] = { 99 #if defined(__i386__) || defined(__x86_64__) 100 /* INTEL_ARCH_PERFMON events */ 101 102 /* 0x3c counters:cpuid um:zero minimum:6000 filter:0 name:CPU_CLK_UNHALTED : 103 * Clock cycles when not halted 104 */ 105 {0x3c, 0, "CPU_CLK_UNHALTED", 106 "Clock cycles when not halted" }, 107 108 /* event:0x3c counters:cpuid um:one minimum:6000 filter:2 name:UNHALTED_REFERENCE_CYCLES : 109 * Unhalted reference cycles 110 */ 111 {0x3c, 1, "UNHALTED_REFERENCE_CYCLES", 112 "Unhalted reference cycles" }, 113 114 /* event:0xc0 counters:cpuid um:zero minimum:6000 filter:1 name:INST_RETIRED : 115 * number of instructions retired 116 */ 117 {0xc0, 0, "INST_RETIRED", 118 "number of instructions retired"}, 119 120 /* event:0x2e counters:cpuid um:x41 minimum:6000 filter:5 name:LLC_MISSES : 121 * Last level cache demand requests from this core that missed the LLC 122 */ 123 {0x2e, 0x41, "LLC_MISSES", 124 "Last level cache demand requests from this core that missed the LLC"}, 125 126 /* event:0x2e counters:cpuid um:x4f minimum:6000 filter:4 name:LLC_REFS : 127 * Last level cache demand requests from this core 128 */ 129 {0x2e, 0x4f, "LLC_REFS", 130 "Last level cache demand requests from this core"}, 131 132 /* event:0xc4 counters:cpuid um:zero minimum:500 filter:6 name:BR_INST_RETIRED : 133 * number of branch instructions retired 134 */ 135 {0xc4, 0, "BR_INST_RETIRED", 136 "number of branch instructions retired"}, 137 138 /* event:0xc5 counters:cpuid um:zero minimum:500 filter:7 name:BR_MISS_PRED_RETIRED : 139 * number of mispredicted branches retired (precise) 140 */ 141 {0xc5, 0, "BR_MISS_PRED_RETIRED", 142 "number of mispredicted branches retired (precise)"}, 143 144 #elif !defined(WITH_ARM_V7_A) 145 /* ARM V6 events */ 146 {0x00, 0, "IFU_IFETCH_MISS", 147 "number of instruction fetch misses"}, 148 {0x01, 0, "CYCLES_IFU_MEM_STALL", 149 "cycles instruction fetch pipe is stalled"}, 150 {0x02, 0, "CYCLES_DATA_STALL", 151 "cycles stall occurs for due to data dependency"}, 152 {0x03, 0, "ITLB_MISS", 153 "number of Instruction MicroTLB misses"}, 154 {0x04, 0, "DTLB_MISS", 155 "number of Data MicroTLB misses"}, 156 {0x05, 0, "BR_INST_EXECUTED", 157 "branch instruction executed w/ or w/o program flow change"}, 158 {0x06, 0, "BR_INST_MISS_PRED", 159 "branch mispredicted"}, 160 {0x07, 0, "INSN_EXECUTED", 161 "instructions executed"}, 162 {0x09, 0, "DCACHE_ACCESS", 163 "data cache access, cacheable locations"}, 164 {0x0a, 0, "DCACHE_ACCESS_ALL", 165 "data cache access, all locations"}, 166 {0x0b, 0, "DCACHE_MISS", 167 "data cache miss"}, 168 {0x0c, 0, "DCACHE_WB", 169 "data cache writeback, 1 event for every half cacheline"}, 170 {0x0d, 0, "PC_CHANGE", 171 "number of times the program counter was changed without a mode switch"}, 172 {0x0f, 0, "TLB_MISS", 173 "Main TLB miss"}, 174 {0x10, 0, "EXP_EXTERNAL", 175 "Explicit external data access"}, 176 {0x11, 0, "LSU_STALL", 177 "cycles stalled because Load Store request queue is full"}, 178 {0x12, 0, "WRITE_DRAIN", 179 "Times write buffer was drained"}, 180 {0xff, 0, "CPU_CYCLES", 181 "clock cycles counter"}, 182 #else 183 /* ARM V7 events */ 184 {0x00, 0, "PMNC_SW_INCR", 185 "Software increment of PMNC registers"}, 186 {0x01, 0, "IFETCH_MISS", 187 "Instruction fetch misses from cache or normal cacheable memory"}, 188 {0x02, 0, "ITLB_MISS", 189 "Instruction fetch misses from TLB"}, 190 {0x03, 0, "DCACHE_REFILL", 191 "Data R/W operation that causes a refill from cache or normal cacheable" 192 "memory"}, 193 {0x04, 0, "DCACHE_ACCESS", 194 "Data R/W from cache"}, 195 {0x05, 0, "DTLB_REFILL", 196 "Data R/W that causes a TLB refill"}, 197 {0x06, 0, "DREAD", 198 "Data read architecturally executed (note: architecturally executed = for" 199 "instructions that are unconditional or that pass the condition code)"}, 200 {0x07, 0, "DWRITE", 201 "Data write architecturally executed"}, 202 {0x08, 0, "INSTR_EXECUTED", 203 "All executed instructions"}, 204 {0x09, 0, "EXC_TAKEN", 205 "Exception taken"}, 206 {0x0A, 0, "EXC_EXECUTED", 207 "Exception return architecturally executed"}, 208 {0x0B, 0, "CID_WRITE", 209 "Instruction that writes to the Context ID Register architecturally" 210 "executed"}, 211 {0x0C, 0, "PC_WRITE", 212 "SW change of PC, architecturally executed (not by exceptions)"}, 213 {0x0D, 0, "PC_IMM_BRANCH", 214 "Immediate branch instruction executed (taken or not)"}, 215 {0x0E, 0, "PC_PROC_RETURN", 216 "Procedure return architecturally executed (not by exceptions)"}, 217 {0x0F, 0, "UNALIGNED_ACCESS", 218 "Unaligned access architecturally executed"}, 219 {0x10, 0, "PC_BRANCH_MIS_PRED", 220 "Branch mispredicted or not predicted. Counts pipeline flushes because of" 221 "misprediction"}, 222 {0x12, 0, "PC_BRANCH_MIS_USED", 223 "Branch or change in program flow that could have been predicted"}, 224 {0x40, 0, "WRITE_BUFFER_FULL", 225 "Any write buffer full cycle"}, 226 {0x41, 0, "L2_STORE_MERGED", 227 "Any store that is merged in L2 cache"}, 228 {0x42, 0, "L2_STORE_BUFF", 229 "Any bufferable store from load/store to L2 cache"}, 230 {0x43, 0, "L2_ACCESS", 231 "Any access to L2 cache"}, 232 {0x44, 0, "L2_CACH_MISS", 233 "Any cacheable miss in L2 cache"}, 234 {0x45, 0, "AXI_READ_CYCLES", 235 "Number of cycles for an active AXI read"}, 236 {0x46, 0, "AXI_WRITE_CYCLES", 237 "Number of cycles for an active AXI write"}, 238 {0x47, 0, "MEMORY_REPLAY", 239 "Any replay event in the memory subsystem"}, 240 {0x48, 0, "UNALIGNED_ACCESS_REPLAY", 241 "Unaligned access that causes a replay"}, 242 {0x49, 0, "L1_DATA_MISS", 243 "L1 data cache miss as a result of the hashing algorithm"}, 244 {0x4A, 0, "L1_INST_MISS", 245 "L1 instruction cache miss as a result of the hashing algorithm"}, 246 {0x4B, 0, "L1_DATA_COLORING", 247 "L1 data access in which a page coloring alias occurs"}, 248 {0x4C, 0, "L1_NEON_DATA", 249 "NEON data access that hits L1 cache"}, 250 {0x4D, 0, "L1_NEON_CACH_DATA", 251 "NEON cacheable data access that hits L1 cache"}, 252 {0x4E, 0, "L2_NEON", 253 "L2 access as a result of NEON memory access"}, 254 {0x4F, 0, "L2_NEON_HIT", 255 "Any NEON hit in L2 cache"}, 256 {0x50, 0, "L1_INST", 257 "Any L1 instruction cache access, excluding CP15 cache accesses"}, 258 {0x51, 0, "PC_RETURN_MIS_PRED", 259 "Return stack misprediction at return stack pop" 260 "(incorrect target address)"}, 261 {0x52, 0, "PC_BRANCH_FAILED", 262 "Branch prediction misprediction"}, 263 {0x53, 0, "PC_BRANCH_TAKEN", 264 "Any predicted branch that is taken"}, 265 {0x54, 0, "PC_BRANCH_EXECUTED", 266 "Any taken branch that is executed"}, 267 {0x55, 0, "OP_EXECUTED", 268 "Number of operations executed" 269 "(in instruction or mutli-cycle instruction)"}, 270 {0x56, 0, "CYCLES_INST_STALL", 271 "Cycles where no instruction available"}, 272 {0x57, 0, "CYCLES_INST", 273 "Number of instructions issued in a cycle"}, 274 {0x58, 0, "CYCLES_NEON_DATA_STALL", 275 "Number of cycles the processor waits on MRC data from NEON"}, 276 {0x59, 0, "CYCLES_NEON_INST_STALL", 277 "Number of cycles the processor waits on NEON instruction queue or" 278 "NEON load queue"}, 279 {0x5A, 0, "NEON_CYCLES", 280 "Number of cycles NEON and integer processors are not idle"}, 281 {0x70, 0, "PMU0_EVENTS", 282 "Number of events from external input source PMUEXTIN[0]"}, 283 {0x71, 0, "PMU1_EVENTS", 284 "Number of events from external input source PMUEXTIN[1]"}, 285 {0x72, 0, "PMU_EVENTS", 286 "Number of events from both external input sources PMUEXTIN[0]" 287 "and PMUEXTIN[1]"}, 288 {0xFF, 0, "CPU_CYCLES", 289 "Number of CPU cycles"}, 290 #endif 291 }; 292 293 void usage() 294 { 295 printf("\nopcontrol: usage:\n" 296 " --list-events list event types\n" 297 " --help this message\n" 298 " --verbose show extra status\n" 299 " --verbose-log=lvl set daemon logging verbosity during setup\n" 300 " levels are: all,sfile,arcs,samples,module,misc\n" 301 " --setup setup directories\n" 302 #if defined(__i386__) || defined(__x86_64__) 303 " --quick setup and select CPU_CLK_UNHALTED:60000\n" 304 #else 305 " --quick setup and select CPU_CYCLES:150000\n" 306 #endif 307 " --timer timer-based profiling\n" 308 " --status show configuration\n" 309 " --start start data collection\n" 310 " --stop stop data collection\n" 311 " --reset clears out data from current session\n" 312 " --shutdown kill the oprofile daeman\n" 313 " --callgraph=depth callgraph depth\n" 314 " --event=eventspec\n" 315 " Choose an event. May be specified multiple times.\n" 316 " eventspec is in the form of name[:count], where :\n" 317 " name: event name, see \"opcontrol --list-events\"\n" 318 " count: reset counter value\n" 319 " --vmlinux=file vmlinux kernel image\n" 320 " --kernel-range=start,end\n" 321 " kernel range vma address in hexadecimal\n" 322 ); 323 } 324 325 void setup_session_dir() 326 { 327 int fd; 328 329 fd = open(OP_DATA_DIR, O_RDONLY); 330 if (fd != -1) { 331 system("rm -r "OP_DATA_DIR); 332 close(fd); 333 } 334 335 if (mkdir(OP_DATA_DIR, 0755)) { 336 fprintf(stderr, "Cannot create directory \"%s\": %s\n", 337 OP_DATA_DIR, strerror(errno)); 338 } 339 if (mkdir(OP_DATA_DIR"/samples", 0755)) { 340 fprintf(stderr, "Cannot create directory \"%s\": %s\n", 341 OP_DATA_DIR"/samples", strerror(errno)); 342 } 343 } 344 345 int read_num(const char* file) 346 { 347 char buffer[256]; 348 int fd = open(file, O_RDONLY); 349 if (fd<0) return -1; 350 int rd = read(fd, buffer, sizeof(buffer)-1); 351 buffer[rd] = 0; 352 close(fd); 353 return atoi(buffer); 354 } 355 356 int do_setup() 357 { 358 char dir[1024]; 359 360 /* 361 * Kill the old daemon so that setup can be done more than once to achieve 362 * the same effect as reset. 363 */ 364 int num = read_num(OP_DATA_DIR"/lock"); 365 if (num >= 0) { 366 printf("Terminating the old daemon...\n"); 367 kill(num, SIGTERM); 368 sleep(5); 369 } 370 371 setup_session_dir(); 372 373 if (mkdir(OP_DRIVER_BASE, 0755)) { 374 if (errno != EEXIST) { 375 fprintf(stderr, "Cannot create directory "OP_DRIVER_BASE": %s\n", 376 strerror(errno)); 377 return -1; 378 } 379 } 380 381 if (access(OP_DRIVER_BASE"/stats", F_OK)) { 382 if (system("mount -t oprofilefs nodev "OP_DRIVER_BASE)) { 383 return -1; 384 } 385 } 386 return 0; 387 } 388 389 void do_list_events() 390 { 391 unsigned int i; 392 393 printf("%-20s: %s\n", "name", "meaning"); 394 printf("----------------------------------------" 395 "--------------------------------------\n"); 396 for (i = 0; i < sizeof(event_info)/sizeof(struct event_info); i++) { 397 printf("%-20s: %s\n", event_info[i].name, event_info[i].explanation); 398 } 399 } 400 401 int find_event_idx_from_name(const char *name) 402 { 403 unsigned int i; 404 405 for (i = 0; i < sizeof(event_info)/sizeof(struct event_info); i++) { 406 if (!strcmp(name, event_info[i].name)) { 407 return i; 408 } 409 } 410 return -1; 411 } 412 413 const char * find_event_name_from_id(int id) 414 { 415 unsigned int i; 416 417 for (i = 0; i < sizeof(event_info)/sizeof(struct event_info); i++) { 418 if (event_info[i].id == id) { 419 return event_info[i].name; 420 } 421 } 422 return NULL; 423 } 424 425 int process_event(const char *event_spec) 426 { 427 char event_name[512]; 428 char count_name[512]; 429 unsigned int i; 430 int event_idx; 431 int count_val; 432 433 strncpy(event_name, event_spec, 512); 434 count_name[0] = 0; 435 436 /* First, check if the name is followed by ":" */ 437 for (i = 0; i < strlen(event_name); i++) { 438 if (event_name[i] == 0) { 439 break; 440 } 441 if (event_name[i] == ':') { 442 strncpy(count_name, event_name+i+1, 512); 443 event_name[i] = 0; 444 break; 445 } 446 } 447 event_idx = find_event_idx_from_name(event_name); 448 if (event_idx == -1) { 449 fprintf(stderr, "Unknown event name: %s\n", event_name); 450 return -1; 451 } 452 453 /* Use default count */ 454 if (count_name[0] == 0) { 455 count_val = min_count[0]; 456 } else { 457 count_val = atoi(count_name); 458 } 459 460 selected_events[num_events] = event_idx; 461 selected_counts[num_events++] = count_val; 462 verbose("event_id is %d\n", event_info[event_idx].id); 463 verbose("count_val is %d\n", count_val); 464 return 0; 465 } 466 467 int echo_dev(const char* str, int val, const char* file, int counter) 468 { 469 char fullname[512]; 470 char content[128]; 471 int fd; 472 473 if (counter >= 0) { 474 snprintf(fullname, 512, OP_DRIVER_BASE"/%d/%s", counter, file); 475 } 476 else { 477 snprintf(fullname, 512, OP_DRIVER_BASE"/%s", file); 478 } 479 fd = open(fullname, O_WRONLY); 480 if (fd<0) { 481 fprintf(stderr, "Cannot open %s: %s\n", fullname, strerror(errno)); 482 return fd; 483 } 484 if (str == 0) { 485 sprintf(content, "%d", val); 486 } 487 else { 488 strncpy(content, str, 128); 489 } 490 verbose("Configure %s (%s)\n", fullname, content); 491 write(fd, content, strlen(content)); 492 close(fd); 493 return 0; 494 } 495 496 void do_status() 497 { 498 int num; 499 char fullname[512]; 500 int i; 501 502 printf("Driver directory: %s\n", OP_DRIVER_BASE); 503 printf("Session directory: %s\n", OP_DATA_DIR); 504 for (i = 0; i < MAX_EVENTS; i++) { 505 sprintf(fullname, OP_DRIVER_BASE"/%d/enabled", i); 506 num = read_num(fullname); 507 if (num > 0) { 508 printf("Counter %d:\n", i); 509 510 /* event name */ 511 sprintf(fullname, OP_DRIVER_BASE"/%d/event", i); 512 num = read_num(fullname); 513 printf(" name: %s\n", find_event_name_from_id(num)); 514 515 /* profile interval */ 516 sprintf(fullname, OP_DRIVER_BASE"/%d/count", i); 517 num = read_num(fullname); 518 printf(" count: %d\n", num); 519 } 520 else { 521 printf("Counter %d disabled\n", i); 522 } 523 } 524 525 num = read_num(OP_DATA_DIR"/lock"); 526 if (num >= 0) { 527 int fd; 528 /* Still needs to check if this lock is left-over */ 529 sprintf(fullname, "/proc/%d", num); 530 fd = open(fullname, O_RDONLY); 531 if (fd == -1) { 532 printf("OProfile daemon exited prematurely - redo setup" 533 " before you continue\n"); 534 return; 535 } 536 else { 537 close(fd); 538 539 printf("oprofiled pid: %d\n", num); 540 num = read_num(OP_DRIVER_BASE"/enable"); 541 542 printf("profiler is%s running\n", num == 0 ? " not" : ""); 543 544 DIR* dir = opendir(OP_DRIVER_BASE"/stats"); 545 if (dir) { 546 for (struct dirent* dirent; !!(dirent = readdir(dir));) { 547 if (strlen(dirent->d_name) >= 4 && memcmp(dirent->d_name, "cpu", 3) == 0) { 548 char cpupath[256]; 549 strcpy(cpupath, OP_DRIVER_BASE"/stats/"); 550 strcat(cpupath, dirent->d_name); 551 552 strcpy(fullname, cpupath); 553 strcat(fullname, "/sample_received"); 554 num = read_num(fullname); 555 printf(" %s %9u samples received\n", dirent->d_name, num); 556 557 strcpy(fullname, cpupath); 558 strcat(fullname, "/sample_lost_overflow"); 559 num = read_num(fullname); 560 printf(" %s %9u samples lost overflow\n", dirent->d_name, num); 561 562 strcpy(fullname, cpupath); 563 strcat(fullname, "/sample_invalid_eip"); 564 num = read_num(fullname); 565 printf(" %s %9u samples invalid eip\n", dirent->d_name, num); 566 567 strcpy(fullname, cpupath); 568 strcat(fullname, "/backtrace_aborted"); 569 num = read_num(fullname); 570 printf(" %s %9u backtrace aborted\n", dirent->d_name, num); 571 } 572 } 573 closedir(dir); 574 } 575 576 num = read_num(OP_DRIVER_BASE"/backtrace_depth"); 577 printf("backtrace_depth: %u\n", num); 578 } 579 } 580 else { 581 printf("oprofiled is not running\n"); 582 } 583 } 584 585 void do_reset() 586 { 587 /* 588 * Sending SIGHUP will result in the following crash in oprofiled when 589 * profiling subsequent runs: 590 * Stack Trace: 591 * RELADDR FUNCTION FILE:LINE 592 * 00008cd8 add_node+12 oprofilelibdb/db_insert.c:32 593 * 00008d69 odb_update_node_with_offset+60 oprofilelibdb/db_insert.c:102 594 * 595 * However without sending SIGHUP oprofile cannot be restarted successfully. 596 * As a temporary workaround, change do_reset into a no-op for now and kill 597 * the old daemon in do_setup to start all over again as a heavy-weight 598 * reset. 599 */ 600 #if 0 601 int fd; 602 603 fd = open(OP_DATA_DIR"/samples/current", O_RDONLY); 604 if (fd == -1) { 605 return; 606 } 607 close(fd); 608 system("rm -r "OP_DATA_DIR"/samples/current"); 609 int num = read_num(OP_DATA_DIR"/lock"); 610 611 if (num >= 0) { 612 printf("Signalling daemon...\n"); 613 kill(num, SIGHUP); 614 } 615 #endif 616 } 617 618 int main(int argc, char * const argv[]) 619 { 620 int option_index; 621 bool show_status = false; 622 char* verbose_log = NULL; 623 624 /* Initialize default strings */ 625 strcpy(vmlinux, "--no-vmlinux"); 626 strcpy(kernel_range, ""); 627 628 while (1) { 629 int c = getopt_long(argc, argv, "c:e:v:r:dhVtl:", long_options, &option_index); 630 if (c == -1) { 631 break; 632 } 633 switch (c) { 634 case 0: 635 break; 636 /* --callgraph */ 637 case 'c': 638 strncpy(callgraph, optarg, sizeof(callgraph)); 639 break; 640 /* --event */ 641 case 'e': 642 if (num_events == MAX_EVENTS) { 643 fprintf(stderr, "More than %d events specified\n", 644 MAX_EVENTS); 645 exit(1); 646 } 647 if (process_event(optarg)) { 648 exit(1); 649 } 650 break; 651 /* --vmlinux */ 652 case 'v': 653 sprintf(vmlinux, "-k %s", optarg); 654 break; 655 /* --kernel-range */ 656 case 'r': 657 sprintf(kernel_range, "-r %s", optarg); 658 break; 659 case 'd': 660 /* --dump */ { 661 int pid = read_num(OP_DATA_DIR"/lock"); 662 echo_dev("1", 0, "dump", -1); 663 break; 664 } 665 /* --shutdown */ 666 case 'h': { 667 int pid = read_num(OP_DATA_DIR"/lock"); 668 if (pid >= 0) { 669 kill(pid, SIGHUP); /* Politely ask the daemon to close files */ 670 sleep(1); 671 kill(pid, SIGTERM);/* Politely ask the daemon to die */ 672 sleep(1); 673 kill(pid, SIGKILL); 674 } 675 setup_session_dir(); 676 break; 677 } 678 /* --verbose */ 679 case 'V': 680 verbose_print++; 681 break; 682 /* --verbose-log */ 683 case 'l': 684 verbose_log = strdup(optarg); 685 break; 686 /* --status */ 687 case 't': 688 show_status = true; 689 break; 690 default: 691 usage(); 692 exit(1); 693 } 694 } 695 verbose("list_events = %d\n", list_events); 696 verbose("setup = %d\n", setup); 697 698 if (list_events) { 699 do_list_events(); 700 } 701 702 if (quick) { 703 #if defined(__i386__) || defined(__x86_64__) 704 process_event("CPU_CLK_UNHALTED"); 705 #else 706 process_event("CPU_CYCLES"); 707 #endif 708 setup = 1; 709 } 710 711 if (timer) { 712 setup = 1; 713 } 714 715 if (reset) { 716 do_reset(); 717 } 718 719 if (show_usage) { 720 usage(); 721 } 722 723 if (setup) { 724 if (do_setup()) { 725 fprintf(stderr, "do_setup failed"); 726 exit(1); 727 } 728 } 729 730 if (strlen(callgraph)) { 731 echo_dev(callgraph, 0, "backtrace_depth", -1); 732 } 733 734 if (num_events != 0 || timer != 0) { 735 char command[1024]; 736 int i; 737 738 strcpy(command, argv[0]); 739 char* slash = strrchr(command, '/'); 740 strcpy(slash ? slash + 1 : command, "oprofiled --session-dir="OP_DATA_DIR); 741 742 #if defined(__i386__) || defined(__x86_64__) 743 /* Nothing */ 744 #elif !defined(WITH_ARM_V7_A) 745 /* Since counter #3 can only handle CPU_CYCLES, check and shuffle the 746 * order a bit so that the maximal number of events can be profiled 747 * simultaneously 748 */ 749 if (num_events == 3) { 750 for (i = 0; i < num_events; i++) { 751 int event_idx = selected_events[i]; 752 753 if (event_info[event_idx].id == 0xff) { 754 break; 755 } 756 } 757 758 /* No CPU_CYCLES is found */ 759 if (i == 3) { 760 fprintf(stderr, "You can only specify three events if one of " 761 "them is CPU_CYCLES\n"); 762 exit(1); 763 } 764 /* Swap CPU_CYCLES to counter #2 (starting from #0)*/ 765 else if (i != 2) { 766 int temp; 767 768 temp = selected_events[2]; 769 selected_events[2] = selected_events[i]; 770 selected_events[i] = temp; 771 772 temp = selected_counts[2]; 773 selected_counts[2] = selected_counts[i]; 774 selected_counts[i] = temp; 775 } 776 } 777 #endif 778 779 /* Configure the counters and enable them */ 780 for (i = 0; i < num_events; i++) { 781 int event_idx = selected_events[i]; 782 int setup_result = 0; 783 784 if (i == 0) { 785 snprintf(command + strlen(command), sizeof(command) - strlen(command), 786 " --events="); 787 } else { 788 snprintf(command + strlen(command), sizeof(command) - strlen(command), ","); 789 } 790 /* Compose name:id:count:unit_mask:kernel:user, something like 791 * --events=CYCLES_DATA_STALL:2:0:200000:0:1:1,.... 792 */ 793 snprintf(command + strlen(command), sizeof(command) - strlen(command), 794 "%s:%d:%d:%d:%d:1:1", 795 event_info[event_idx].name, 796 event_info[event_idx].id, 797 i, 798 selected_counts[i], 799 event_info[event_idx].um); 800 801 setup_result |= echo_dev("1", 0, "user", i); 802 setup_result |= echo_dev("1", 0, "kernel", i); 803 setup_result |= echo_dev(NULL, event_info[event_idx].um, "unit_mask", i); 804 setup_result |= echo_dev("1", 0, "enabled", i); 805 setup_result |= echo_dev(NULL, selected_counts[i], "count", i); 806 setup_result |= echo_dev(NULL, event_info[event_idx].id, 807 "event", i); 808 if (setup_result) { 809 fprintf(stderr, "Counter configuration failed for %s\n", 810 event_info[event_idx].name); 811 fprintf(stderr, "Did you do \"opcontrol --setup\" first?\n"); 812 exit(1); 813 } 814 } 815 816 if (timer == 0) { 817 /* If not in timer mode, disable unused counters */ 818 for (i = num_events; i < MAX_EVENTS; i++) { 819 echo_dev("0", 0, "enabled", i); 820 } 821 } else { 822 /* Timer mode uses empty event list */ 823 snprintf(command + strlen(command), sizeof(command) - strlen(command), 824 " --events="); 825 } 826 827 snprintf(command + strlen(command), sizeof(command) - strlen(command), 828 " %s", vmlinux); 829 if (kernel_range[0]) { 830 snprintf(command + strlen(command), sizeof(command) - strlen(command), 831 " %s", kernel_range); 832 } 833 834 if (verbose_log) { 835 snprintf(command + strlen(command), sizeof(command) - strlen(command), 836 " --verbose=%s", verbose_log); 837 } 838 839 printf("Starting oprofiled...\n"); 840 verbose("command: %s\n", command); 841 842 int rc = system(command); 843 if (rc) { 844 fprintf(stderr, "Failed, oprofile returned exit code: %d\n", rc); 845 } else { 846 sleep(2); 847 printf("Ready\n"); 848 } 849 } 850 851 if (start) { 852 echo_dev("1", 0, "enable", -1); 853 int num = read_num(OP_DATA_DIR"/lock"); 854 855 if (num >= 0) { 856 kill(num, SIGUSR1); 857 } 858 } 859 860 if (stop) { 861 echo_dev("1", 0, "dump", -1); 862 echo_dev("0", 0, "enable", -1); 863 } 864 865 if (show_status) { 866 do_status(); 867 } 868 } 869