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