bool PerfSource::prepare() { DynBuf printb; DynBuf b1; long long schedSwitchId; long long cpuIdleId; const uint64_t currTime = getTime(); // Reread cpuinfo since cores may have changed since startup gSessionData->readCpuInfo(); if (0 || !mMonitor.init() || !mUEvent.init() || !mMonitor.add(mUEvent.getFd()) || (schedSwitchId = PerfDriver::getTracepointId(SCHED_SWITCH, &printb)) < 0 || !sendTracepointFormat(currTime, &mBuffer, SCHED_SWITCH, &printb, &b1) || (cpuIdleId = PerfDriver::getTracepointId(CPU_IDLE, &printb)) < 0 || !sendTracepointFormat(currTime, &mBuffer, CPU_IDLE, &printb, &b1) // Only want RAW but not IP on sched_switch and don't want TID on SAMPLE_ID || !mCountersGroup.add(currTime, &mBuffer, 100/**/, PERF_TYPE_TRACEPOINT, schedSwitchId, 1, PERF_SAMPLE_RAW, PERF_GROUP_MMAP | PERF_GROUP_COMM | PERF_GROUP_TASK | PERF_GROUP_SAMPLE_ID_ALL | PERF_GROUP_PER_CPU) || !mIdleGroup.add(currTime, &mBuffer, 101/**/, PERF_TYPE_TRACEPOINT, cpuIdleId, 1, PERF_SAMPLE_RAW, PERF_GROUP_PER_CPU) // Only want TID and IP but not RAW on timer || (gSessionData->mSampleRate > 0 && !gSessionData->mIsEBS && !mCountersGroup.add(currTime, &mBuffer, 102/**/, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_CPU_CLOCK, 1000000000UL / gSessionData->mSampleRate, PERF_SAMPLE_TID | PERF_SAMPLE_IP, PERF_GROUP_PER_CPU)) || !gSessionData->perf.enable(currTime, &mCountersGroup, &mBuffer) || 0) { logg->logMessage("%s(%s:%i): perf setup failed, are you running Linux 3.4 or later?", __FUNCTION__, __FILE__, __LINE__); return false; } for (int cpu = 0; cpu < gSessionData->mCores; ++cpu) { const int result = mCountersGroup.prepareCPU(cpu, &mMonitor); if ((result != PG_SUCCESS) && (result != PG_CPU_OFFLINE)) { logg->logError(__FILE__, __LINE__, "PerfGroup::prepareCPU on mCountersGroup failed"); handleException(); } } for (int cpu = 0; cpu < gSessionData->mCores; ++cpu) { const int result = mIdleGroup.prepareCPU(cpu, &mMonitor); if ((result != PG_SUCCESS) && (result != PG_CPU_OFFLINE)) { logg->logError(__FILE__, __LINE__, "PerfGroup::prepareCPU on mIdleGroup failed"); handleException(); } } int numEvents = 0; for (int cpu = 0; cpu < gSessionData->mCores; ++cpu) { numEvents += mCountersGroup.onlineCPU(currTime, cpu, false, &mBuffer); } for (int cpu = 0; cpu < gSessionData->mCores; ++cpu) { numEvents += mIdleGroup.onlineCPU(currTime, cpu, false, &mBuffer); } if (numEvents <= 0) { logg->logMessage("%s(%s:%i): PerfGroup::onlineCPU failed on all cores", __FUNCTION__, __FILE__, __LINE__); return false; } // Send the summary right before the start so that the monotonic delta is close to the start time if (!gSessionData->perf.summary(&mSummary)) { logg->logError(__FILE__, __LINE__, "PerfDriver::summary failed", __FUNCTION__, __FILE__, __LINE__); handleException(); } // Start the timer thread to used to sync perf and monotonic raw times pthread_t syncThread; if (pthread_create(&syncThread, NULL, syncFunc, NULL)) { logg->logError(__FILE__, __LINE__, "pthread_create failed", __FUNCTION__, __FILE__, __LINE__); handleException(); } struct sched_param param; param.sched_priority = sched_get_priority_max(SCHED_FIFO); if (pthread_setschedparam(syncThread, SCHED_FIFO | SCHED_RESET_ON_FORK, ¶m) != 0) { logg->logError(__FILE__, __LINE__, "pthread_setschedparam failed"); handleException(); } mBuffer.commit(currTime); return true; }
bool PerfSource::prepare() { DynBuf printb; DynBuf b1; DynBuf b2; DynBuf b3; long long schedSwitchId; // Reread cpuinfo since cores may have changed since startup gSessionData->readCpuInfo(); if (0 || !mMonitor.init() || !mUEvent.init() || !mMonitor.add(mUEvent.getFd()) || (schedSwitchId = PerfDriver::getTracepointId(SCHED_SWITCH, &printb)) < 0 || !sendTracepointFormat(&mBuffer, SCHED_SWITCH, &printb, &b1) // Only want RAW but not IP on sched_switch and don't want TID on SAMPLE_ID || !mCountersGroup.add(&mBuffer, 100/**/, PERF_TYPE_TRACEPOINT, schedSwitchId, 1, PERF_SAMPLE_RAW, PERF_GROUP_MMAP | PERF_GROUP_COMM | PERF_GROUP_TASK | PERF_GROUP_SAMPLE_ID_ALL | PERF_GROUP_PER_CPU) // Only want TID and IP but not RAW on timer || (gSessionData->mSampleRate > 0 && !gSessionData->mIsEBS && !mCountersGroup.add(&mBuffer, 99/**/, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_CPU_CLOCK, 1000000000UL / gSessionData->mSampleRate, PERF_SAMPLE_TID | PERF_SAMPLE_IP, PERF_GROUP_PER_CPU)) || !gSessionData->perf.enable(&mCountersGroup, &mBuffer) || 0) { logg->logMessage("%s(%s:%i): perf setup failed, are you running Linux 3.4 or later?", __FUNCTION__, __FILE__, __LINE__); return false; } if (!gSessionData->perf.summary(&mSummary)) { logg->logMessage("%s(%s:%i): PerfDriver::summary failed", __FUNCTION__, __FILE__, __LINE__); return false; } { // Run prepareCPU in parallel as perf_event_open can take more than 1 sec in some cases pthread_t threads[NR_CPUS]; PrepareParallelArgs args[NR_CPUS]; for (int cpu = 0; cpu < gSessionData->mCores; ++cpu) { args[cpu].pg = &mCountersGroup; args[cpu].cpu = cpu; if (pthread_create(&threads[cpu], NULL, prepareParallel, &args[cpu]) != 0) { logg->logMessage("%s(%s:%i): pthread_create failed", __FUNCTION__, __FILE__, __LINE__); return false; } } for (int cpu = 0; cpu < gSessionData->mCores; ++cpu) { if (pthread_join(threads[cpu], NULL) != 0) { logg->logMessage("%s(%s:%i): pthread_join failed", __FUNCTION__, __FILE__, __LINE__); return false; } } } int numEvents = 0; for (int cpu = 0; cpu < gSessionData->mCores; ++cpu) { numEvents += mCountersGroup.onlineCPU(cpu, false, &mBuffer, &mMonitor); } if (numEvents <= 0) { logg->logMessage("%s(%s:%i): PerfGroup::onlineCPU failed on all cores", __FUNCTION__, __FILE__, __LINE__); return false; } // Start events before reading proc to avoid race conditions if (!mCountersGroup.start()) { logg->logMessage("%s(%s:%i): PerfGroup::start failed", __FUNCTION__, __FILE__, __LINE__); return false; } if (!readProc(&mBuffer, true, &printb, &b1, &b2, &b3)) { logg->logMessage("%s(%s:%i): readProc failed", __FUNCTION__, __FILE__, __LINE__); return false; } mBuffer.commit(1); return true; }