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 #include "queue_task.h"
16 #include "ffrt_trace.h"
17 #include "dfx/log/ffrt_log_api.h"
18 #include "c/task.h"
19 #include "util/slab.h"
20 #include "tm/task_factory.h"
21
22 namespace {
23 constexpr uint64_t MIN_SCHED_TIMEOUT = 100000; // 0.1s
24 }
25 namespace ffrt {
QueueTask(QueueHandler * handler,const task_attr_private * attr,bool insertHead)26 QueueTask::QueueTask(QueueHandler* handler, const task_attr_private* attr, bool insertHead)
27 : handler_(handler), insertHead_(insertHead)
28 {
29 type = ffrt_queue_task;
30 if (handler) {
31 if (attr) {
32 label = handler->GetName() + "_" + attr->name_ + "_" + std::to_string(gid);
33 } else {
34 label = handler->GetName() + "_" + std::to_string(gid);
35 }
36 }
37
38 fq_we.task = reinterpret_cast<CPUEUTask*>(this);
39 uptime_ = static_cast<uint64_t>(std::chrono::duration_cast<std::chrono::microseconds>(
40 std::chrono::steady_clock::now().time_since_epoch()).count());
41
42 if (attr) {
43 delay_ = attr->delay_;
44 qos_ = attr->qos_;
45 uptime_ += delay_;
46 prio_ = attr->prio_;
47 stack_size = std::max(attr->stackSize_, MIN_STACK_SIZE);
48 if (delay_ && attr->timeout_) {
49 FFRT_LOGW("task [gid=%llu] not support delay and timeout at the same time, timeout ignored", gid);
50 } else if (attr->timeout_) {
51 schedTimeout_ = std::max(attr->timeout_, MIN_SCHED_TIMEOUT); // min 0.1s
52 }
53 }
54
55 FFRT_LOGD("ctor task [gid=%llu], delay=%lluus, type=%lu, prio=%d, timeout=%luus", gid, delay_, type, prio_,
56 schedTimeout_);
57 }
58
~QueueTask()59 QueueTask::~QueueTask()
60 {
61 FFRT_LOGD("dtor task [gid=%llu]", gid);
62 }
63
Destroy()64 void QueueTask::Destroy()
65 {
66 // release user func
67 auto f = reinterpret_cast<ffrt_function_header_t*>(func_storage);
68 f->destroy(f);
69 // free serial task object
70 DecDeleteRef();
71 }
72
Notify()73 void QueueTask::Notify()
74 {
75 std::unique_lock lock(mutex_);
76 isFinished_.store(true);
77 if (onWait_) {
78 waitCond_.notify_all();
79 }
80 }
81
Execute()82 void QueueTask::Execute()
83 {
84 IncDeleteRef();
85 FFRT_LOGD("Execute stask[%lu], name[%s]", gid, label.c_str());
86 if (isFinished_.load()) {
87 FFRT_LOGE("task [gid=%llu] is complete, no need to execute again", gid);
88 DecDeleteRef();
89 return;
90 }
91
92 handler_->Dispatch(this);
93 FFRT_TASKDONE_MARKER(gid);
94 DecDeleteRef();
95 }
96
Wait()97 void QueueTask::Wait()
98 {
99 std::unique_lock lock(mutex_);
100 onWait_ = true;
101 while (!isFinished_.load()) {
102 waitCond_.wait(lock);
103 }
104 }
105
FreeMem()106 void QueueTask::FreeMem()
107 {
108 TaskFactory<QueueTask>::Free(this);
109 }
110
GetQueueId() const111 uint32_t QueueTask::GetQueueId() const
112 {
113 return handler_->GetQueueId();
114 }
115 } // namespace ffrt
116