1 /*
2 * Copyright (c) 2025 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 #include "libpandabase/taskmanager/task_queue_set.h"
17 #include "libpandabase/utils/logger.h"
18
19 namespace ark::taskmanager::internal {
20
TaskQueueSet(TaskWaitList * waitList,TaskTimeStatsType taskTimeStatsType)21 TaskQueueSet::TaskQueueSet(TaskWaitList *waitList, TaskTimeStatsType taskTimeStatsType) : waitList_(waitList)
22 {
23 switch (taskTimeStatsType) {
24 case TaskTimeStatsType::LIGHT_STATISTICS:
25 taskTimeStats_ = new LightTaskTimeTimeStats(MAX_WORKER_COUNT);
26 break;
27 case TaskTimeStatsType::NO_STATISTICS:
28 break;
29 default:
30 UNREACHABLE();
31 }
32 for (size_t i = 0; i < MAX_COUNT_OF_QUEUE; i++) {
33 // Atomic with relaxed order reason: no order dependency with another variables
34 queues_[i].store(nullptr, std::memory_order_relaxed);
35 }
36 }
37
~TaskQueueSet()38 TaskQueueSet::~TaskQueueSet()
39 {
40 for (size_t i = 0; i < MAX_COUNT_OF_QUEUE; i++) {
41 // Atomic with relaxed order reason: no order dependency with another variables
42 ASSERT_PRINT(queues_[i].load(std::memory_order_relaxed) == nullptr, "Queue was not deleted" << i);
43 }
44 if (taskTimeStats_ != nullptr) {
45 auto stats = taskTimeStats_->GetTaskStatistics();
46 for (const auto &s : stats) {
47 LOG(INFO, TASK_MANAGER) << s;
48 }
49 }
50 while (!deleterQueue_.empty()) {
51 auto deleter = deleterQueue_.front();
52 deleter();
53 deleterQueue_.pop();
54 }
55 delete taskTimeStats_;
56 }
57
GetQueue(QueueId id)58 TaskQueueInterface *TaskQueueSet::GetQueue(QueueId id)
59 {
60 TASK_MANAGER_CHECK_ID_VALUE(id);
61 // Atomic with relaxed order reason: no order dependency with another variables
62 return queues_[id].load(std::memory_order_relaxed);
63 }
64
SelectQueue()65 TaskQueueInterface *TaskQueueSet::SelectQueue()
66 {
67 // Collect all non-deleted queues
68 std::array<TaskQueueInterface *, MAX_COUNT_OF_QUEUE> queues {};
69 size_t countOfQueues = 0;
70 size_t prioritySum = 0;
71 for (size_t i = 0; i < MAX_COUNT_OF_QUEUE; i++) {
72 // Atomic with relaxed order reason: no order dependency with another variables
73 auto *queue = queues_[i].load(std::memory_order_relaxed);
74 if (queue == nullptr || queue->IsEmpty()) {
75 continue;
76 }
77 queues[countOfQueues] = queue;
78 prioritySum += queue->GetPriority();
79 countOfQueues++;
80 }
81 if (prioritySum == 0) {
82 return nullptr;
83 }
84 // Select queue here
85 // Atomic with relaxed order reason: no order dependency with another variables
86 auto selectionIndex = selectionIndex_.fetch_add(1U, std::memory_order_relaxed) % prioritySum;
87 for (size_t i = 0; i < countOfQueues; i++) {
88 auto *queue = queues[i];
89 auto priority = queue->GetPriority();
90 if (selectionIndex < priority) {
91 return queue;
92 }
93 selectionIndex -= priority;
94 }
95
96 return nullptr;
97 }
98
AreQueuesEmpty() const99 bool TaskQueueSet::AreQueuesEmpty() const
100 {
101 for (size_t i = 0; i < MAX_COUNT_OF_QUEUE; i++) {
102 // Atomic with relaxed order reason: no order dependency with another variables
103 auto *queue = queues_[i].load(std::memory_order_relaxed);
104 if (queue == nullptr) {
105 continue;
106 }
107 if (!queue->IsEmpty()) {
108 return false;
109 }
110 }
111 return true;
112 }
113
GetCountOfLiveTasks() const114 size_t TaskQueueSet::GetCountOfLiveTasks() const
115 {
116 size_t count = 0;
117 for (size_t i = 0; i < MAX_COUNT_OF_QUEUE; i++) {
118 // Atomic with relaxed order reason: no order dependency with another variables
119 auto *queue = queues_[i].load(std::memory_order_relaxed);
120 if (queue == nullptr) {
121 continue;
122 }
123 auto *iQueue = static_cast<SchedulableTaskQueueInterface *>(queue);
124 count += iQueue->GetCountOfLiveTasks();
125 }
126 return count;
127 }
128
GetTaskTimeStats() const129 TaskTimeStatsBase *TaskQueueSet::GetTaskTimeStats() const
130 {
131 return taskTimeStats_;
132 }
133
134 } // namespace ark::taskmanager::internal
135