blob: 6b440e21f0128b3c91cc0e8aeaf436b6587bb93a [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>
Jean-Baptiste Querud850f372010-05-03 15:16:06 -070026#include <string.h>
The Android Open Source Project10e23ee2009-03-03 19:30:30 -080027#include <errno.h>
28#include <fcntl.h>
29#include <signal.h>
Jeff Brown87866d92011-02-02 13:27:17 -080030#include <dirent.h>
The Android Open Source Project10e23ee2009-03-03 19:30:30 -080031#include <sys/stat.h>
Jeff Brown87866d92011-02-02 13:27:17 -080032#include <sys/types.h>
33#include <sys/wait.h>
The Android Open Source Project10e23ee2009-03-03 19:30:30 -080034
35#include "op_config.h"
36
Bruce Beare751a4432010-03-04 10:30:51 -080037#define verbose(fmt...) if (verbose_print) printf(fmt)
The Android Open Source Project10e23ee2009-03-03 19:30:30 -080038
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
Bruce Beare751a4432010-03-04 10:30:51 -080043#if defined(__i386__) || defined(__x86_64__)
44#define MAX_EVENTS 2
45int min_count[MAX_EVENTS] = {60000, 100000};
46#elif !defined(WITH_ARM_V7_A)
Ben Cheng5a4eb4e2009-09-14 16:00:41 -070047#define MAX_EVENTS 3
Ben Cheng14345072009-09-16 11:31:39 -070048int min_count[MAX_EVENTS] = {150000, 200000, 250000};
Ben Cheng5a4eb4e2009-09-14 16:00:41 -070049#else
Ben Cheng14345072009-09-16 11:31:39 -070050#define MAX_EVENTS 5
Ben Chengafec5b92010-02-22 15:33:08 -080051int min_count[MAX_EVENTS] = {150000, 20000, 25000, 30000, 35000};
Ben Cheng5a4eb4e2009-09-14 16:00:41 -070052#endif
53
Bruce Beare751a4432010-03-04 10:30:51 -080054int verbose_print;
The Android Open Source Project10e23ee2009-03-03 19:30:30 -080055int list_events;
56int show_usage;
57int setup;
58int quick;
Ben Chenga9404b82010-09-03 16:46:45 -070059int timer;
The Android Open Source Project10e23ee2009-03-03 19:30:30 -080060int num_events;
61int start;
62int stop;
63int reset;
64
Ben Cheng5a4eb4e2009-09-14 16:00:41 -070065int selected_events[MAX_EVENTS];
66int selected_counts[MAX_EVENTS];
The Android Open Source Project10e23ee2009-03-03 19:30:30 -080067
Bruce Beare751a4432010-03-04 10:30:51 -080068char callgraph[8];
The Android Open Source Project10e23ee2009-03-03 19:30:30 -080069char kernel_range[512];
70char vmlinux[512];
71
72struct 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},
Ben Chenga9404b82010-09-03 16:46:45 -070078 {"timer", 0, &timer, 1},
Bruce Beare751a4432010-03-04 10:30:51 -080079 {"callgraph", 1, 0, 'c'},
The Android Open Source Project10e23ee2009-03-03 19:30:30 -080080 {"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},
Bruce Beare751a4432010-03-04 10:30:51 -080085 {"dump", 0, 0, 'd'},
The Android Open Source Project10e23ee2009-03-03 19:30:30 -080086 {"shutdown", 0, 0, 'h'},
87 {"status", 0, 0, 't'},
Bruce Beare751a4432010-03-04 10:30:51 -080088 {"verbose", 0, 0, 'V'},
Jeff Brown87866d92011-02-02 13:27:17 -080089 {"verbose-log", 1, 0, 'l'},
The Android Open Source Project10e23ee2009-03-03 19:30:30 -080090 {0, 0, 0, 0},
91};
92
93struct event_info {
94 int id;
Bruce Beare751a4432010-03-04 10:30:51 -080095 int um;
The Android Open Source Project10e23ee2009-03-03 19:30:30 -080096 const char *name;
97 const char *explanation;
98} event_info[] = {
Bruce Beare751a4432010-03-04 10:30:51 -080099#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)
Ben Cheng5a4eb4e2009-09-14 16:00:41 -0700145 /* ARM V6 events */
Bruce Beare751a4432010-03-04 10:30:51 -0800146 {0x00, 0, "IFU_IFETCH_MISS",
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800147 "number of instruction fetch misses"},
Bruce Beare751a4432010-03-04 10:30:51 -0800148 {0x01, 0, "CYCLES_IFU_MEM_STALL",
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800149 "cycles instruction fetch pipe is stalled"},
Bruce Beare751a4432010-03-04 10:30:51 -0800150 {0x02, 0, "CYCLES_DATA_STALL",
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800151 "cycles stall occurs for due to data dependency"},
Bruce Beare751a4432010-03-04 10:30:51 -0800152 {0x03, 0, "ITLB_MISS",
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800153 "number of Instruction MicroTLB misses"},
Bruce Beare751a4432010-03-04 10:30:51 -0800154 {0x04, 0, "DTLB_MISS",
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800155 "number of Data MicroTLB misses"},
Bruce Beare751a4432010-03-04 10:30:51 -0800156 {0x05, 0, "BR_INST_EXECUTED",
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800157 "branch instruction executed w/ or w/o program flow change"},
Bruce Beare751a4432010-03-04 10:30:51 -0800158 {0x06, 0, "BR_INST_MISS_PRED",
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800159 "branch mispredicted"},
Bruce Beare751a4432010-03-04 10:30:51 -0800160 {0x07, 0, "INSN_EXECUTED",
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800161 "instructions executed"},
Bruce Beare751a4432010-03-04 10:30:51 -0800162 {0x09, 0, "DCACHE_ACCESS",
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800163 "data cache access, cacheable locations"},
Bruce Beare751a4432010-03-04 10:30:51 -0800164 {0x0a, 0, "DCACHE_ACCESS_ALL",
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800165 "data cache access, all locations"},
Bruce Beare751a4432010-03-04 10:30:51 -0800166 {0x0b, 0, "DCACHE_MISS",
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800167 "data cache miss"},
Bruce Beare751a4432010-03-04 10:30:51 -0800168 {0x0c, 0, "DCACHE_WB",
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800169 "data cache writeback, 1 event for every half cacheline"},
Bruce Beare751a4432010-03-04 10:30:51 -0800170 {0x0d, 0, "PC_CHANGE",
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800171 "number of times the program counter was changed without a mode switch"},
Bruce Beare751a4432010-03-04 10:30:51 -0800172 {0x0f, 0, "TLB_MISS",
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800173 "Main TLB miss"},
Bruce Beare751a4432010-03-04 10:30:51 -0800174 {0x10, 0, "EXP_EXTERNAL",
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800175 "Explicit external data access"},
Bruce Beare751a4432010-03-04 10:30:51 -0800176 {0x11, 0, "LSU_STALL",
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800177 "cycles stalled because Load Store request queue is full"},
Bruce Beare751a4432010-03-04 10:30:51 -0800178 {0x12, 0, "WRITE_DRAIN",
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800179 "Times write buffer was drained"},
Bruce Beare751a4432010-03-04 10:30:51 -0800180 {0xff, 0, "CPU_CYCLES",
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800181 "clock cycles counter"},
Ben Cheng5a4eb4e2009-09-14 16:00:41 -0700182#else
183 /* ARM V7 events */
Bruce Beare751a4432010-03-04 10:30:51 -0800184 {0x00, 0, "PMNC_SW_INCR",
Ben Cheng5a4eb4e2009-09-14 16:00:41 -0700185 "Software increment of PMNC registers"},
Bruce Beare751a4432010-03-04 10:30:51 -0800186 {0x01, 0, "IFETCH_MISS",
Ben Cheng5a4eb4e2009-09-14 16:00:41 -0700187 "Instruction fetch misses from cache or normal cacheable memory"},
Bruce Beare751a4432010-03-04 10:30:51 -0800188 {0x02, 0, "ITLB_MISS",
Ben Cheng5a4eb4e2009-09-14 16:00:41 -0700189 "Instruction fetch misses from TLB"},
Bruce Beare751a4432010-03-04 10:30:51 -0800190 {0x03, 0, "DCACHE_REFILL",
Ben Cheng5a4eb4e2009-09-14 16:00:41 -0700191 "Data R/W operation that causes a refill from cache or normal cacheable"
192 "memory"},
Bruce Beare751a4432010-03-04 10:30:51 -0800193 {0x04, 0, "DCACHE_ACCESS",
Ben Cheng5a4eb4e2009-09-14 16:00:41 -0700194 "Data R/W from cache"},
Bruce Beare751a4432010-03-04 10:30:51 -0800195 {0x05, 0, "DTLB_REFILL",
Ben Cheng5a4eb4e2009-09-14 16:00:41 -0700196 "Data R/W that causes a TLB refill"},
Bruce Beare751a4432010-03-04 10:30:51 -0800197 {0x06, 0, "DREAD",
Ben Cheng5a4eb4e2009-09-14 16:00:41 -0700198 "Data read architecturally executed (note: architecturally executed = for"
199 "instructions that are unconditional or that pass the condition code)"},
Bruce Beare751a4432010-03-04 10:30:51 -0800200 {0x07, 0, "DWRITE",
Ben Cheng5a4eb4e2009-09-14 16:00:41 -0700201 "Data write architecturally executed"},
Bruce Beare751a4432010-03-04 10:30:51 -0800202 {0x08, 0, "INSTR_EXECUTED",
Ben Cheng5a4eb4e2009-09-14 16:00:41 -0700203 "All executed instructions"},
Bruce Beare751a4432010-03-04 10:30:51 -0800204 {0x09, 0, "EXC_TAKEN",
Ben Cheng5a4eb4e2009-09-14 16:00:41 -0700205 "Exception taken"},
Bruce Beare751a4432010-03-04 10:30:51 -0800206 {0x0A, 0, "EXC_EXECUTED",
Ben Cheng5a4eb4e2009-09-14 16:00:41 -0700207 "Exception return architecturally executed"},
Mike Lockwoode815c522010-04-30 08:30:05 -0400208 {0x0B, 0, "CID_WRITE",
Ben Cheng5a4eb4e2009-09-14 16:00:41 -0700209 "Instruction that writes to the Context ID Register architecturally"
210 "executed"},
Mike Lockwoode815c522010-04-30 08:30:05 -0400211 {0x0C, 0, "PC_WRITE",
Ben Cheng5a4eb4e2009-09-14 16:00:41 -0700212 "SW change of PC, architecturally executed (not by exceptions)"},
Mike Lockwoode815c522010-04-30 08:30:05 -0400213 {0x0D, 0, "PC_IMM_BRANCH",
Ben Cheng5a4eb4e2009-09-14 16:00:41 -0700214 "Immediate branch instruction executed (taken or not)"},
Mike Lockwoode815c522010-04-30 08:30:05 -0400215 {0x0E, 0, "PC_PROC_RETURN",
Ben Cheng5a4eb4e2009-09-14 16:00:41 -0700216 "Procedure return architecturally executed (not by exceptions)"},
Mike Lockwoode815c522010-04-30 08:30:05 -0400217 {0x0F, 0, "UNALIGNED_ACCESS",
Ben Cheng5a4eb4e2009-09-14 16:00:41 -0700218 "Unaligned access architecturally executed"},
Mike Lockwoode815c522010-04-30 08:30:05 -0400219 {0x10, 0, "PC_BRANCH_MIS_PRED",
Ben Cheng5a4eb4e2009-09-14 16:00:41 -0700220 "Branch mispredicted or not predicted. Counts pipeline flushes because of"
221 "misprediction"},
Mike Lockwoode815c522010-04-30 08:30:05 -0400222 {0x12, 0, "PC_BRANCH_MIS_USED",
Ben Cheng5a4eb4e2009-09-14 16:00:41 -0700223 "Branch or change in program flow that could have been predicted"},
Mike Lockwoode815c522010-04-30 08:30:05 -0400224 {0x40, 0, "WRITE_BUFFER_FULL",
Ben Cheng5a4eb4e2009-09-14 16:00:41 -0700225 "Any write buffer full cycle"},
Mike Lockwoode815c522010-04-30 08:30:05 -0400226 {0x41, 0, "L2_STORE_MERGED",
Ben Cheng5a4eb4e2009-09-14 16:00:41 -0700227 "Any store that is merged in L2 cache"},
Mike Lockwoode815c522010-04-30 08:30:05 -0400228 {0x42, 0, "L2_STORE_BUFF",
Ben Cheng5a4eb4e2009-09-14 16:00:41 -0700229 "Any bufferable store from load/store to L2 cache"},
Mike Lockwoode815c522010-04-30 08:30:05 -0400230 {0x43, 0, "L2_ACCESS",
Ben Cheng5a4eb4e2009-09-14 16:00:41 -0700231 "Any access to L2 cache"},
Mike Lockwoode815c522010-04-30 08:30:05 -0400232 {0x44, 0, "L2_CACH_MISS",
Ben Cheng5a4eb4e2009-09-14 16:00:41 -0700233 "Any cacheable miss in L2 cache"},
Mike Lockwoode815c522010-04-30 08:30:05 -0400234 {0x45, 0, "AXI_READ_CYCLES",
Ben Cheng5a4eb4e2009-09-14 16:00:41 -0700235 "Number of cycles for an active AXI read"},
Mike Lockwoode815c522010-04-30 08:30:05 -0400236 {0x46, 0, "AXI_WRITE_CYCLES",
Ben Cheng5a4eb4e2009-09-14 16:00:41 -0700237 "Number of cycles for an active AXI write"},
Mike Lockwoode815c522010-04-30 08:30:05 -0400238 {0x47, 0, "MEMORY_REPLAY",
Ben Cheng5a4eb4e2009-09-14 16:00:41 -0700239 "Any replay event in the memory subsystem"},
Mike Lockwoode815c522010-04-30 08:30:05 -0400240 {0x48, 0, "UNALIGNED_ACCESS_REPLAY",
Ben Cheng5a4eb4e2009-09-14 16:00:41 -0700241 "Unaligned access that causes a replay"},
Mike Lockwoode815c522010-04-30 08:30:05 -0400242 {0x49, 0, "L1_DATA_MISS",
Ben Cheng5a4eb4e2009-09-14 16:00:41 -0700243 "L1 data cache miss as a result of the hashing algorithm"},
Mike Lockwoode815c522010-04-30 08:30:05 -0400244 {0x4A, 0, "L1_INST_MISS",
Ben Cheng5a4eb4e2009-09-14 16:00:41 -0700245 "L1 instruction cache miss as a result of the hashing algorithm"},
Mike Lockwoode815c522010-04-30 08:30:05 -0400246 {0x4B, 0, "L1_DATA_COLORING",
Ben Cheng5a4eb4e2009-09-14 16:00:41 -0700247 "L1 data access in which a page coloring alias occurs"},
Mike Lockwoode815c522010-04-30 08:30:05 -0400248 {0x4C, 0, "L1_NEON_DATA",
Ben Cheng5a4eb4e2009-09-14 16:00:41 -0700249 "NEON data access that hits L1 cache"},
Mike Lockwoode815c522010-04-30 08:30:05 -0400250 {0x4D, 0, "L1_NEON_CACH_DATA",
Ben Cheng5a4eb4e2009-09-14 16:00:41 -0700251 "NEON cacheable data access that hits L1 cache"},
Mike Lockwoode815c522010-04-30 08:30:05 -0400252 {0x4E, 0, "L2_NEON",
Ben Cheng5a4eb4e2009-09-14 16:00:41 -0700253 "L2 access as a result of NEON memory access"},
Mike Lockwoode815c522010-04-30 08:30:05 -0400254 {0x4F, 0, "L2_NEON_HIT",
Ben Cheng5a4eb4e2009-09-14 16:00:41 -0700255 "Any NEON hit in L2 cache"},
Mike Lockwoode815c522010-04-30 08:30:05 -0400256 {0x50, 0, "L1_INST",
Ben Cheng5a4eb4e2009-09-14 16:00:41 -0700257 "Any L1 instruction cache access, excluding CP15 cache accesses"},
Mike Lockwoode815c522010-04-30 08:30:05 -0400258 {0x51, 0, "PC_RETURN_MIS_PRED",
Ben Cheng5a4eb4e2009-09-14 16:00:41 -0700259 "Return stack misprediction at return stack pop"
260 "(incorrect target address)"},
Mike Lockwoode815c522010-04-30 08:30:05 -0400261 {0x52, 0, "PC_BRANCH_FAILED",
Ben Cheng5a4eb4e2009-09-14 16:00:41 -0700262 "Branch prediction misprediction"},
Mike Lockwoode815c522010-04-30 08:30:05 -0400263 {0x53, 0, "PC_BRANCH_TAKEN",
Ben Cheng5a4eb4e2009-09-14 16:00:41 -0700264 "Any predicted branch that is taken"},
Mike Lockwoode815c522010-04-30 08:30:05 -0400265 {0x54, 0, "PC_BRANCH_EXECUTED",
Ben Cheng5a4eb4e2009-09-14 16:00:41 -0700266 "Any taken branch that is executed"},
Mike Lockwoode815c522010-04-30 08:30:05 -0400267 {0x55, 0, "OP_EXECUTED",
Ben Cheng5a4eb4e2009-09-14 16:00:41 -0700268 "Number of operations executed"
269 "(in instruction or mutli-cycle instruction)"},
Mike Lockwoode815c522010-04-30 08:30:05 -0400270 {0x56, 0, "CYCLES_INST_STALL",
Ben Cheng5a4eb4e2009-09-14 16:00:41 -0700271 "Cycles where no instruction available"},
Mike Lockwoode815c522010-04-30 08:30:05 -0400272 {0x57, 0, "CYCLES_INST",
Ben Cheng5a4eb4e2009-09-14 16:00:41 -0700273 "Number of instructions issued in a cycle"},
Mike Lockwoode815c522010-04-30 08:30:05 -0400274 {0x58, 0, "CYCLES_NEON_DATA_STALL",
Ben Cheng5a4eb4e2009-09-14 16:00:41 -0700275 "Number of cycles the processor waits on MRC data from NEON"},
Mike Lockwoode815c522010-04-30 08:30:05 -0400276 {0x59, 0, "CYCLES_NEON_INST_STALL",
Ben Cheng5a4eb4e2009-09-14 16:00:41 -0700277 "Number of cycles the processor waits on NEON instruction queue or"
278 "NEON load queue"},
Mike Lockwoode815c522010-04-30 08:30:05 -0400279 {0x5A, 0, "NEON_CYCLES",
Ben Cheng5a4eb4e2009-09-14 16:00:41 -0700280 "Number of cycles NEON and integer processors are not idle"},
Mike Lockwoode815c522010-04-30 08:30:05 -0400281 {0x70, 0, "PMU0_EVENTS",
Ben Cheng5a4eb4e2009-09-14 16:00:41 -0700282 "Number of events from external input source PMUEXTIN[0]"},
Mike Lockwoode815c522010-04-30 08:30:05 -0400283 {0x71, 0, "PMU1_EVENTS",
Ben Cheng5a4eb4e2009-09-14 16:00:41 -0700284 "Number of events from external input source PMUEXTIN[1]"},
Mike Lockwoode815c522010-04-30 08:30:05 -0400285 {0x72, 0, "PMU_EVENTS",
Ben Cheng5a4eb4e2009-09-14 16:00:41 -0700286 "Number of events from both external input sources PMUEXTIN[0]"
287 "and PMUEXTIN[1]"},
Mike Lockwoode815c522010-04-30 08:30:05 -0400288 {0xFF, 0, "CPU_CYCLES",
Ben Cheng5a4eb4e2009-09-14 16:00:41 -0700289 "Number of CPU cycles"},
290#endif
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800291};
292
Ben Cheng14345072009-09-16 11:31:39 -0700293void usage()
294{
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800295 printf("\nopcontrol: usage:\n"
296 " --list-events list event types\n"
297 " --help this message\n"
Bruce Beare751a4432010-03-04 10:30:51 -0800298 " --verbose show extra status\n"
Jeff Brown87866d92011-02-02 13:27:17 -0800299 " --verbose-log=lvl set daemon logging verbosity during setup\n"
300 " levels are: all,sfile,arcs,samples,module,misc\n"
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800301 " --setup setup directories\n"
Bruce Beare751a4432010-03-04 10:30:51 -0800302#if defined(__i386__) || defined(__x86_64__)
303 " --quick setup and select CPU_CLK_UNHALTED:60000\n"
304#else
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800305 " --quick setup and select CPU_CYCLES:150000\n"
Bruce Beare751a4432010-03-04 10:30:51 -0800306#endif
Ben Chenga9404b82010-09-03 16:46:45 -0700307 " --timer timer-based profiling\n"
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800308 " --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"
Bruce Beare751a4432010-03-04 10:30:51 -0800313 " --callgraph=depth callgraph depth\n"
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800314 " --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
Ben Cheng14345072009-09-16 11:31:39 -0700325void setup_session_dir()
326{
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800327 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
Mike Playled0950102010-07-09 17:02:22 +0100335 if (mkdir(OP_DATA_DIR, 0755)) {
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800336 fprintf(stderr, "Cannot create directory \"%s\": %s\n",
337 OP_DATA_DIR, strerror(errno));
338 }
Mike Playled0950102010-07-09 17:02:22 +0100339 if (mkdir(OP_DATA_DIR"/samples", 0755)) {
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800340 fprintf(stderr, "Cannot create directory \"%s\": %s\n",
341 OP_DATA_DIR"/samples", strerror(errno));
342 }
343}
344
Ben Cheng529d8682012-01-04 14:35:36 -0800345int 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
Ben Cheng14345072009-09-16 11:31:39 -0700356int do_setup()
357{
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800358 char dir[1024];
359
Ben Cheng529d8682012-01-04 14:35:36 -0800360 /*
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
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800371 setup_session_dir();
372
Mike Playled0950102010-07-09 17:02:22 +0100373 if (mkdir(OP_DRIVER_BASE, 0755)) {
Jeff Brown87866d92011-02-02 13:27:17 -0800374 if (errno != EEXIST) {
375 fprintf(stderr, "Cannot create directory "OP_DRIVER_BASE": %s\n",
376 strerror(errno));
377 return -1;
378 }
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800379 }
Jeff Brown87866d92011-02-02 13:27:17 -0800380
381 if (access(OP_DRIVER_BASE"/stats", F_OK)) {
382 if (system("mount -t oprofilefs nodev "OP_DRIVER_BASE)) {
383 return -1;
384 }
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800385 }
386 return 0;
387}
388
389void 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
Ben Cheng14345072009-09-16 11:31:39 -0700401int find_event_idx_from_name(const char *name)
402{
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800403 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
Ben Cheng14345072009-09-16 11:31:39 -0700413const char * find_event_name_from_id(int id)
414{
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800415 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
Ben Cheng14345072009-09-16 11:31:39 -0700425int process_event(const char *event_spec)
426{
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800427 char event_name[512];
428 char count_name[512];
429 unsigned int i;
Ben Cheng14345072009-09-16 11:31:39 -0700430 int event_idx;
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800431 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 }
Ben Cheng14345072009-09-16 11:31:39 -0700447 event_idx = find_event_idx_from_name(event_name);
448 if (event_idx == -1) {
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800449 fprintf(stderr, "Unknown event name: %s\n", event_name);
450 return -1;
451 }
452
Jeff Brown87866d92011-02-02 13:27:17 -0800453 /* Use default count */
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800454 if (count_name[0] == 0) {
455 count_val = min_count[0];
456 } else {
457 count_val = atoi(count_name);
458 }
459
Ben Cheng14345072009-09-16 11:31:39 -0700460 selected_events[num_events] = event_idx;
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800461 selected_counts[num_events++] = count_val;
Ben Cheng14345072009-09-16 11:31:39 -0700462 verbose("event_id is %d\n", event_info[event_idx].id);
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800463 verbose("count_val is %d\n", count_val);
464 return 0;
465}
466
467int 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
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800496void 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);
Ben Cheng5a4eb4e2009-09-14 16:00:41 -0700504 for (i = 0; i < MAX_EVENTS; i++) {
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800505 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) {
Ben Cheng529d8682012-01-04 14:35:36 -0800532 printf("OProfile daemon exited prematurely - redo setup"
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800533 " before you continue\n");
534 return;
535 }
536 else {
537 close(fd);
Jeff Brown87866d92011-02-02 13:27:17 -0800538
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800539 printf("oprofiled pid: %d\n", num);
540 num = read_num(OP_DRIVER_BASE"/enable");
Jeff Brown87866d92011-02-02 13:27:17 -0800541
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800542 printf("profiler is%s running\n", num == 0 ? " not" : "");
Jeff Brown87866d92011-02-02 13:27:17 -0800543
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 }
Bruce Beare751a4432010-03-04 10:30:51 -0800575
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800576 num = read_num(OP_DRIVER_BASE"/backtrace_depth");
Ben Cheng529d8682012-01-04 14:35:36 -0800577 printf("backtrace_depth: %u\n", num);
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800578 }
579 }
580 else {
581 printf("oprofiled is not running\n");
582 }
583}
584
585void do_reset()
586{
Ben Cheng529d8682012-01-04 14:35:36 -0800587 /*
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
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800601 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");
Ben Cheng529d8682012-01-04 14:35:36 -0800609 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
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800616}
617
618int main(int argc, char * const argv[])
619{
620 int option_index;
Jeff Brown87866d92011-02-02 13:27:17 -0800621 bool show_status = false;
622 char* verbose_log = NULL;
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800623
624 /* Initialize default strings */
625 strcpy(vmlinux, "--no-vmlinux");
626 strcpy(kernel_range, "");
627
628 while (1) {
Jeff Brown87866d92011-02-02 13:27:17 -0800629 int c = getopt_long(argc, argv, "c:e:v:r:dhVtl:", long_options, &option_index);
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800630 if (c == -1) {
631 break;
632 }
633 switch (c) {
634 case 0:
635 break;
Bruce Beare751a4432010-03-04 10:30:51 -0800636 /* --callgraph */
637 case 'c':
Jeff Brown87866d92011-02-02 13:27:17 -0800638 strncpy(callgraph, optarg, sizeof(callgraph));
Bruce Beare751a4432010-03-04 10:30:51 -0800639 break;
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800640 /* --event */
641 case 'e':
Ben Cheng5a4eb4e2009-09-14 16:00:41 -0700642 if (num_events == MAX_EVENTS) {
643 fprintf(stderr, "More than %d events specified\n",
644 MAX_EVENTS);
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800645 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;
Bruce Beare751a4432010-03-04 10:30:51 -0800659 case 'd':
660 /* --dump */ {
661 int pid = read_num(OP_DATA_DIR"/lock");
662 echo_dev("1", 0, "dump", -1);
Bruce Beare751a4432010-03-04 10:30:51 -0800663 break;
664 }
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800665 /* --shutdown */
666 case 'h': {
667 int pid = read_num(OP_DATA_DIR"/lock");
668 if (pid >= 0) {
Bruce Beare751a4432010-03-04 10:30:51 -0800669 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);
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800673 kill(pid, SIGKILL);
Jeff Brown87866d92011-02-02 13:27:17 -0800674 }
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800675 setup_session_dir();
676 break;
677 }
Bruce Beare751a4432010-03-04 10:30:51 -0800678 /* --verbose */
679 case 'V':
680 verbose_print++;
681 break;
Jeff Brown87866d92011-02-02 13:27:17 -0800682 /* --verbose-log */
683 case 'l':
684 verbose_log = strdup(optarg);
685 break;
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800686 /* --status */
687 case 't':
Jeff Brown87866d92011-02-02 13:27:17 -0800688 show_status = true;
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800689 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) {
Bruce Beare751a4432010-03-04 10:30:51 -0800703#if defined(__i386__) || defined(__x86_64__)
704 process_event("CPU_CLK_UNHALTED");
705#else
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800706 process_event("CPU_CYCLES");
Bruce Beare751a4432010-03-04 10:30:51 -0800707#endif
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800708 setup = 1;
709 }
710
Ben Chenga9404b82010-09-03 16:46:45 -0700711 if (timer) {
712 setup = 1;
713 }
714
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800715 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
Bruce Beare751a4432010-03-04 10:30:51 -0800730 if (strlen(callgraph)) {
731 echo_dev(callgraph, 0, "backtrace_depth", -1);
732 }
733
Ben Chenga9404b82010-09-03 16:46:45 -0700734 if (num_events != 0 || timer != 0) {
Jeff Brown87866d92011-02-02 13:27:17 -0800735 char command[1024];
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800736 int i;
737
Jeff Brown87866d92011-02-02 13:27:17 -0800738 strcpy(command, argv[0]);
739 char* slash = strrchr(command, '/');
740 strcpy(slash ? slash + 1 : command, "oprofiled --session-dir="OP_DATA_DIR);
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800741
Bruce Beare751a4432010-03-04 10:30:51 -0800742#if defined(__i386__) || defined(__x86_64__)
743 /* Nothing */
744#elif !defined(WITH_ARM_V7_A)
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800745 /* 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 }
Ben Cheng5a4eb4e2009-09-14 16:00:41 -0700777#endif
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800778
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800779 /* 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) {
Jeff Brown87866d92011-02-02 13:27:17 -0800785 snprintf(command + strlen(command), sizeof(command) - strlen(command),
786 " --events=");
787 } else {
788 snprintf(command + strlen(command), sizeof(command) - strlen(command), ",");
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800789 }
790 /* Compose name:id:count:unit_mask:kernel:user, something like
791 * --events=CYCLES_DATA_STALL:2:0:200000:0:1:1,....
792 */
Jeff Brown87866d92011-02-02 13:27:17 -0800793 snprintf(command + strlen(command), sizeof(command) - strlen(command),
Bruce Beare751a4432010-03-04 10:30:51 -0800794 "%s:%d:%d:%d:%d:1:1",
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800795 event_info[event_idx].name,
796 event_info[event_idx].id,
797 i,
Bruce Beare751a4432010-03-04 10:30:51 -0800798 selected_counts[i],
799 event_info[event_idx].um);
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800800
801 setup_result |= echo_dev("1", 0, "user", i);
802 setup_result |= echo_dev("1", 0, "kernel", i);
Bruce Beare751a4432010-03-04 10:30:51 -0800803 setup_result |= echo_dev(NULL, event_info[event_idx].um, "unit_mask", i);
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800804 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
Ben Chenga9404b82010-09-03 16:46:45 -0700816 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 */
Jeff Brown87866d92011-02-02 13:27:17 -0800823 snprintf(command + strlen(command), sizeof(command) - strlen(command),
824 " --events=");
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800825 }
826
Jeff Brown87866d92011-02-02 13:27:17 -0800827 snprintf(command + strlen(command), sizeof(command) - strlen(command),
828 " %s", vmlinux);
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800829 if (kernel_range[0]) {
Jeff Brown87866d92011-02-02 13:27:17 -0800830 snprintf(command + strlen(command), sizeof(command) - strlen(command),
831 " %s", kernel_range);
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800832 }
Jeff Brown87866d92011-02-02 13:27:17 -0800833
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");
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800840 verbose("command: %s\n", command);
Jeff Brown87866d92011-02-02 13:27:17 -0800841
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 }
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800849 }
850
851 if (start) {
852 echo_dev("1", 0, "enable", -1);
Ben Cheng529d8682012-01-04 14:35:36 -0800853 int num = read_num(OP_DATA_DIR"/lock");
854
855 if (num >= 0) {
856 kill(num, SIGUSR1);
857 }
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800858 }
859
860 if (stop) {
Ben Chengafec5b92010-02-22 15:33:08 -0800861 echo_dev("1", 0, "dump", -1);
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800862 echo_dev("0", 0, "enable", -1);
863 }
Jeff Brown87866d92011-02-02 13:27:17 -0800864
865 if (show_status) {
866 do_status();
867 }
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800868}