PerfSource::PerfSource(PerfDriver & driver, Child & child, sem_t & senderSem, sem_t & startProfile, const std::set<int> & appTids, FtraceDriver & ftraceDriver, bool enableOnCommandExec, ICpuInfo & cpuInfo) : Source(child), mSummary(1024 * 1024, &senderSem), mCountersBuf(createPerfBufferConfig()), mCountersGroup(driver.getConfig(), mCountersBuf.calculateBufferLength(), gSessionData.mBacktraceDepth, gSessionData.mSampleRate, gSessionData.mIsEBS, cpuInfo.getClusters(), cpuInfo.getClusterIds(), getTracepointId(SCHED_SWITCH)), mMonitor(), mUEvent(), mAppTids(appTids), mDriver(driver), mAttrsBuffer(NULL), mSenderSem(senderSem), mStartProfile(startProfile), mInterruptFd(-1), mIsDone(false), mFtraceDriver(ftraceDriver), mCpuInfo(cpuInfo), mSyncThreads(), enableOnCommandExec(false) { const PerfConfig & mConfig = mDriver.getConfig(); if ((!mConfig.is_system_wide) && (!mConfig.has_attr_clockid_support)) { logg.logMessage("Tracing gatord as well as target application as no clock_id support"); mAppTids.insert(getpid()); } // was !enableOnCommandExec but this causes us to miss the exec comm record associated with the this->enableOnCommandExec = (enableOnCommandExec && mConfig.has_attr_clockid_support && mConfig.has_attr_comm_exec); }
static PerfEventType* forName(const char* name) { // First, look through the table of predefined perf events for (PerfEventType* event = AVAILABLE_EVENTS; event->name != NULL; event++) { if (strcmp(name, event->name) == 0) { return event; } } // Second, try kernel tracepoints defined in debugfs if (strchr(name, ':') != NULL) { int tracepoint_id = getTracepointId(name); if (tracepoint_id > 0) { KERNEL_TRACEPOINT.config = tracepoint_id; return &KERNEL_TRACEPOINT; } } return NULL; }
bool PerfDriver::setup() { // Check the kernel version struct utsname utsname; if (uname(&utsname) != 0) { logg->logMessage("%s(%s:%i): uname failed", __FUNCTION__, __FILE__, __LINE__); return false; } int release[3] = { 0, 0, 0 }; int part = 0; char *ch = utsname.release; while (*ch >= '0' && *ch <= '9' && part < ARRAY_LENGTH(release)) { release[part] = 10*release[part] + *ch - '0'; ++ch; if (*ch == '.') { ++part; ++ch; } } if (KERNEL_VERSION(release[0], release[1], release[2]) < KERNEL_VERSION(3, 4, 0)) { logg->logMessage("%s(%s:%i): Unsupported kernel version", __FUNCTION__, __FILE__, __LINE__); return false; } mLegacySupport = KERNEL_VERSION(release[0], release[1], release[2]) < KERNEL_VERSION(3, 12, 0); if (access(EVENTS_PATH, R_OK) != 0) { logg->logMessage("%s(%s:%i): " EVENTS_PATH " does not exist, is CONFIG_TRACING enabled?", __FUNCTION__, __FILE__, __LINE__); return false; } // Add supported PMUs bool foundCpu = false; DIR *dir = opendir(PERF_DEVICES); if (dir == NULL) { logg->logMessage("%s(%s:%i): opendif failed", __FUNCTION__, __FILE__, __LINE__); return false; } struct dirent *dirent; while ((dirent = readdir(dir)) != NULL) { for (int i = 0; i < ARRAY_LENGTH(gator_cpus); ++i) { // Do the names match exactly? if (strcmp(dirent->d_name, gator_cpus[i].pmnc_name) != 0 && // Do these names match but have the old vs new prefix? (strncmp(dirent->d_name, OLD_PMU_PREFIX, sizeof(OLD_PMU_PREFIX) - 1) != 0 || strncmp(gator_cpus[i].pmnc_name, NEW_PMU_PREFIX, sizeof(NEW_PMU_PREFIX) - 1) != 0 || strcmp(dirent->d_name + sizeof(OLD_PMU_PREFIX) - 1, gator_cpus[i].pmnc_name + sizeof(NEW_PMU_PREFIX) - 1) != 0)) { continue; } int type; char buf[256]; snprintf(buf, sizeof(buf), PERF_DEVICES "/%s/type", dirent->d_name); if (DriverSource::readIntDriver(buf, &type) != 0) { continue; } foundCpu = true; addCpuCounters(gator_cpus[i].pmnc_name, type, gator_cpus[i].pmnc_counters); } for (int i = 0; i < ARRAY_LENGTH(uncore_counters); ++i) { if (strcmp(dirent->d_name, uncore_counters[i].name) != 0) { continue; } int type; char buf[256]; snprintf(buf, sizeof(buf), PERF_DEVICES "/%s/type", dirent->d_name); if (DriverSource::readIntDriver(buf, &type) != 0) { continue; } addUncoreCounters(uncore_counters[i].name, type, uncore_counters[i].count); } } closedir(dir); if (!foundCpu) { // If no cpu was found based on pmu names, try by cpuid for (int i = 0; i < ARRAY_LENGTH(gator_cpus); ++i) { if (gSessionData->mMaxCpuId != gator_cpus[i].cpuid) { continue; } foundCpu = true; addCpuCounters(gator_cpus[i].pmnc_name, PERF_TYPE_RAW, gator_cpus[i].pmnc_counters); } } /* if (!foundCpu) { // If all else fails, use the perf architected counters // 9 because that's how many are in events-Perf-Hardware.xml - assume they can all be enabled at once addCpuCounters("Perf_Hardware", PERF_TYPE_HARDWARE, 9); } */ // Add supported software counters long long id; DynBuf printb; id = getTracepointId("irq/softirq_exit", &printb); if (id >= 0) { mCounters = new PerfCounter(mCounters, "Linux_irq_softirq", PERF_TYPE_TRACEPOINT, id, true); } id = getTracepointId("irq/irq_handler_exit", &printb); if (id >= 0) { mCounters = new PerfCounter(mCounters, "Linux_irq_irq", PERF_TYPE_TRACEPOINT, id, true); } //Linux_block_rq_wr //Linux_block_rq_rd //Linux_net_rx //Linux_net_tx id = getTracepointId(SCHED_SWITCH, &printb); if (id >= 0) { mCounters = new PerfCounter(mCounters, "Linux_sched_switch", PERF_TYPE_TRACEPOINT, id, true); } //Linux_meminfo_memused //Linux_meminfo_memfree //Linux_meminfo_bufferram //Linux_power_cpu_freq //Linux_power_cpu_idle mCounters = new PerfCounter(mCounters, "Linux_cpu_wait_contention", TYPE_DERIVED, -1, false); //Linux_cpu_wait_io mIsSetup = true; return true; }