1 /* 2 * Copyright (c) 2023 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 <list> 17 #include <vector> 18 #include <queue> 19 #include <thread> 20 #include <gtest/gtest.h> 21 #define private public 22 #define protected public 23 #include "ffrt_inner.h" 24 25 #include "core/entity.h" 26 #include "sched/task_scheduler.h" 27 #include "sched/scheduler.h" 28 #include "core/task_attr_private.h" 29 #include "tm/scpu_task.h" 30 #include "sched/stask_scheduler.h" 31 #include "../common.h" 32 33 using namespace std; 34 using namespace testing; 35 #ifdef HWTEST_TESTING_EXT_ENABLE 36 using namespace testing::ext; 37 #endif 38 using namespace ffrt; 39 40 class SchedulerTest : public testing::Test { 41 protected: SetUpTestCase()42 static void SetUpTestCase() 43 { 44 } 45 TearDownTestCase()46 static void TearDownTestCase() 47 { 48 } 49 SetUp()50 void SetUp() override 51 { 52 } 53 TearDown()54 void TearDown() override 55 { 56 } 57 }; 58 59 HWTEST_F(SchedulerTest, ffrt_task_runqueue_test, TestSize.Level0) 60 { 61 ffrt::FIFOQueue *fifoqueue = new ffrt::FIFOQueue(); 62 int aimnum = 10; 63 SCPUEUTask task(nullptr, nullptr, 0); 64 for (int i = 0; i < aimnum ; i++) { 65 fifoqueue->EnQueue(&task); 66 } 67 EXPECT_EQ(fifoqueue->Size(), aimnum); 68 EXPECT_EQ(fifoqueue->Empty(), false); 69 delete fifoqueue; 70 } 71 72 /* 73 * 测试用例名称:ffrt_sched_local_push_pop 74 * 测试用例描述:TaskSchduler, 开启本地队列后push和pop 75 * 预置条件 :无 76 * 操作步骤 :1、初始化STaskScheduler 77 2、push和pop任务 78 * 预期结果 :push和pop后的任务数量符合预期 79 */ 80 HWTEST_F(SchedulerTest, ffrt_sched_local_push_pop, TestSize.Level0) 81 { 82 STaskScheduler scheduler; 83 scheduler.SetTaskSchedMode(TaskSchedMode::LOCAL_TASK_SCHED_MODE); 84 85 int taskCount = 100; 86 87 EXPECT_EQ(scheduler.GetGlobalTaskCnt(), 0); 88 89 task_attr_private attr; 90 attr.notifyWorker_ = false; 91 for (int i = 0; i < taskCount; i++) { 92 TaskBase* task = new SCPUEUTask(&attr, nullptr, 0); 93 scheduler.PushTaskGlobal(task, false); 94 } 95 96 EXPECT_EQ(scheduler.GetTotalTaskCnt(), taskCount); 97 98 // 提交三个任务,保持worker不退出1秒 99 for (int i = 0; i < 3; i++) { __anon539643200102() 100 submit([]() { 101 sleep(1); 102 }); 103 } 104 105 // 赋值tick,保证能够从全局队列拿任务 106 unsigned int tick = 0; 107 *(scheduler.GetWorkerTick()) = &tick; 108 109 TaskBase* task = scheduler.PopTask(); 110 111 while (task != nullptr) { 112 delete task; 113 task = scheduler.PopTask(); 114 } 115 116 EXPECT_EQ(scheduler.GetLocalTaskCnt(), 0); 117 118 ffrt::wait(); 119 } 120 121 /* 122 * 测试用例名称 : ffrt_sched_local_steal 123 * 测试用例描述 : TaskSchduler, 开启本地队列后偷任务 124 * 预置条件 :无 125 * 操作步骤 : 1.初始化STaskScheduler 126 * 2.push任务到localQueue后保存到本地队列容器中 127 * 3.调用PopTask触发偷取任务 128 * 预期结果 : 偷取任务成功 129 */ 130 HWTEST_F(SchedulerTest, ffrt_sched_local_steal, TestSize.Level0) 131 { 132 STaskScheduler scheduler; 133 scheduler.SetTaskSchedMode(TaskSchedMode::LOCAL_TASK_SCHED_MODE); 134 135 int taskCount = 10; 136 137 SpmcQueue localQueue; 138 localQueue.Init(128); 139 140 for (int i = 0; i < taskCount; i++) { 141 TaskBase* task = new SCPUEUTask(nullptr, nullptr, 0); 142 localQueue.PushTail(task); 143 } 144 145 scheduler.localQueues.emplace(syscall(SYS_gettid) + 1, &localQueue); 146 147 EXPECT_GE(scheduler.GetTotalTaskCnt(), taskCount); 148 149 EXPECT_GE(scheduler.GetPriorityTaskCnt(), 0); 150 151 TaskBase* task = scheduler.PopTask(); 152 153 while (task != nullptr) { 154 delete task; 155 task = scheduler.PopTask(); 156 } 157 158 EXPECT_EQ(scheduler.GetLocalTaskCnt(), 0); 159 } 160 161 /* 162 * 测试用例名称:ffrt_sched_local_priority 163 * 测试用例描述:TaskSchduler, 开启本地队列后向优先槽推任务 164 * 预置条件 :无 165 * 操作步骤 :1、初始化STaskScheduler 166 2、push任务到localQueue后保存到本地队列容器中 167 3、调用PopTask触发偷取任务 168 * 预期结果 :偷取任务成功 169 */ 170 HWTEST_F(SchedulerTest, ffrt_sched_local_priority, TestSize.Level0) 171 { 172 STaskScheduler scheduler; 173 scheduler.SetTaskSchedMode(TaskSchedMode::LOCAL_TASK_SCHED_MODE); 174 175 int taskCount = 10; 176 177 for (int i = 0; i < taskCount; i++) { 178 TaskBase* task = new SCPUEUTask(nullptr, nullptr, 0); 179 scheduler.PushTaskToPriorityStack(task); 180 } 181 182 auto task = scheduler.PopTask(); 183 184 EXPECT_NE(task, nullptr); 185 186 while (task != nullptr) { 187 delete task; 188 task = scheduler.PopTask(); 189 } 190 191 EXPECT_LE(scheduler.GetLocalTaskCnt(), 0); 192 } 193 194 namespace { PushTest(void * task)195 void PushTest(void* task) { 196 if (task != nullptr) { 197 delete reinterpret_cast<TaskBase*>(task); 198 } 199 } 200 } 201 202 /* 203 * 测试用例名称:task_runqueue_pop_to_another_full_test 204 * 测试用例描述:SpmcQueue, 向另一个即将满任务的队列中push任务 205 * 预置条件 :无 206 * 操作步骤 :1、初始化两个队列,一个填10个,一个空间未初始化 207 2、调用PopHeadToAnotherQueue向另一个队列中push任务 208 * 预期结果 :Push任务失败,原队列任务数量符合预期 209 */ 210 HWTEST_F(SchedulerTest, task_runqueue_pop_to_another_fail_test, TestSize.Level0) 211 { 212 int taskCount = 10; 213 int localSize = 128; 214 SpmcQueue localQueue; 215 localQueue.Init(localSize); 216 217 SpmcQueue anotherQueue; 218 anotherQueue.tail_ = 0; 219 anotherQueue.head_ = 0; 220 anotherQueue.capacity_ = localSize; 221 222 for (int i = 0; i < taskCount; i++) { 223 TaskBase* task = new SCPUEUTask(nullptr, nullptr, 0); 224 localQueue.PushTail(task); 225 } 226 227 int pushCount = localQueue.PopHeadToAnotherQueue(anotherQueue, taskCount, PushTest); 228 229 EXPECT_EQ(localQueue.GetLength(), taskCount - 1); 230 EXPECT_EQ(anotherQueue.GetLength(), 0); 231 EXPECT_EQ(pushCount, 0); 232 233 auto task = anotherQueue.PopHead(); 234 while (task != nullptr) { 235 delete reinterpret_cast<TaskBase*>(task); 236 task = anotherQueue.PopHead(); 237 } 238 } 239 240 HWTEST_F(SchedulerTest, sched_test, TestSize.Level1) 241 { 242 STaskScheduler* scheduler = new STaskScheduler(); 243 scheduler->SetTaskSchedMode(TaskSchedMode::LOCAL_TASK_SCHED_MODE); 244 ffrt_executor_task_t work = {}; 245 bool ret = scheduler->CancelUVWork(&work); 246 #ifndef FFRT_GITEE 247 EXPECT_EQ(ret, true); 248 #endif 249 ffrt::TaskBase* task = new ffrt::SCPUEUTask(nullptr, nullptr, 0); 250 scheduler->PushTask(task); 251 scheduler->GetPriorityTaskCnt(); 252 scheduler->PushTaskLocalOrPriority(task); 253 delete scheduler; 254 } 255