diff --git a/include/pcerrc.h b/include/pcerrc.h index bcdf187283d4f0d3b37f58619c9ae842d73aa045..abaf10f090171e3b80b4835273ecbfe35975de12 100644 --- a/include/pcerrc.h +++ b/include/pcerrc.h @@ -70,6 +70,9 @@ extern "C" { #define LIBPERF_ERR_FAILED_PMU_DISABLE 1026 #define LIBPERF_ERR_FAILED_PMU_RESET 1027 #define LIBPERF_ERR_NOT_OPENED 1028 +#define LIBPERF_ERR_QUERY_EVENT_TYPE_INVALID 1029 +#define LIBPERF_ERR_QUERY_EVENT_LIST_FAILED 1030 +#define LIBPERF_ERR_FOLDER_PATH_INACCESSIBLE 1031 #define UNKNOWN_ERROR 9999 diff --git a/include/pmu.h b/include/pmu.h index 99b158029fb9b961b8614c6596afe448c25e4953..1f97d365b0a88e8c0676dcf4b18a6ff83eaf7512 100644 --- a/include/pmu.h +++ b/include/pmu.h @@ -28,6 +28,13 @@ enum PmuTaskType { MAX_TASK_TYPE }; +enum PmuEventType { + CORE_EVENT, + UNCORE_EVENT, + TRACE_EVENT, + ALL_EVENT +}; + enum AggregateType { PER_SYSTEM, PER_CORE, @@ -121,6 +128,23 @@ struct PmuData { */ int PmuOpen(enum PmuTaskType collectType, struct PmuAttr *attr); +/** + * @brief + * Query all available event from system. + * @param eventType type of event chosen by user + * @param numEvt length of event list + * @return event list + */ +const char** PmuEventList(enum PmuEventType eventType, unsigned *numEvt); + +/** + * @brief + * Free eventList pointer. + * @param eventList event list + * @param numEvt length of event list + */ +void PmuEventListFree(const char** eventList, unsigned *numEvt); + /** * @brief * Enable counting or sampling of task . diff --git a/pmu/pfm/pfm.cpp b/pmu/pfm/pfm.cpp index 1f8ea3f820c8b82fde00658b98603627537ff352..4b46838a289888d2e0994686df036a43c1088a7e 100644 --- a/pmu/pfm/pfm.cpp +++ b/pmu/pfm/pfm.cpp @@ -40,6 +40,25 @@ using namespace KUNPENG_PMU; static constexpr int MAX_STRING_LEN = 2048; static CHIP_TYPE g_chipType = UNDEFINED_TYPE; +static struct PmuEvt* GetRawEvent(const char* pmuName, int collectType) +{ + // check raw event name like 'r11' or 'r60ea' is valid or not + const char *numStr = pmuName + 1; + char *endPtr; + __u64 config = strtol(numStr, &endPtr, 16); + if (*endPtr != '\0') { + return nullptr; + } + struct PmuEvt* pmuEvtPtr = new PmuEvt; + pmuEvtPtr->config = config; + pmuEvtPtr->name = pmuName; + pmuEvtPtr->type = PERF_TYPE_RAW; + pmuEvtPtr->pmuType = CORE_TYPE; + pmuEvtPtr->collectType = collectType; + pmuEvtPtr->cpumask = -1; + return std::move(pmuEvtPtr); +} + static struct PmuEvt* ConstructPmuEvtFromCore(KUNPENG_PMU::CoreConfig config, int collectType) { struct PmuEvt* pmuEvtPtr = new PmuEvt; @@ -87,6 +106,7 @@ static int GetSpeType(void) using EvtRetriever = std::function; static const std::unordered_map EvtMap{ + {KUNPENG_PMU::RAW_TYPE, GetRawEvent}, {KUNPENG_PMU::CORE_TYPE, GetCoreEvent}, {KUNPENG_PMU::UNCORE_TYPE, GetUncoreEvent}, {KUNPENG_PMU::TRACE_TYPE, GetKernelTraceEvent}, @@ -94,6 +114,10 @@ static const std::unordered_map EvtMap{ static int GetEventType(const char *pmuName, string &evtName) { + if (pmuName[0] == 'r') { + evtName = pmuName; + return RAW_TYPE; + } auto coreMap = CORE_EVENT_MAP.at(g_chipType); auto findCoreEvent = coreMap.find(pmuName); if (findCoreEvent != coreMap.end()) { @@ -148,7 +172,7 @@ struct PmuEvt* PfmGetPmuEvent(const char* pmuName, int collectType) struct PmuEvt* PfmGetSpeEvent( unsigned long dataFilter, unsigned long eventFilter, unsigned long minLatency, int collectType) { - PmuEvt* evt = new PmuEvt{0}; + auto* evt = new PmuEvt{0}; evt->collectType = collectType; int type = GetSpeType(); if (type == -1) { @@ -165,7 +189,5 @@ struct PmuEvt* PfmGetSpeEvent( void PmuEvtFree(PmuEvt *evt) { - if (evt != nullptr) { - delete evt; - } + delete evt; } diff --git a/pmu/pfm/pfm_event.h b/pmu/pfm/pfm_event.h index b416baf395abc0c771a7678314683abf2a2ef2a3..aaca4a646e1085fef3ad35014947efaba3650a3c 100644 --- a/pmu/pfm/pfm_event.h +++ b/pmu/pfm/pfm_event.h @@ -22,6 +22,7 @@ namespace KUNPENG_PMU { enum PMU_TYPE { + RAW_TYPE, CORE_TYPE, UNCORE_TYPE, TRACE_TYPE, diff --git a/pmu/pfm/uncore.cpp b/pmu/pfm/uncore.cpp index 16257f32292a0233abe6e36989e015b9d3794e31..382802d8a0feece548f1aa989f3abb81eed61a69 100644 --- a/pmu/pfm/uncore.cpp +++ b/pmu/pfm/uncore.cpp @@ -76,7 +76,7 @@ static int64_t GetUncoreEventConfig(const char* pmuName) } string configStr; evtIn >> configStr; - auto findEq = configStr.find("="); + auto findEq = configStr.find('='); if (findEq == string::npos) { return -1; } diff --git a/pmu/pmu.cpp b/pmu/pmu.cpp index a88470f52f4b235ac55f88492dc247fd2093f63d..2f05b57d54b198f5d586000c24e52644f5a3f54a 100644 --- a/pmu/pmu.cpp +++ b/pmu/pmu.cpp @@ -16,6 +16,8 @@ #include #include #include +#include +#include "common.h" #include "pfm.h" #include "pfm_event.h" #include "pmu_event.h" @@ -33,6 +35,7 @@ using namespace std; static unordered_map runningStatus; static SafeHandler pdMutex; +static const int NINE = 9; struct PmuTaskAttr* AssignPmuTaskParam(PmuTaskType collectType, struct PmuAttr *attr); @@ -118,6 +121,54 @@ static int CheckAttr(enum PmuTaskType collectType, struct PmuAttr *attr) return SUCCESS; } +void AppendChildEvents(char* evt, unordered_map& eventSplitMap) +{ + string strName(evt); + 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); + } + } +} + +static void SplitUncoreEvent(struct PmuAttr *attr, unordered_map &eventSplitMap) +{ + char** evtList = attr->evtList; + unsigned size = attr->numEvt; + int newSize = 0; + for (int i = 0; i < size; ++i) { + char* evt = evtList[i]; + char* slashPos = std::strchr(evt, '/'); + if (slashPos != nullptr && slashPos != evt) { + char* prevChar = slashPos - 1; + if (!std::isdigit(*prevChar)) { + // 添加子事件 + AppendChildEvents(evt, eventSplitMap); + continue; + } + } + eventSplitMap.emplace(evt, evt); + newSize++; + } +} + +static unsigned GenerateSplitList(unordered_map& eventSplitMap, vector &newEvtlist) +{ + // append child event + for (auto& event : eventSplitMap) { + newEvtlist.push_back(const_cast(event.first.c_str())); + } + return newEvtlist.size(); +} + static bool PdValid(const int &pd) { return PmuList::GetInstance()->IsPdAlive(pd); @@ -143,6 +194,12 @@ int PmuOpen(enum PmuTaskType collectType, struct PmuAttr *attr) if (err != SUCCESS) { return -1; } + unordered_map eventSplitMap; + SplitUncoreEvent(attr, eventSplitMap); + auto previousEventList = make_pair(attr->numEvt, attr->evtList); + vector newEvtlist; + attr->numEvt = GenerateSplitList(eventSplitMap, newEvtlist); + attr->evtList = newEvtlist.data(); auto pTaskAttr = AssignPmuTaskParam(collectType, attr); if (pTaskAttr == nullptr) { @@ -161,6 +218,9 @@ int PmuOpen(enum PmuTaskType collectType, struct PmuAttr *attr) PmuList::GetInstance()->Close(pd); pd = -1; } + // store eventList provided by user and the mapping relationship between the user eventList and the split + // eventList into buff + KUNPENG_PMU::PmuList::GetInstance()->StoreSplitData(pd, previousEventList, eventSplitMap); New(err); return pd; } catch (std::bad_alloc&) { diff --git a/pmu/pmu_list.cpp b/pmu/pmu_list.cpp index 42a4382f0447659ea79326663e15b8c347145cb0..4ac2fa9b6f7f8a30f394e80d74548b13a087b85d 100644 --- a/pmu/pmu_list.cpp +++ b/pmu/pmu_list.cpp @@ -32,6 +32,7 @@ namespace KUNPENG_PMU { // Initializing pmu list singleton instance and global lock std::mutex PmuList::pmuListMtx; std::mutex PmuList::dataListMtx; + std::mutex PmuList::dataParentMtx; int PmuList::CheckRlimit(const unsigned fdNum) { @@ -210,6 +211,14 @@ namespace KUNPENG_PMU { return SUCCESS; } + void PmuList::StoreSplitData(const unsigned pd, pair previousEventList, + unordered_map eventSplitMap) + { + lock_guard lg(dataParentMtx); + parentEventMap.emplace(pd, move(eventSplitMap)); + previousEventMap.emplace(pd, move(previousEventList)); + } + void PmuList::Close(const int pd) { auto evtList = GetEvtList(pd); @@ -220,6 +229,7 @@ namespace KUNPENG_PMU { EraseDataList(pd); RemoveEpollFd(pd); EraseSpeCpu(pd); + EraseParentEventMap(); SymResolverDestroy(); } @@ -305,6 +315,17 @@ namespace KUNPENG_PMU { pmuList.erase(pd); } + void PmuList::EraseParentEventMap() + { + lock_guard lg(dataParentMtx); + for (auto& pair : parentEventMap) { + auto& innerMap = pair.second; + innerMap.clear(); + } + parentEventMap.clear(); + previousEventMap.clear(); + } + PmuList::EventData& PmuList::GetDataList(const unsigned pd) { lock_guard lg(dataListMtx); @@ -370,15 +391,7 @@ namespace KUNPENG_PMU { auto& evData = dataList[pd]; auto pData = evData.data.data(); if (GetTaskType(pd) == COUNTING) { - std::vector newPmuData; - AggregateData(evData.data, newPmuData); - EventData newEvData = { - .pd = pd, - .collectType = COUNTING, - .data = newPmuData, - }; - - auto inserted = userDataList.emplace(newEvData.data.data(), move(newEvData)); + auto inserted = userDataList.emplace(pData, move(evData)); dataList.erase(pd); return inserted.first->second.data; } else { diff --git a/pmu/pmu_list.h b/pmu/pmu_list.h index 67b8bd23231101b973d84f779bd13e10b75c8436..90f588b6c8129c65199991030c6439aa9df2f1eb 100644 --- a/pmu/pmu_list.h +++ b/pmu/pmu_list.h @@ -66,6 +66,8 @@ public: int NewPd(); int GetHistoryData(const int pd, std::vector& pmuData); + void StoreSplitData(unsigned pd, std::pair previousEventList, + std::unordered_map eventSplitMap); private: using ProcPtr = std::shared_ptr; @@ -86,6 +88,7 @@ private: void InsertEvtList(const unsigned pd, std::shared_ptr evtList); std::vector>& GetEvtList(const unsigned pd); void EraseEvtList(const unsigned pd); + void EraseParentEventMap(); EventData& GetDataList(const unsigned pd); void EraseDataList(const unsigned pd); @@ -108,10 +111,12 @@ private: int PrepareProcTopoList(PmuTaskAttr* pmuTaskAttrHead, std::vector& procTopoList) const; int CheckRlimit(const unsigned fdNum); static void AggregateData(const std::vector& evData, std::vector& newEvData); + void AggregateUncoreData(const unsigned pd, const std::vector &evData, std::vector &newEvData); std::vector& GetPreviousData(const unsigned pd); static std::mutex pmuListMtx; static std::mutex dataListMtx; + static std::mutex dataParentMtx; std::unordered_map>> pmuList; // Key: pd // Value: PmuData List. @@ -121,7 +126,15 @@ private: // Value: PmuData vector for raw pointer. // PmuData is stored here after user call . std::unordered_map userDataList; - + // Key1: pd + // Key2: parent event + // Value: child event name list + // parent event name is stored here before user call to aggregate event. + std::unordered_map> parentEventMap; + // Key: pd + // Value: previous event list and its length + // previous event list is stored here before user call to aggregate event. + std::unordered_map> previousEventMap; // Key: pd // Value: epoll fd std::unordered_map epollList;