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 "cpp/queue.h"
17 #include "dm/dependence_manager.h"
18 #include "serial_handler.h"
19 #include "serial_task.h"
20
21 using namespace std;
22 using namespace ffrt;
23
24 namespace {
ResetTimeoutCb(ffrt::task_attr_private * p)25 inline void ResetTimeoutCb(ffrt::task_attr_private* p)
26 {
27 if (p->timeoutCb_ == nullptr) {
28 return;
29 }
30 GetSerialTaskByFuncStorageOffset(p->timeoutCb_)->DecDeleteRef();
31 p->timeoutCb_ = nullptr;
32 }
33
ffrt_queue_submit_base(ffrt_queue_t queue,ffrt_function_header_t * f,bool withHandle,uint64_t & delayUs)34 inline SerialTask* ffrt_queue_submit_base(ffrt_queue_t queue, ffrt_function_header_t* f, bool withHandle,
35 uint64_t& delayUs)
36 {
37 FFRT_COND_DO_ERR((queue == nullptr), return nullptr, "input invalid, queue == nullptr");
38 FFRT_COND_DO_ERR((f == nullptr), return nullptr, "input invalid, function header == nullptr");
39
40 SerialTask* task = GetSerialTaskByFuncStorageOffset(f);
41 new (task)ffrt::SerialTask();
42 SerialHandler* handler = static_cast<SerialHandler*>(queue);
43 task->SetQueHandler(handler);
44
45 if (withHandle) {
46 task->IncDeleteRef();
47 }
48 handler->SubmitDelayed(task, delayUs);
49 return task;
50 }
51 } // namespace
52
53 API_ATTRIBUTE((visibility("default")))
ffrt_queue_attr_init(ffrt_queue_attr_t * attr)54 int ffrt_queue_attr_init(ffrt_queue_attr_t* attr)
55 {
56 FFRT_COND_DO_ERR((attr == nullptr), return -1, "input invalid, attr == nullptr");
57 static_assert(sizeof(ffrt::task_attr_private) <= ffrt_task_attr_storage_size,
58 "size must be less than ffrt_queue_attr_storage_size");
59
60 new (attr) ffrt::task_attr_private();
61 return 0;
62 }
63
64 API_ATTRIBUTE((visibility("default")))
ffrt_queue_attr_destroy(ffrt_queue_attr_t * attr)65 void ffrt_queue_attr_destroy(ffrt_queue_attr_t* attr)
66 {
67 FFRT_COND_DO_ERR((attr == nullptr), return, "input invalid, attr == nullptr");
68 auto p = reinterpret_cast<ffrt::task_attr_private*>(attr);
69 ResetTimeoutCb(p);
70 p->~task_attr_private();
71 }
72
73 API_ATTRIBUTE((visibility("default")))
ffrt_queue_attr_set_qos(ffrt_queue_attr_t * attr,ffrt_qos_t qos)74 void ffrt_queue_attr_set_qos(ffrt_queue_attr_t* attr, ffrt_qos_t qos)
75 {
76 FFRT_COND_DO_ERR((attr == nullptr), return, "input invalid, attr == nullptr");
77 (reinterpret_cast<ffrt::task_attr_private*>(attr))->qos_map = qos;
78 }
79
80 API_ATTRIBUTE((visibility("default")))
ffrt_queue_attr_get_qos(const ffrt_queue_attr_t * attr)81 ffrt_qos_t ffrt_queue_attr_get_qos(const ffrt_queue_attr_t* attr)
82 {
83 FFRT_COND_DO_ERR((attr == nullptr), return ffrt_qos_default, "input invalid, attr == nullptr");
84 ffrt_queue_attr_t* p = const_cast<ffrt_queue_attr_t*>(attr);
85 return (reinterpret_cast<ffrt::task_attr_private*>(p))->qos_map.m_qos;
86 }
87
88 API_ATTRIBUTE((visibility("default")))
ffrt_queue_attr_set_timeout(ffrt_queue_attr_t * attr,uint64_t timeout_us)89 void ffrt_queue_attr_set_timeout(ffrt_queue_attr_t* attr, uint64_t timeout_us)
90 {
91 FFRT_COND_DO_ERR((attr == nullptr), return, "input invalid, attr == nullptr");
92 (reinterpret_cast<ffrt::task_attr_private*>(attr))->timeout_ = timeout_us;
93 }
94
95 API_ATTRIBUTE((visibility("default")))
ffrt_queue_attr_get_timeout(const ffrt_queue_attr_t * attr)96 uint64_t ffrt_queue_attr_get_timeout(const ffrt_queue_attr_t* attr)
97 {
98 FFRT_COND_DO_ERR((attr == nullptr), return 0, "input invalid, attr == nullptr");
99 ffrt_queue_attr_t* p = const_cast<ffrt_queue_attr_t*>(attr);
100 return (reinterpret_cast<ffrt::task_attr_private*>(p))->timeout_;
101 }
102
103 API_ATTRIBUTE((visibility("default")))
ffrt_queue_attr_set_callback(ffrt_queue_attr_t * attr,ffrt_function_header_t * f)104 void ffrt_queue_attr_set_callback(ffrt_queue_attr_t* attr, ffrt_function_header_t* f)
105 {
106 FFRT_COND_DO_ERR((attr == nullptr), return, "input invalid, attr == nullptr");
107 ffrt::task_attr_private* p = reinterpret_cast<ffrt::task_attr_private*>(attr);
108 ResetTimeoutCb(p);
109 p->timeoutCb_ = f;
110 // the memory of timeoutCb are managed in the form of SerialTask
111 SerialTask* task = GetSerialTaskByFuncStorageOffset(f);
112 new (task)ffrt::SerialTask();
113 }
114
115 API_ATTRIBUTE((visibility("default")))
ffrt_queue_attr_get_callback(const ffrt_queue_attr_t * attr)116 ffrt_function_header_t* ffrt_queue_attr_get_callback(const ffrt_queue_attr_t* attr)
117 {
118 FFRT_COND_DO_ERR((attr == nullptr), return nullptr, "input invalid, attr == nullptr");
119 ffrt_queue_attr_t* p = const_cast<ffrt_queue_attr_t*>(attr);
120 return (reinterpret_cast<ffrt::task_attr_private*>(p))->timeoutCb_;
121 }
122
123 API_ATTRIBUTE((visibility("default")))
ffrt_queue_create(ffrt_queue_type_t type,const char * name,const ffrt_queue_attr_t * attr)124 ffrt_queue_t ffrt_queue_create(ffrt_queue_type_t type, const char* name, const ffrt_queue_attr_t* attr)
125 {
126 FFRT_COND_DO_ERR((type != ffrt_queue_serial), return nullptr, "input invalid, type unsupport");
127 FFRT_COND_DO_ERR((attr == nullptr), return nullptr, "input invalid, attr == nullptr");
128
129 int qos = ffrt_queue_attr_get_qos(attr);
130 shared_ptr<SerialLooper> looper =
131 make_shared<SerialLooper>(name, qos, ffrt_queue_attr_get_timeout(attr), ffrt_queue_attr_get_callback(attr));
132 FFRT_COND_DO_ERR((looper == nullptr), return nullptr, "failed to construct SerialLooper");
133
134 SerialHandler* handler = new (std::nothrow) SerialHandler(looper);
135 FFRT_COND_DO_ERR((handler == nullptr), return nullptr, "failed to construct SerialHandler");
136 return static_cast<ffrt_queue_t>(handler);
137 }
138
139 API_ATTRIBUTE((visibility("default")))
ffrt_queue_destroy(ffrt_queue_t queue)140 void ffrt_queue_destroy(ffrt_queue_t queue)
141 {
142 FFRT_COND_DO_ERR((queue == nullptr), return, "input invalid, queue is nullptr");
143 SerialHandler* handler = static_cast<SerialHandler*>(queue);
144 delete handler;
145 }
146
147 API_ATTRIBUTE((visibility("default")))
ffrt_queue_submit(ffrt_queue_t queue,ffrt_function_header_t * f,const ffrt_task_attr_t * attr)148 void ffrt_queue_submit(ffrt_queue_t queue, ffrt_function_header_t* f, const ffrt_task_attr_t* attr)
149 {
150 uint64_t delayUs = (attr == nullptr) ? 0 : ffrt_task_attr_get_delay(attr);
151 SerialTask* task = ffrt_queue_submit_base(queue, f, false, delayUs);
152 FFRT_COND_DO_ERR((task == nullptr), return, "failed to submit serial task");
153 }
154
155 API_ATTRIBUTE((visibility("default")))
ffrt_queue_submit_h(ffrt_queue_t queue,ffrt_function_header_t * f,const ffrt_task_attr_t * attr)156 ffrt_task_handle_t ffrt_queue_submit_h(ffrt_queue_t queue, ffrt_function_header_t* f, const ffrt_task_attr_t* attr)
157 {
158 uint64_t delayUs = (attr == nullptr) ? 0 : ffrt_task_attr_get_delay(attr);
159 SerialTask* task = ffrt_queue_submit_base(queue, f, true, delayUs);
160 FFRT_COND_DO_ERR((task == nullptr), return nullptr, "failed to submit serial task");
161 return static_cast<ffrt_task_handle_t>(task);
162 }
163
164 API_ATTRIBUTE((visibility("default")))
ffrt_queue_wait(ffrt_task_handle_t handle)165 void ffrt_queue_wait(ffrt_task_handle_t handle)
166 {
167 FFRT_COND_DO_ERR((handle == nullptr), return, "input invalid, task_handle is nullptr");
168 SerialTask* task = static_cast<SerialTask*>(handle);
169 task->Wait();
170 }
171
172 API_ATTRIBUTE((visibility("default")))
ffrt_queue_cancel(ffrt_task_handle_t handle)173 int ffrt_queue_cancel(ffrt_task_handle_t handle)
174 {
175 FFRT_COND_DO_ERR((handle == nullptr), return -1, "input invalid, handle is nullptr");
176 SerialTask* task = static_cast<SerialTask*>(handle);
177 FFRT_COND_DO_ERR((task->handler_ == nullptr), return -1, "input invalid, task->handler_ is nullptr");
178 return task->handler_->Cancel(task);
179 }