1 /* 2 * Copyright (c) 2023-2024 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 PANDA_LIBPANDABASE_TASKMANAGER_TASK_H 17 #define PANDA_LIBPANDABASE_TASKMANAGER_TASK_H 18 19 #include "libpandabase/macros.h" 20 #include "libpandabase/utils/bit_utils.h" 21 #include "libpandabase/globals.h" 22 #include "libpandabase/utils/time.h" 23 #include "libpandabase/utils/logger.h" 24 #include <functional> 25 #include <ostream> 26 #include <array> 27 28 namespace ark::taskmanager { 29 30 /* 31 * TaskType - represents all types of components that can use TaskManager. 32 * UNKNOWN type - is a service type, it should be the last one in the list. 33 */ 34 enum class TaskType : uint8_t { GC, JIT, UNKNOWN }; 35 constexpr auto ALL_TASK_TYPES = std::array {TaskType::GC, TaskType::JIT}; 36 constexpr uint8_t TASK_TYPE_NEEDED_BITS = MinimumBitsToStore(static_cast<size_t>(TaskType::UNKNOWN) - 1U); 37 static_assert(ALL_TASK_TYPES.size() == static_cast<size_t>(TaskType::UNKNOWN)); 38 static_assert(std::is_same<decltype(ALL_TASK_TYPES)::value_type, TaskType>::value); 39 40 /* 41 * VMType - represents all types of VM that can use TaskManager. 42 * UNKNOWN type - is a service type, it should be the last one in the list. 43 */ 44 enum class VMType : uint8_t { DYNAMIC_VM, STATIC_VM, UNKNOWN }; 45 constexpr auto ALL_VM_TYPES = std::array {VMType::DYNAMIC_VM, VMType::STATIC_VM}; 46 constexpr uint8_t VM_TYPE_NEEDED_BITS = MinimumBitsToStore(static_cast<size_t>(VMType::UNKNOWN) - 1U); 47 static_assert(ALL_VM_TYPES.size() == static_cast<size_t>(VMType::UNKNOWN)); 48 static_assert(std::is_same<decltype(ALL_VM_TYPES)::value_type, VMType>::value); 49 50 /* 51 * TaskExecutionMode - represents all possible modes of tasks execution. 52 * UNKNOWN type - is a service type, it should be the last one in the list. 53 */ 54 enum class TaskExecutionMode : uint8_t { FOREGROUND, BACKGROUND, UNKNOWN }; 55 constexpr auto ALL_TASK_EXECUTION_MODES = std::array {TaskExecutionMode::FOREGROUND, TaskExecutionMode::BACKGROUND}; 56 constexpr uint8_t EXECUTION_MODE_NEEDED_BITS = MinimumBitsToStore(static_cast<size_t>(TaskExecutionMode::UNKNOWN) - 1U); 57 static_assert(ALL_TASK_EXECUTION_MODES.size() == static_cast<size_t>(TaskExecutionMode::UNKNOWN)); 58 static_assert(std::is_same<decltype(ALL_TASK_EXECUTION_MODES)::value_type, TaskExecutionMode>::value); 59 60 /** 61 * @brief TaskProperties is class that consider all enums that are related to Task. It's used to parameterize task 62 * creation. 63 */ 64 class TaskProperties { 65 // NOLINTBEGIN(hicpp-signed-bitwise) 66 /* 67 * TaskProperties representation: 68 * 69 * +-------+-------------------------------+-------+-------+-------+ 70 * | 0 | zeros | Task | VM |Exec | 71 * | | | Type | Type | Mode | 72 * +-------+-------------------------------+-------+-------+-------+ 73 * +-------+-------------------------------------------------------+ 74 * | 1 | zeros (invalid) | 75 * | | | 76 * +-------+-------------------------------------------------------+ 77 */ 78 using StorageType = uint8_t; 79 // Checking that we have enough bits for correct representation 80 static_assert((TASK_TYPE_NEEDED_BITS + VM_TYPE_NEEDED_BITS + EXECUTION_MODE_NEEDED_BITS) < 81 (sizeof(StorageType) * BITS_PER_BYTE)); 82 StorageType val_; 83 84 static constexpr StorageType TASK_TYPE_MASK = (1U << TASK_TYPE_NEEDED_BITS) - 1U; 85 static constexpr StorageType TASK_TYPE_SHIFT = VM_TYPE_NEEDED_BITS + EXECUTION_MODE_NEEDED_BITS; 86 87 static constexpr StorageType VM_TYPE_MASK = (1U << VM_TYPE_NEEDED_BITS) - 1U; 88 static constexpr StorageType VM_TYPE_SHIFT = EXECUTION_MODE_NEEDED_BITS; 89 90 static constexpr StorageType EXECUTION_MODE_MASK = (1U << EXECUTION_MODE_NEEDED_BITS) - 1U; 91 GetInternalRepresentation(StorageType taskType, StorageType vmType, StorageType executionMode)92 static inline constexpr StorageType GetInternalRepresentation(StorageType taskType, StorageType vmType, 93 StorageType executionMode) 94 { 95 return (taskType << TASK_TYPE_SHIFT) | (vmType << VM_TYPE_SHIFT) | executionMode; 96 } 97 98 static inline constexpr StorageType GetTaskTypeFromInternalRepresentation(StorageType val) noexcept 99 { 100 return (val >> TASK_TYPE_SHIFT) & TASK_TYPE_MASK; 101 } 102 103 static inline constexpr StorageType GetVMTypeFromInternalRepresentation(StorageType val) noexcept 104 { 105 return (val >> VM_TYPE_SHIFT) & VM_TYPE_MASK; 106 } 107 108 static inline constexpr StorageType GetExecutionModeFromInternalRepresentation(StorageType val) noexcept 109 { 110 return val & EXECUTION_MODE_MASK; 111 } 112 113 static constexpr StorageType INVALID_INTERNAL_REPRESENTATION = 1U << (sizeof(StorageType) * BITS_PER_BYTE - 1U); 114 115 public: TaskProperties()116 constexpr TaskProperties() : val_(INVALID_INTERNAL_REPRESENTATION) {} 117 TaskProperties(TaskType taskType, VMType vmType, TaskExecutionMode executionMode)118 constexpr TaskProperties(TaskType taskType, VMType vmType, TaskExecutionMode executionMode) 119 : val_(GetInternalRepresentation(static_cast<StorageType>(taskType), static_cast<StorageType>(vmType), 120 static_cast<StorageType>(executionMode))) 121 { 122 } 123 GetTaskType() const124 constexpr TaskType GetTaskType() const 125 { 126 return static_cast<TaskType>(GetTaskTypeFromInternalRepresentation(val_)); 127 } 128 GetVMType() const129 constexpr VMType GetVMType() const 130 { 131 return static_cast<VMType>(GetVMTypeFromInternalRepresentation(val_)); 132 } 133 GetTaskExecutionMode() const134 constexpr TaskExecutionMode GetTaskExecutionMode() const 135 { 136 return static_cast<TaskExecutionMode>(GetExecutionModeFromInternalRepresentation(val_)); 137 } 138 operator ==(const TaskProperties &lv, const TaskProperties &rv)139 friend constexpr bool operator==(const TaskProperties &lv, const TaskProperties &rv) 140 { 141 return lv.val_ == rv.val_; 142 } 143 144 class Hash { 145 public: MaxValue()146 static constexpr size_t MaxValue() 147 { 148 return GetInternalRepresentation(static_cast<StorageType>(TaskType::UNKNOWN) - 1U, 149 static_cast<StorageType>(VMType::UNKNOWN) - 1U, 150 static_cast<StorageType>(TaskExecutionMode::UNKNOWN) - 1U); 151 } 152 153 constexpr Hash() = default; operator ()(const TaskProperties &properties) const154 constexpr size_t operator()(const TaskProperties &properties) const 155 { 156 return properties.val_; 157 } 158 }; 159 // NOLINTEND(hicpp-signed-bitwise) 160 }; 161 162 constexpr auto INVALID_TASK_PROPERTIES = TaskProperties(); 163 164 PANDA_PUBLIC_API std::ostream &operator<<(std::ostream &os, TaskType type); 165 PANDA_PUBLIC_API std::ostream &operator<<(std::ostream &os, VMType type); 166 PANDA_PUBLIC_API std::ostream &operator<<(std::ostream &os, TaskExecutionMode mode); 167 PANDA_PUBLIC_API std::ostream &operator<<(std::ostream &os, TaskProperties prop); 168 169 /** 170 * @brief TaskLifeTimeAggregator structure used to save and log life time of task and execution time. 171 * It's methods doesn't works on release build. 172 */ 173 class TaskLifeTimeAggregator { 174 public: 175 NO_COPY_SEMANTIC(TaskLifeTimeAggregator); 176 DEFAULT_MOVE_SEMANTIC(TaskLifeTimeAggregator); 177 178 PANDA_PUBLIC_API TaskLifeTimeAggregator() = default; 179 180 /// @brief Saves time of task adding in queue. 181 PANDA_PUBLIC_API void GetAndStoreTimeOfTaskAddingToQueue(); 182 183 /// @brief Saves start time of execution. Use this method before task execution start 184 PANDA_PUBLIC_API void GetAndStoreTimeOfTaskExecutionStart(); 185 186 /// @brief Logs life time and execution time of task. Use this method after task execution end 187 PANDA_PUBLIC_API void GetTimeOfTaskExecutionFinishAndStoreTimeStats(TaskProperties prop); 188 189 PANDA_PUBLIC_API ~TaskLifeTimeAggregator() = default; 190 191 private: 192 // Time points for logs 193 uint64_t addingToQueueTime_ {0}; 194 uint64_t startExecutionTime_ {0}; 195 }; 196 197 class Task { 198 public: 199 PANDA_PUBLIC_API Task() = default; 200 NO_COPY_SEMANTIC(Task); 201 DEFAULT_MOVE_SEMANTIC(Task); 202 203 using RunnerCallback = std::function<void()>; 204 205 /** 206 * @brief Tasks are created through this method with the specified arguments. 207 * @param properties - properties of task, it contains TaskType, VMType and ExecutionMote. 208 * @param runner - body of task, that will be executed. 209 */ 210 [[nodiscard]] PANDA_PUBLIC_API static Task Create(TaskProperties properties, RunnerCallback runner); 211 212 /// @brief Returns properties of task 213 PANDA_PUBLIC_API TaskProperties GetTaskProperties() const; 214 215 /// @brief Executes body of task 216 PANDA_PUBLIC_API void RunTask(); 217 218 /** 219 * @brief Makes task invalid, it should not be executed anymore. 220 * @see INVALID_TASK_PROPERTIES 221 */ 222 PANDA_PUBLIC_API void MakeInvalid(); 223 224 /** 225 * @brief Checks if task is invalid 226 * @see INVALID_TASK_PROPERTIES 227 */ 228 PANDA_PUBLIC_API bool IsInvalid() const; 229 230 PANDA_PUBLIC_API void EventOnTaskAdding(); 231 232 PANDA_PUBLIC_API ~Task() = default; 233 234 private: Task(TaskProperties properties, RunnerCallback runner)235 Task(TaskProperties properties, RunnerCallback runner) : properties_(properties), runner_(std::move(runner)) {} 236 237 PANDA_PUBLIC_API void EventOnStartExecution(); 238 PANDA_PUBLIC_API void EventOnEndExecution(); 239 240 TaskProperties properties_ {INVALID_TASK_PROPERTIES}; 241 RunnerCallback runner_ {nullptr}; 242 TaskLifeTimeAggregator lifeTimeStorage_; 243 }; 244 245 } // namespace ark::taskmanager 246 247 #endif // PANDA_LIBPANDABASE_TASKMANAGER_TASK_H 248