148f512ceSopenharmony_ci/*
248f512ceSopenharmony_ci * Copyright (c) 2023 Huawei Device Co., Ltd.
348f512ceSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
448f512ceSopenharmony_ci * you may not use this file except in compliance with the License.
548f512ceSopenharmony_ci * You may obtain a copy of the License at
648f512ceSopenharmony_ci *
748f512ceSopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
848f512ceSopenharmony_ci *
948f512ceSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
1048f512ceSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
1148f512ceSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1248f512ceSopenharmony_ci * See the License for the specific language governing permissions and
1348f512ceSopenharmony_ci * limitations under the License.
1448f512ceSopenharmony_ci */
1548f512ceSopenharmony_ci#ifndef HIEPRF_UNIQUE_STACK_TABLE_H
1648f512ceSopenharmony_ci#define HIEPRF_UNIQUE_STACK_TABLE_H
1748f512ceSopenharmony_ci#include "utilities.h"
1848f512ceSopenharmony_ci#include <cinttypes>
1948f512ceSopenharmony_ci#include <linux/perf_event.h>
2048f512ceSopenharmony_ci#include <string>
2148f512ceSopenharmony_cinamespace OHOS {
2248f512ceSopenharmony_cinamespace Developtools {
2348f512ceSopenharmony_cinamespace HiPerf {
2448f512ceSopenharmony_ci
2548f512ceSopenharmony_ci#define ADDR_BIT_LENGTH        40
2648f512ceSopenharmony_ci#define IDX_BIT_LENGTH         23
2748f512ceSopenharmony_ci#define KERNEL_FLAG_BIT_LENGTH 1
2848f512ceSopenharmony_ci#define DECONFLICT_INCREASE_STEP  3
2948f512ceSopenharmony_ci#define RESIZE_MULTIPLE          2
3048f512ceSopenharmony_ci#define NR_BIT_LENGTH          41
3148f512ceSopenharmony_ci
3248f512ceSopenharmony_ciconstexpr uint32_t INITIAL_TABLE_SIZE = 4 * 1024 * 1024;
3348f512ceSopenharmony_ciconstexpr uint32_t MAX_NODES_CNT = 1 << IDX_BIT_LENGTH ;
3448f512ceSopenharmony_ciconstexpr uint64_t IP_IN_KERNEL = 1uLL << 63;
3548f512ceSopenharmony_ciconstexpr uint64_t HEAD_NODE_INDEX = 0;
3648f512ceSopenharmony_ci// FFFFFF0000000000
3748f512ceSopenharmony_ciconstexpr uint64_t KERNEL_PREFIX = 0xFFFFFFull << 40;
3848f512ceSopenharmony_ciconstexpr uint8_t INIT_DECONFLICT_ALLOWED = 22;
3948f512ceSopenharmony_ciconstexpr uint8_t HASH_STEP_BASE_MULTIPLE = 2;
4048f512ceSopenharmony_ciconstexpr uint8_t HASH_STEP_BASE_NUM = 1;
4148f512ceSopenharmony_ci
4248f512ceSopenharmony_ci// align
4348f512ceSopenharmony_ci#pragma pack(push, 4)
4448f512ceSopenharmony_ci
4548f512ceSopenharmony_ciunion Node {
4648f512ceSopenharmony_ci    uint64_t value;
4748f512ceSopenharmony_ci    struct {
4848f512ceSopenharmony_ci        uint64_t ip : ADDR_BIT_LENGTH;
4948f512ceSopenharmony_ci        uint64_t prevIdx : IDX_BIT_LENGTH;
5048f512ceSopenharmony_ci        uint64_t inKernel : KERNEL_FLAG_BIT_LENGTH;
5148f512ceSopenharmony_ci    } section;
5248f512ceSopenharmony_ci};
5348f512ceSopenharmony_ci
5448f512ceSopenharmony_cistruct UniStackNode {
5548f512ceSopenharmony_ci    uint32_t index;
5648f512ceSopenharmony_ci    Node node;
5748f512ceSopenharmony_ci};
5848f512ceSopenharmony_ci
5948f512ceSopenharmony_cistruct UniStackTableInfo {
6048f512ceSopenharmony_ci    uint32_t pid;
6148f512ceSopenharmony_ci    uint32_t tableSize;
6248f512ceSopenharmony_ci    uint32_t numNodes;
6348f512ceSopenharmony_ci    std::vector<UniStackNode> nodes;
6448f512ceSopenharmony_ci};
6548f512ceSopenharmony_ci
6648f512ceSopenharmony_ciunion StackId {
6748f512ceSopenharmony_ci    uint64_t value;
6848f512ceSopenharmony_ci    struct {
6948f512ceSopenharmony_ci        uint64_t id : IDX_BIT_LENGTH;
7048f512ceSopenharmony_ci        uint64_t nr : NR_BIT_LENGTH;
7148f512ceSopenharmony_ci    } section;
7248f512ceSopenharmony_ci};
7348f512ceSopenharmony_ci
7448f512ceSopenharmony_ci#pragma pack(pop)
7548f512ceSopenharmony_cistatic_assert(sizeof(Node) == 8, "Node size must be 8 byte");
7648f512ceSopenharmony_ci
7748f512ceSopenharmony_ciclass UniqueStackTable {
7848f512ceSopenharmony_cipublic:
7948f512ceSopenharmony_ci    bool Init();
8048f512ceSopenharmony_ci    explicit UniqueStackTable(pid_t pid) : pid_(pid)
8148f512ceSopenharmony_ci    {
8248f512ceSopenharmony_ci        Init();
8348f512ceSopenharmony_ci    }
8448f512ceSopenharmony_ci
8548f512ceSopenharmony_ci    UniqueStackTable(pid_t pid, uint32_t size) : pid_(pid), tableSize_(size)
8648f512ceSopenharmony_ci    {
8748f512ceSopenharmony_ci        Init();
8848f512ceSopenharmony_ci    }
8948f512ceSopenharmony_ci    ~UniqueStackTable()
9048f512ceSopenharmony_ci    {
9148f512ceSopenharmony_ci        tableBuf_ = nullptr;
9248f512ceSopenharmony_ci    }
9348f512ceSopenharmony_ci
9448f512ceSopenharmony_ci    uint64_t PutIpsInTable(StackId *stackId, u64 *ips, u64 nr);
9548f512ceSopenharmony_ci    bool GetIpsByStackId(const StackId stackId, std::vector<u64>& ips);
9648f512ceSopenharmony_ci    bool ImportNode(uint32_t index, const Node& node);
9748f512ceSopenharmony_ci    size_t GetWriteSize();
9848f512ceSopenharmony_ci
9948f512ceSopenharmony_ci    bool Resize();
10048f512ceSopenharmony_ci
10148f512ceSopenharmony_ci    uint32_t GetPid()
10248f512ceSopenharmony_ci    {
10348f512ceSopenharmony_ci        return pid_;
10448f512ceSopenharmony_ci    }
10548f512ceSopenharmony_ci
10648f512ceSopenharmony_ci    uint32_t GetTabelSize()
10748f512ceSopenharmony_ci    {
10848f512ceSopenharmony_ci        return tableSize_;
10948f512ceSopenharmony_ci    }
11048f512ceSopenharmony_ci
11148f512ceSopenharmony_ci    std::vector<uint32_t>& GetUsedIndexes()
11248f512ceSopenharmony_ci    {
11348f512ceSopenharmony_ci        return usedSlots_;
11448f512ceSopenharmony_ci    }
11548f512ceSopenharmony_ci
11648f512ceSopenharmony_ci    Node* GetHeadNode()
11748f512ceSopenharmony_ci    {
11848f512ceSopenharmony_ci        return reinterpret_cast<Node *>(tableBuf_.get());
11948f512ceSopenharmony_ci    }
12048f512ceSopenharmony_ci
12148f512ceSopenharmony_ciprivate:
12248f512ceSopenharmony_ci    Node* GetFrame(uint64_t stackId);
12348f512ceSopenharmony_ci    uint64_t PutIpInSlot(uint64_t thisIp, uint64_t prevIdx);
12448f512ceSopenharmony_ci    u32 pid_;
12548f512ceSopenharmony_ci    uint32_t tableSize_ = INITIAL_TABLE_SIZE;
12648f512ceSopenharmony_ci    std::unique_ptr<uint8_t[]> tableBuf_ = nullptr;
12748f512ceSopenharmony_ci    std::vector<uint32_t> usedSlots_;
12848f512ceSopenharmony_ci    uint32_t totalNodes_ = 0;
12948f512ceSopenharmony_ci    // current available node count, include index 0
13048f512ceSopenharmony_ci    uint32_t availableNodes_ = 0;
13148f512ceSopenharmony_ci    uint32_t hashModulus_ = 1;
13248f512ceSopenharmony_ci    // 0 for reserved, start from 1
13348f512ceSopenharmony_ci    uint32_t availableIndex_ = 1;
13448f512ceSopenharmony_ci    // for de-conflict
13548f512ceSopenharmony_ci    uint64_t hashStep_ = 0;
13648f512ceSopenharmony_ci    uint8_t deconflictTimes_ = INIT_DECONFLICT_ALLOWED;
13748f512ceSopenharmony_ci};
13848f512ceSopenharmony_ci
13948f512ceSopenharmony_ciusing ProcessStackMap = std::map<pid_t, std::shared_ptr<UniqueStackTable>>;
14048f512ceSopenharmony_ci} // namespace HiPerf
14148f512ceSopenharmony_ci} // namespace Developtools
14248f512ceSopenharmony_ci} // namespace OHOS
14348f512ceSopenharmony_ci#endif // HIEPRF_UNIQUE_STACK_TABLE_H