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 "c/queue_ext.h" 16#include "cpp/queue.h" 17#include "util/event_handler_adapter.h" 18#include "dm/dependence_manager.h" 19#include "tm/queue_task.h" 20#include "queue_handler.h" 21 22using namespace std; 23using namespace ffrt; 24 25namespace { 26inline void ResetTimeoutCb(ffrt::queue_attr_private* p) 27{ 28 if (p->timeoutCb_ == nullptr) { 29 return; 30 } 31 QueueTask* cbTask = GetQueueTaskByFuncStorageOffset(p->timeoutCb_); 32 cbTask->DecDeleteRef(); 33 p->timeoutCb_ = nullptr; 34} 35 36inline QueueTask* ffrt_queue_submit_base(ffrt_queue_t queue, ffrt_function_header_t* f, bool withHandle, 37 bool insertHead, const ffrt_task_attr_t* attr) 38{ 39 FFRT_COND_DO_ERR(unlikely(queue == nullptr), return nullptr, "input invalid, queue == nullptr"); 40 FFRT_COND_DO_ERR(unlikely(f == nullptr), return nullptr, "input invalid, function header == nullptr"); 41 QueueHandler* handler = static_cast<QueueHandler*>(queue); 42 ffrt::task_attr_private *p = reinterpret_cast<ffrt::task_attr_private *>(const_cast<ffrt_task_attr_t *>(attr)); 43 QueueTask* task = GetQueueTaskByFuncStorageOffset(f); 44 new (task)ffrt::QueueTask(handler, p, insertHead); 45 if (withHandle) { 46 task->IncDeleteRef(); 47 } 48 49 handler->Submit(task); 50 return task; 51} 52} // namespace 53 54API_ATTRIBUTE((visibility("default"))) 55int ffrt_queue_attr_init(ffrt_queue_attr_t* attr) 56{ 57 FFRT_COND_DO_ERR((attr == nullptr), return -1, "input invalid, attr == nullptr"); 58 static_assert(sizeof(ffrt::queue_attr_private) <= ffrt_queue_attr_storage_size, 59 "size must be less than ffrt_queue_attr_storage_size"); 60 61 new (attr) ffrt::queue_attr_private(); 62 return 0; 63} 64 65API_ATTRIBUTE((visibility("default"))) 66void ffrt_queue_attr_destroy(ffrt_queue_attr_t* attr) 67{ 68 FFRT_COND_DO_ERR((attr == nullptr), return, "input invalid, attr == nullptr"); 69 auto p = reinterpret_cast<ffrt::queue_attr_private*>(attr); 70 ResetTimeoutCb(p); 71 p->~queue_attr_private(); 72} 73 74API_ATTRIBUTE((visibility("default"))) 75void ffrt_queue_attr_set_qos(ffrt_queue_attr_t* attr, ffrt_qos_t qos) 76{ 77 FFRT_COND_DO_ERR((attr == nullptr), return, "input invalid, attr == nullptr"); 78 79 (reinterpret_cast<ffrt::queue_attr_private*>(attr))->qos_ = ffrt::GetFuncQosMap()(qos); 80} 81 82API_ATTRIBUTE((visibility("default"))) 83ffrt_qos_t ffrt_queue_attr_get_qos(const ffrt_queue_attr_t* attr) 84{ 85 FFRT_COND_DO_ERR((attr == nullptr), return ffrt_qos_default, "input invalid, attr == nullptr"); 86 ffrt_queue_attr_t* p = const_cast<ffrt_queue_attr_t*>(attr); 87 return (reinterpret_cast<ffrt::queue_attr_private*>(p))->qos_; 88} 89 90API_ATTRIBUTE((visibility("default"))) 91void ffrt_queue_attr_set_timeout(ffrt_queue_attr_t* attr, uint64_t timeout_us) 92{ 93 FFRT_COND_DO_ERR((attr == nullptr), return, "input invalid, attr == nullptr"); 94 (reinterpret_cast<ffrt::queue_attr_private*>(attr))->timeout_ = timeout_us; 95} 96 97API_ATTRIBUTE((visibility("default"))) 98uint64_t ffrt_queue_attr_get_timeout(const ffrt_queue_attr_t* attr) 99{ 100 FFRT_COND_DO_ERR((attr == nullptr), return 0, "input invalid, attr == nullptr"); 101 ffrt_queue_attr_t* p = const_cast<ffrt_queue_attr_t*>(attr); 102 return (reinterpret_cast<ffrt::queue_attr_private*>(p))->timeout_; 103} 104 105API_ATTRIBUTE((visibility("default"))) 106void ffrt_queue_attr_set_callback(ffrt_queue_attr_t* attr, ffrt_function_header_t* f) 107{ 108 FFRT_COND_DO_ERR((attr == nullptr), return, "input invalid, attr == nullptr"); 109 ffrt::queue_attr_private* p = reinterpret_cast<ffrt::queue_attr_private*>(attr); 110 ResetTimeoutCb(p); 111 p->timeoutCb_ = f; 112 // the memory of timeoutCb are managed in the form of QueueTask 113 QueueTask* task = GetQueueTaskByFuncStorageOffset(f); 114 new (task)ffrt::QueueTask(nullptr); 115} 116 117API_ATTRIBUTE((visibility("default"))) 118ffrt_function_header_t* ffrt_queue_attr_get_callback(const ffrt_queue_attr_t* attr) 119{ 120 FFRT_COND_DO_ERR((attr == nullptr), return nullptr, "input invalid, attr == nullptr"); 121 ffrt_queue_attr_t* p = const_cast<ffrt_queue_attr_t*>(attr); 122 return (reinterpret_cast<ffrt::queue_attr_private*>(p))->timeoutCb_; 123} 124 125API_ATTRIBUTE((visibility("default"))) 126void ffrt_queue_attr_set_max_concurrency(ffrt_queue_attr_t* attr, const int max_concurrency) 127{ 128 FFRT_COND_DO_ERR((attr == nullptr), return, "input invalid, attr == nullptr"); 129 130 FFRT_COND_DO_ERR((max_concurrency <= 0), return, 131 "max concurrency should be a valid value"); 132 133 (reinterpret_cast<ffrt::queue_attr_private*>(attr))->maxConcurrency_ = max_concurrency; 134} 135 136API_ATTRIBUTE((visibility("default"))) 137int ffrt_queue_attr_get_max_concurrency(const ffrt_queue_attr_t* attr) 138{ 139 FFRT_COND_DO_ERR((attr == nullptr), return 0, "input invalid, attr == nullptr"); 140 ffrt_queue_attr_t* p = const_cast<ffrt_queue_attr_t*>(attr); 141 return (reinterpret_cast<ffrt::queue_attr_private*>(p))->maxConcurrency_; 142} 143 144API_ATTRIBUTE((visibility("default"))) 145ffrt_queue_t ffrt_queue_create(ffrt_queue_type_t type, const char* name, const ffrt_queue_attr_t* attr) 146{ 147 bool invalidType = (type == ffrt_queue_max) || (type < ffrt_queue_serial) || 148 (type >= static_cast<ffrt_queue_type_t>(ffrt_queue_inner_max)); 149 FFRT_COND_DO_ERR(invalidType, return nullptr, "input invalid, type unsupport"); 150 QueueHandler* handler = new (std::nothrow) QueueHandler(name, attr, type); 151 FFRT_COND_DO_ERR((handler == nullptr), return nullptr, "failed to construct QueueHandler"); 152 return static_cast<ffrt_queue_t>(handler); 153} 154 155API_ATTRIBUTE((visibility("default"))) 156void ffrt_queue_destroy(ffrt_queue_t queue) 157{ 158 FFRT_COND_DO_ERR((queue == nullptr), return, "input invalid, queue is nullptr"); 159 QueueHandler* handler = static_cast<QueueHandler*>(queue); 160 delete handler; 161} 162 163API_ATTRIBUTE((visibility("default"))) 164void ffrt_queue_submit(ffrt_queue_t queue, ffrt_function_header_t* f, const ffrt_task_attr_t* attr) 165{ 166 FFRT_COND_DO_ERR((f == nullptr), return, "input invalid, function is nullptr"); 167 QueueTask* task = ffrt_queue_submit_base(queue, f, false, false, attr); 168 FFRT_COND_DO_ERR((task == nullptr), return, "failed to submit serial task"); 169} 170 171API_ATTRIBUTE((visibility("default"))) 172void ffrt_queue_submit_head(ffrt_queue_t queue, ffrt_function_header_t* f, const ffrt_task_attr_t* attr) 173{ 174 FFRT_COND_DO_ERR((f == nullptr), return, "input invalid, function is nullptr"); 175 QueueTask* task = ffrt_queue_submit_base(queue, f, false, true, attr); 176 FFRT_COND_DO_ERR((task == nullptr), return, "failed to submit serial task"); 177} 178 179API_ATTRIBUTE((visibility("default"))) 180ffrt_task_handle_t ffrt_queue_submit_h(ffrt_queue_t queue, ffrt_function_header_t* f, const ffrt_task_attr_t* attr) 181{ 182 FFRT_COND_DO_ERR((f == nullptr), return nullptr, "input invalid, function is nullptr"); 183 QueueTask* task = ffrt_queue_submit_base(queue, f, true, false, attr); 184 FFRT_COND_DO_ERR((task == nullptr), return nullptr, "failed to submit serial task"); 185 return static_cast<ffrt_task_handle_t>(task); 186} 187 188API_ATTRIBUTE((visibility("default"))) 189ffrt_task_handle_t ffrt_queue_submit_head_h(ffrt_queue_t queue, ffrt_function_header_t* f, const ffrt_task_attr_t* attr) 190{ 191 FFRT_COND_DO_ERR((f == nullptr), return nullptr, "input invalid, function is nullptr"); 192 QueueTask* task = ffrt_queue_submit_base(queue, f, true, true, attr); 193 FFRT_COND_DO_ERR((task == nullptr), return nullptr, "failed to submit serial task"); 194 return static_cast<ffrt_task_handle_t>(task); 195} 196 197API_ATTRIBUTE((visibility("default"))) 198void ffrt_queue_wait(ffrt_task_handle_t handle) 199{ 200 FFRT_COND_DO_ERR((handle == nullptr), return, "input invalid, task_handle is nullptr"); 201 QueueTask* task = static_cast<QueueTask*>(handle); 202 task->Wait(); 203} 204 205API_ATTRIBUTE((visibility("default"))) 206int ffrt_queue_cancel(ffrt_task_handle_t handle) 207{ 208 FFRT_COND_DO_ERR((handle == nullptr), return -1, "input invalid, handle is nullptr"); 209 QueueTask* task = reinterpret_cast<QueueTask*>(static_cast<CPUEUTask*>(handle)); 210 QueueHandler* handler = task->GetHandler(); 211 FFRT_COND_DO_ERR((handler == nullptr), return -1, "task handler is nullptr"); 212 int ret = handler->Cancel(task); 213 return ret; 214} 215 216API_ATTRIBUTE((visibility("default"))) 217void ffrt_queue_cancel_all(ffrt_queue_t queue) 218{ 219 FFRT_COND_DO_ERR(unlikely(queue == nullptr), return, "input invalid, queue is nullptr"); 220 QueueHandler* handler = static_cast<QueueHandler*>(queue); 221 handler->Cancel(); 222} 223 224API_ATTRIBUTE((visibility("default"))) 225void ffrt_queue_cancel_and_wait(ffrt_queue_t queue) 226{ 227 FFRT_COND_DO_ERR(unlikely(queue == nullptr), return, "input invalid, queue is nullptr"); 228 QueueHandler* handler = static_cast<QueueHandler*>(queue); 229 handler->CancelAndWait(); 230} 231 232API_ATTRIBUTE((visibility("default"))) 233int ffrt_queue_cancel_by_name(ffrt_queue_t queue, const char* name) 234{ 235 FFRT_COND_DO_ERR(unlikely(queue == nullptr), return -1, "input invalid, queue is nullptr"); 236 FFRT_COND_DO_ERR(unlikely(name == nullptr), return -1, "input invalid, name is nullptr"); 237 QueueHandler* handler = static_cast<QueueHandler*>(queue); 238 return handler->Cancel(name); 239} 240 241API_ATTRIBUTE((visibility("default"))) 242bool ffrt_queue_has_task(ffrt_queue_t queue, const char* name) 243{ 244 FFRT_COND_DO_ERR(unlikely(queue == nullptr), return false, "input invalid, queue is nullptr"); 245 FFRT_COND_DO_ERR(unlikely(name == nullptr), return false, "input invalid, name is nullptr"); 246 QueueHandler* handler = static_cast<QueueHandler*>(queue); 247 return handler->HasTask(name); 248} 249 250API_ATTRIBUTE((visibility("default"))) 251bool ffrt_queue_is_idle(ffrt_queue_t queue) 252{ 253 FFRT_COND_DO_ERR(unlikely(queue == nullptr), return false, "input invalid, queue is nullptr"); 254 QueueHandler* handler = static_cast<QueueHandler*>(queue); 255 return handler->IsIdle(); 256} 257 258API_ATTRIBUTE((visibility("default"))) 259void ffrt_queue_set_eventhandler(ffrt_queue_t queue, void* eventhandler) 260{ 261 FFRT_COND_DO_ERR(unlikely(queue == nullptr), return, "input invalid, queue is nullptr"); 262 QueueHandler* handler = static_cast<QueueHandler*>(queue); 263 handler->SetEventHandler(eventhandler); 264} 265 266API_ATTRIBUTE((visibility("default"))) 267void* ffrt_get_current_queue_eventhandler() 268{ 269 CPUEUTask* curTask = ffrt::ExecuteCtx::Cur()->task; 270 if (curTask == nullptr || curTask->type != ffrt_queue_task) { 271 FFRT_LOGW("Current task is nullptr or is not a serial task."); 272 return nullptr; 273 } 274 275 QueueHandler* handler = reinterpret_cast<QueueTask*>(curTask)->GetHandler(); 276 FFRT_COND_DO_ERR((handler == nullptr), return nullptr, "task handler is nullptr"); 277 return handler->GetEventHandler(); 278} 279 280API_ATTRIBUTE((visibility("default"))) 281ffrt_queue_t ffrt_get_main_queue() 282{ 283 FFRT_COND_DO_ERR((EventHandlerAdapter::Instance()->GetMainEventHandler == nullptr), 284 return nullptr, "failed to load GetMainEventHandler Func."); 285 void* mainHandler = EventHandlerAdapter::Instance()->GetMainEventHandler(); 286 FFRT_COND_DO_ERR((mainHandler == nullptr), return nullptr, "failed to get main queue."); 287 QueueHandler *handler = new (std::nothrow) QueueHandler( 288 "main_queue", nullptr, ffrt_queue_eventhandler_interactive); 289 FFRT_COND_DO_ERR((handler == nullptr), return nullptr, "failed to construct MainThreadQueueHandler"); 290 handler->SetEventHandler(mainHandler); 291 return static_cast<ffrt_queue_t>(handler); 292} 293 294API_ATTRIBUTE((visibility("default"))) 295ffrt_queue_t ffrt_get_current_queue() 296{ 297 FFRT_COND_DO_ERR((EventHandlerAdapter::Instance()->GetCurrentEventHandler == nullptr), 298 return nullptr, "failed to load GetCurrentEventHandler Func."); 299 void* workerHandler = EventHandlerAdapter::Instance()->GetCurrentEventHandler(); 300 FFRT_COND_DO_ERR((workerHandler == nullptr), return nullptr, "failed to get ArkTs worker queue."); 301 QueueHandler *handler = new (std::nothrow) QueueHandler( 302 "current_queue", nullptr, ffrt_queue_eventhandler_interactive); 303 FFRT_COND_DO_ERR((handler == nullptr), return nullptr, "failed to construct WorkerThreadQueueHandler"); 304 handler->SetEventHandler(workerHandler); 305 return static_cast<ffrt_queue_t>(handler); 306} 307 308API_ATTRIBUTE((visibility("default"))) 309int ffrt_queue_dump(ffrt_queue_t queue, const char* tag, char* buf, uint32_t len, bool history_info) 310{ 311 FFRT_COND_DO_ERR((queue == nullptr), return -1, "input invalid, queue is nullptr"); 312 FFRT_COND_DO_ERR((tag == nullptr || buf == nullptr), return -1, "input invalid, tag or buf is nullptr"); 313 QueueHandler* handler = static_cast<QueueHandler*>(queue); 314 return handler->Dump(tag, buf, len, history_info); 315} 316 317API_ATTRIBUTE((visibility("default"))) 318int ffrt_queue_size_dump(ffrt_queue_t queue, ffrt_inner_queue_priority_t priority) 319{ 320 FFRT_COND_DO_ERR((queue == nullptr), return -1, "input invalid, queue is nullptr"); 321 QueueHandler* handler = static_cast<QueueHandler*>(queue); 322 return handler->DumpSize(priority); 323}