diff --git a/pmu/pmu.cpp b/pmu/pmu.cpp index 2f05b57d54b198f5d586000c24e52644f5a3f54a..56b46186d11f7310afa49f5f3d406da87a9a1d59 100644 --- a/pmu/pmu.cpp +++ b/pmu/pmu.cpp @@ -35,7 +35,7 @@ using namespace std; static unordered_map runningStatus; static SafeHandler pdMutex; -static const int NINE = 9; +static pair uncoreEventPair; struct PmuTaskAttr* AssignPmuTaskParam(PmuTaskType collectType, struct PmuAttr *attr); @@ -127,14 +127,11 @@ void AppendChildEvents(char* evt, unordered_map& eventSplitMap) auto findSlash = strName.find('/'); string devName = strName.substr(0, findSlash); string evtName = strName.substr(devName.size(), strName.size() - devName.size() + 1); - for (int i = 0; i <= NINE; i++) { - string typePath = "/sys/devices/"; - string childName = devName; - typePath += devName + to_string(i) + "/type"; - string realPath = GetRealPath(typePath); - childName += to_string(i) + evtName; - if (IsValidPath(realPath)) { - eventSplitMap.emplace(childName, evt); + auto numEvt = uncoreEventPair.first; + auto uncoreEventList = uncoreEventPair.second; + for (int i = 0; i < numEvt; ++i) { + if (std::strncmp(uncoreEventList[i], devName.c_str(), devName.length()) == 0) { + eventSplitMap.emplace(uncoreEventList[i], evt); } } } @@ -144,6 +141,9 @@ static void SplitUncoreEvent(struct PmuAttr *attr, unordered_map char** evtList = attr->evtList; unsigned size = attr->numEvt; int newSize = 0; + unsigned numEvt; + auto eventList = PmuEventList(UNCORE_EVENT, &numEvt); + uncoreEventPair = make_pair(numEvt, eventList); for (int i = 0; i < size; ++i) { char* evt = evtList[i]; char* slashPos = std::strchr(evt, '/'); diff --git a/pmu/pmu_event_list.cpp b/pmu/pmu_event_list.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7088388a8027bfed55a84069a747645c8d5489f3 --- /dev/null +++ b/pmu/pmu_event_list.cpp @@ -0,0 +1,185 @@ +/** + * @copyright Copyright (c) Huawei Technologies Co., Ltd. 2023-2023. All rights reserved. + * @brief + * @version 24.0 + * @date 2024-04-18 + */ +#include +#include +#include +#include +#include +#include +#include +#include "core.h" +#include "pcerr.h" +#include "pmu.h" + +using namespace pcerr; +using namespace std; +using EvtQueryer = function; + +static const string SLASH = "/"; +static const string COLON = ":"; +static const string UNCORE_PREFIX = "hisi"; +static const string SYS_DEVICES = "/sys/devices/"; +static const string EVENT_DIR = "/events/"; +static const string TRACE_FOLDER = "/sys/kernel/tracing/events/"; + +static std::mutex pmuEventListMtx; + +static vector uncoreEventList; +static vector traceEventList; + +static void GetEventName(const string& devName, vector& eventList) +{ + DIR* dir; + struct dirent* entry; + auto path = SYS_DEVICES + devName + EVENT_DIR; + if ((dir = opendir(path.c_str())) == nullptr) { + New(LIBPERF_ERR_FOLDER_PATH_INACCESSIBLE, "Could not open \"/sys/devices/\""); + return; + } + while ((entry = readdir(dir)) != nullptr) { + if (entry->d_type != DT_REG) { // Check if it is a regular file + continue; + } + string fileName(entry->d_name); + auto eventName = devName; + eventName += SLASH + fileName; + eventName += SLASH; + char* eventNameCopy = new char[eventName.length() + 1]; + strcpy(eventNameCopy, eventName.c_str()); + eventList.push_back(eventNameCopy); + } + closedir(dir); +} + +static void GetTraceSubFolder(const string& devName, vector& eventList) +{ + DIR* dir; + struct dirent* entry; + auto path = TRACE_FOLDER + devName; + if ((dir = opendir(path.c_str())) == nullptr) { + New(LIBPERF_ERR_FOLDER_PATH_INACCESSIBLE, "Could not open " + path); + return; + } + while ((entry = readdir(dir)) != nullptr) { + if (entry->d_type != DT_DIR) { // Check if it is a regular folder + continue; + } + string folderName(entry->d_name); + if (folderName.find('.') == string::npos) { + auto eventName = devName; + eventName += COLON + folderName; + char* eventNameCopy = new char[eventName.length() + 1]; + strcpy(eventNameCopy, eventName.c_str()); + eventList.push_back(eventNameCopy); + } + } + closedir(dir); +} + +const char** QueryCoreEvent(unsigned *numEvt) +{ + static vector eventList; + auto coreEventMap = KUNPENG_PMU::CORE_EVENT_MAP.at(GetCpuType()); + for (auto& pair : coreEventMap) { + auto eventName = pair.first; + char* eventNameCopy = new char[eventName.length() + 1]; + strcpy(eventNameCopy, eventName.c_str()); + eventList.push_back(eventNameCopy); + } + *numEvt = eventList.size(); + return eventList.data(); +} + +const char** QueryUncoreEvent(unsigned *numEvt) +{ + DIR* dir; + struct dirent* entry; + dir = opendir(SYS_DEVICES.c_str()); + while ((entry = readdir(dir)) != nullptr) { + if (entry->d_type == DT_DIR) { + string folderName = entry->d_name; + if (folderName.find(UNCORE_PREFIX) == 0) { + string devName(entry->d_name); + GetEventName(devName, uncoreEventList); + } + } + } + closedir(dir); + *numEvt = uncoreEventList.size(); + return uncoreEventList.data(); +} + +const char** QueryTraceEvent(unsigned *numEvt) +{ + DIR* dir; + struct dirent* entry; + dir = opendir(TRACE_FOLDER.c_str()); + while ((entry = readdir(dir)) != nullptr) { + if (entry->d_type == DT_DIR) { + string folderName = entry->d_name; + if (folderName.find('.') == string::npos) { + string devName(entry->d_name); + GetTraceSubFolder(devName, traceEventList); + } + } + } + closedir(dir); + *numEvt = traceEventList.size(); + return traceEventList.data(); +} + +const char** QueryAllEvent(unsigned *numEvt) +{ + unsigned coreNum; + unsigned uncoreNum; + unsigned traceNum; + auto coreList = QueryCoreEvent(&coreNum); + auto uncoreList = QueryUncoreEvent(&uncoreNum); + auto traceList = QueryTraceEvent(&traceNum); + *numEvt = coreNum + uncoreNum + traceNum; + const char** combinedList = new const char* [*numEvt]; + memcpy(combinedList, coreList, coreNum * sizeof(char*)); + memcpy(combinedList + coreNum, uncoreList, uncoreNum * sizeof(char*)); + memcpy(combinedList + coreNum + uncoreNum, traceList, traceNum * sizeof(char*)); + return combinedList; +} + +static const unordered_map QueryMap{ + {PmuEventType::CORE_EVENT, QueryCoreEvent}, + {PmuEventType::UNCORE_EVENT, QueryUncoreEvent}, + {PmuEventType::TRACE_EVENT, QueryTraceEvent}, + {PmuEventType::ALL_EVENT, QueryAllEvent}, +}; + +const char** PmuEventList(enum PmuEventType eventType, unsigned *numEvt) +{ + lock_guard lg(pmuEventListMtx); + const char** eventList; + if (QueryMap.find(eventType) == QueryMap.end()) { + New(LIBPERF_ERR_QUERY_EVENT_TYPE_INVALID, "Event type is invalid."); + return nullptr; + } + try { + eventList = QueryMap.at(eventType)(numEvt); + } catch (...) { + New(LIBPERF_ERR_QUERY_EVENT_LIST_FAILED, "Query event failed."); + return nullptr; + } + New(SUCCESS); + return eventList; +} + +void PmuEventListFree(const char** eventList, unsigned *numEvt) +{ + lock_guard lg(pmuEventListMtx); + for (unsigned i = 0; i < *numEvt; i++) { + delete[] eventList[i]; + } + uncoreEventList.clear(); + traceEventList.clear(); + New(SUCCESS); +} \ No newline at end of file diff --git a/pmu/pmu_list.cpp b/pmu/pmu_list.cpp index 4ac2fa9b6f7f8a30f394e80d74548b13a087b85d..95d9760c62f27120d4085207a9ae51a410220c70 100644 --- a/pmu/pmu_list.cpp +++ b/pmu/pmu_list.cpp @@ -381,7 +381,34 @@ namespace KUNPENG_PMU { } } - std::vector& PmuList::ExchangeToUserData(const unsigned pd) + void PmuList::AggregateUncoreData(const unsigned pd, const vector& evData, vector& newEvData) + { + // One count for same parent according to parentEventMap. + auto parentMap = parentEventMap.at(pd); + unordered_map dataMap; + for (auto& pmuData : evData) { + auto parentName = parentMap.at(pmuData.evt); + if (strcmp(parentName, pmuData.evt) == 0) { + // event was not split + newEvData.emplace_back(pmuData); + continue; + } + if (dataMap.find(parentName) == dataMap.end()) { + // split uncore event which not recorded in dataMap yet + dataMap[parentName] = pmuData; + dataMap[parentName].evt = parentMap.at(pmuData.evt); + dataMap[parentName].cpu = 0; + dataMap[parentName].cpuTopo = nullptr; + } else { + dataMap.at(parentMap.at(pmuData.evt)).count += pmuData.count; + } + } + for (const auto& pair : dataMap) { + newEvData.emplace_back(pair.second); + } + } + + vector& PmuList::ExchangeToUserData(const unsigned pd) { lock_guard lg(dataListMtx); if (dataList.count(pd) == 0) { @@ -391,7 +418,15 @@ namespace KUNPENG_PMU { auto& evData = dataList[pd]; auto pData = evData.data.data(); if (GetTaskType(pd) == COUNTING) { - auto inserted = userDataList.emplace(pData, move(evData)); + std::vector newPmuData; + AggregateUncoreData(pd, evData.data, newPmuData); + EventData newEvData = { + .pd = pd, + .collectType = COUNTING, + .data = newPmuData, + }; + + auto inserted = userDataList.emplace(newEvData.data.data(), move(newEvData)); dataList.erase(pd); return inserted.first->second.data; } else {