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