1 /* 2 * Copyright (c) 2021 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 #ifndef RELIABILITY_XCOLLIE_TIMERRING_H 17 #define RELIABILITY_XCOLLIE_TIMERRING_H 18 19 #include <time.h> 20 21 #include <condition_variable> 22 #include <functional> 23 #include <list> 24 #include <mutex> 25 #include <string> 26 #include <vector> 27 28 #include "thread_ex.h" 29 30 namespace OHOS { 31 namespace HiviewDFX { 32 struct TimerTask { 33 std::string name; 34 unsigned int timeout; 35 bool loop; 36 std::function<void (struct InputTimerPara*)> func; 37 struct InputTimerPara* inputTimerPara; 38 }; 39 40 struct InputTimerPara { 41 std::string name; 42 unsigned int timeout; 43 unsigned int flag; 44 int tid; 45 time_t startTime; 46 std::function<void (void*)> func; 47 void* arg; 48 }; 49 50 struct TaskNode { 51 int id; // -1 if not alloc 52 unsigned int seq; 53 int pos; // the position of timer ring 54 int round; // timer ring round 55 struct TimerTask timerTask; 56 }; 57 58 static const unsigned int MAX_XCOLLIE_SHIFT = 7; 59 static const unsigned int COOKIE_SHIFT = 8; 60 static const unsigned int MAX_XCOLLIE_NUM = (1 << MAX_XCOLLIE_SHIFT); 61 static const unsigned int TIMER_RING_CHECK_INTERVAL = 1; 62 static const unsigned int MAX_TIMERRING_SIZE = 60; 63 static const unsigned int MAX_DELAY_COUNT = 3; 64 static const unsigned int MILLI_SECONDS = 1000; 65 66 #define WRAP_SEQ(id) ((id) & ((1 << COOKIE_SHIFT) - 1)) 67 #define CALC_RING_POS(timeout) ((ringPos_ + (((timeout) - 1) / TIMER_RING_CHECK_INTERVAL + 1)) % MAX_TIMERRING_SIZE) 68 #define CALC_RING_ROUND(timeout) (((timeout) / TIMER_RING_CHECK_INTERVAL) / MAX_TIMERRING_SIZE) 69 70 static const std::string XCOLLIE_THREAD_NAME = "XCollieThread"; 71 class TimerRing : public Thread { 72 public: 73 TimerRing(); 74 ~TimerRing() override; 75 int AddTask(const struct TimerTask &task); 76 struct InputTimerPara* CancelTask(int id); 77 bool UpdateTask(int id, unsigned int timeout); 78 bool ReadyToWork() override; 79 bool Run() override; GetName()80 std::string GetName() const 81 { 82 return XCOLLIE_THREAD_NAME; 83 }; 84 void TryNotify(); 85 private: 86 void TryRecycle(std::list<struct TaskNode*> &timeoutNodes); 87 void InitTaskNode(struct TaskNode* taskNode, unsigned int seq); 88 void DoTimeoutTask(); 89 void TrySleep(); 90 91 std::vector<struct TaskNode> taskNodes_ = std::vector<struct TaskNode>(MAX_XCOLLIE_NUM); 92 std::list<struct TaskNode*> freeTaskNodes_ = std::list<struct TaskNode*>(); 93 std::vector<std::list<struct TaskNode*>> ringTaskNodes_ = 94 std::vector<std::list<struct TaskNode*>>(MAX_TIMERRING_SIZE); 95 96 mutable std::mutex lock_; 97 std::condition_variable condition_; 98 bool threadInSleep_; 99 time_t lastTimeout_; 100 uint64_t lastDuration_; 101 int ringPos_; 102 }; 103 } // end of namespace HiviewDFX 104 } // end of namespace OHOS 105 #endif 106