* Copyright (c) Huawei Technologies Co., Ltd. 2024. All rights reserved.
* libkperf licensed under the Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
* PURPOSE.
* See the Mulan PSL v2 for more details.
* Author: Mr.Zhang
* Create: 2024-04-03
* Description: definition of singleton class PmuList for managing performance monitoring tasks,
* collecting data, and handling performance counters in the KUNPENG_PMU namespace
******************************************************************************/
#ifndef PMU_LIST_H
#define PMU_LIST_H
#include <mutex>
#include <vector>
#include <unordered_map>
#include <unordered_set>
#include <sys/epoll.h>
#include "dummy_event.h"
#include "evt_list.h"
#include "pmu_event.h"
namespace KUNPENG_PMU {
class DummyEvent;
enum AnalysisStatus {
STOP_RESOLVE=0,
GOING_RESOLVE=1
};
struct PmuTaskAttr {
std::vector<int> cpuList;
std::vector<int> pidList;
std::shared_ptr<PmuEvt> pmuEvt;
int groupId;
struct PmuTaskAttr* next;
};
struct EvtInitCtx {
bool oneEvtInitOk = false;
int lastErr = SUCCESS;
std::unordered_map<int, struct EventGroupInfo> eventGroupInfoMap;
std::unordered_set<const EvtList*> removeEvt;
std::unordered_map<int, bool> groupLeaderOk;
std::unordered_map<int, bool> groupHasGroupedChild;
};
class PmuList {
public:
static PmuList* GetInstance()
{
static PmuList instance;
return &instance;
}
int Register(const int pd, PmuTaskAttr* taskParam);
* @brief Read all pmu data of event list, and store data to internal buffer.
* @param pd
*/
int ReadDataToBuffer(const int pd);
* @brief Read pmu data from internal buffer and return ref.
* @param pd
* @return std::vector<PmuData>&
*/
std::vector<PmuData>& Read(const int pd);
int AppendData(PmuData* fromData, PmuData** toData, int& len);
int Start(const int pd);
int Pause(const int pd);
void Close(const int pd);
bool AllPmuDead(const int pd);
bool IsPdAlive(const int pd) const;
void FreeData(PmuData* pmuData);
int GetTaskType(const int pd) const;
int GetBlockedSampleState(const int pd) const;
void SetSymbolMode(const int pd, const SymbolMode &mode);
void SetBranchSampleFilter(const int pd, const unsigned long& branchSampleFilter);
void SetAnalysisStatus(const int pd, const unsigned status);
int NewPd();
int GetHistoryData(const int pd, std::vector<PmuData>& pmuData);
void StoreSplitData(unsigned pd, std::pair<unsigned, char**>& previousEventList,
std::unordered_map<std::string, char*>& eventSplitMap);
bool IsAllPidExit(const unsigned pd);
void FillPidList(const unsigned pd, unsigned numPid, int* pidList);
int ResolvePmuDataSymbol(struct PmuData* iPmuData);
std::vector<PerfRecordSample> GetMetaData(PmuData* pmuData) const;
void AddNewProcess(const unsigned &pd, int pid);
PmuData* RegisterDriverHandle(EventData&& newData);
private:
using ProcPtr = std::shared_ptr<ProcTopology>;
using CpuPtr = std::shared_ptr<CpuTopology>;
PmuList()
{}
PmuList(const PmuList&) = delete;
PmuList& operator=(const PmuList&) = delete;
~PmuList() = default;
void InsertEvtList(const unsigned pd, std::shared_ptr<EvtList> evtList);
std::vector<std::shared_ptr<EvtList>>& GetEvtList(const unsigned pd);
void EraseEvtList(const unsigned pd);
void EraseParentEventMap(const unsigned pd);
void EraseSymModeList(const unsigned pd);
void ErasePpidList(const unsigned pd);
void EraseProcptrList(const unsigned pd);
std::pair<bool, std::shared_ptr<EvtList>> GetEvtGroupState(const int groupId, std::shared_ptr<EvtList> evtList, groupMapPtr eventGroupInfoMap);
int InitScanEvtLists(const int pd, std::vector<std::shared_ptr<EvtList>> &evtLists, EvtInitCtx &ctx);
int InitGroupChildren(const int pd, EvtInitCtx &ctx);
int EvtInit(const bool groupEnable, const std::shared_ptr<EvtList> evtLeader, const int pd, const std::shared_ptr<EvtList> &evtList);
int Init(const int pd);
void InsertDataEvtGroupList(const unsigned pd, groupMapPtr evtGroupList);
void EraseDataEvtGroupList(const unsigned pd);
groupMapPtr& GetDataEvtGroupList(const unsigned pd);
EventData& GetDataList(const unsigned pd);
void EraseDataList(const unsigned pd);
std::vector<PmuData>& ExchangeToUserData(const unsigned pd);
void FillStackInfo(EventData &eventData);
void EraseUserData(PmuData* pmuData);
int AddToEpollFd(const int pd, const std::shared_ptr<EvtList> &evtList);
void RemoveEpollFd(const int pd);
int GetEpollFd(const int pd);
std::vector<epoll_event>& GetEpollEvents(const int epollFd);
bool IsCpuInList(const int &cpu) const;
void AddSpeCpu(const unsigned &pd, const int &cpu);
void EraseSpeCpu(const unsigned &pd);
void ClearExitFd(const unsigned &pd);
void RemoveInitErrEvt(const unsigned &pd);
int PrepareCpuTopoList(
const unsigned& pd, PmuTaskAttr* pmuTaskAttrHead, std::vector<CpuPtr>& cpuTopoList);
int PrepareProcTopoList(PmuTaskAttr* pmuTaskAttrHead, std::vector<ProcPtr>& procTopoList, const int pd);
int CheckRlimit(const unsigned pd, const unsigned fdNum);
static unsigned CalRequireFd(unsigned cpuSize, unsigned proSize, const unsigned collectType);
static void AggregateData(const std::vector<PmuData>& evData, std::vector<PmuData>& newEvData);
void AggregateUncoreData(const unsigned pd, const std::vector<PmuData> &evData, std::vector<PmuData> &newEvData);
std::vector<PmuData>& GetPreviousData(const unsigned pd);
SymbolMode GetSymbolMode(const unsigned pd);
unsigned GetAnalysisStatus(const int pd);
unsigned long GetBranchSampleFilter(const unsigned pd);
void OpenDummyEvent(PmuTaskAttr* taskParam, const unsigned pd);
void EraseDummyEvent(const unsigned pd);
void EraseUnUseFd(const unsigned pd);
int InitSymbolRecordModule(const unsigned pd, PmuTaskAttr* taskParam);
static std::mutex pmuListMtx;
static std::mutex dataListMtx;
static std::mutex dataEvtGroupListMtx;
static std::mutex dataParentMtx;
static std::mutex analysisStatusMtx;
std::unordered_map<unsigned, std::vector<std::shared_ptr<EvtList>>> pmuList;
std::unordered_map<unsigned, EventData> dataList;
std::unordered_map<PmuData*, EventData> userDataList;
std::unordered_map<unsigned, std::unordered_map<std::string, char*>> parentEventMap;
std::unordered_map<unsigned, std::pair<unsigned, char**>> previousEventMap;
std::unordered_map<unsigned, int> epollList;
std::unordered_map<int, std::vector<epoll_event>> epollEvents;
std::unordered_map<unsigned, std::set<int>> speCpuList;
unsigned maxPd = 0;
std::unordered_map<unsigned, SymbolMode> symModeList;
std::unordered_map<unsigned, std::vector<pid_t>> ppidList;
std::unordered_map<unsigned, DummyEvent*> dummyList;
std::unordered_map<unsigned, groupMapPtr> dataEvtGroupList;
std::unordered_map<unsigned, unsigned long> branchSampleFilterList;
std::unordered_map<unsigned, volatile unsigned> analysisStatusList;
std::unordered_map<unsigned, std::vector<ProcPtr>> pmuProcList;
std::unordered_map<unsigned, unsigned> pmuNeedFdList;
};
}
#endif