1484543d1Sopenharmony_ci/* 2484543d1Sopenharmony_ci * Copyright (c) 2023 Huawei Device Co., Ltd. 3484543d1Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4484543d1Sopenharmony_ci * you may not use this file except in compliance with the License. 5484543d1Sopenharmony_ci * You may obtain a copy of the License at 6484543d1Sopenharmony_ci * 7484543d1Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8484543d1Sopenharmony_ci * 9484543d1Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10484543d1Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11484543d1Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12484543d1Sopenharmony_ci * See the License for the specific language governing permissions and 13484543d1Sopenharmony_ci * limitations under the License. 14484543d1Sopenharmony_ci */ 15484543d1Sopenharmony_ci 16484543d1Sopenharmony_ci#ifndef __WAITQUEUE_H__ 17484543d1Sopenharmony_ci#define __WAITQUEUE_H__ 18484543d1Sopenharmony_ci#include "sync.h" 19484543d1Sopenharmony_ci#include "cpp/mutex.h" 20484543d1Sopenharmony_ci#include "sched/execute_ctx.h" 21484543d1Sopenharmony_ci#include "util/IntrusiveList.h" 22484543d1Sopenharmony_ci#include "sync/mutex_private.h" 23484543d1Sopenharmony_ci#include "dfx/log/ffrt_log_api.h" 24484543d1Sopenharmony_ci 25484543d1Sopenharmony_cinamespace ffrt { 26484543d1Sopenharmony_ciclass CPUEUTask; 27484543d1Sopenharmony_cistruct TaskWithNode; 28484543d1Sopenharmony_ciusing TaskListNode = ListNode; 29484543d1Sopenharmony_ciusing TaskList = List<TaskWithNode, TaskListNode>; 30484543d1Sopenharmony_ci 31484543d1Sopenharmony_cistruct TaskTimeOutStatus { 32484543d1Sopenharmony_ci explicit TaskTimeOutStatus(TaskTimeoutState state) : status(state) 33484543d1Sopenharmony_ci { 34484543d1Sopenharmony_ci } 35484543d1Sopenharmony_ci TaskTimeoutState status; 36484543d1Sopenharmony_ci std::mutex lock; 37484543d1Sopenharmony_ci}; 38484543d1Sopenharmony_ci 39484543d1Sopenharmony_cienum class TimeoutState { 40484543d1Sopenharmony_ci IDLE, 41484543d1Sopenharmony_ci WAITING, 42484543d1Sopenharmony_ci TIMEOUTING, 43484543d1Sopenharmony_ci DONE, 44484543d1Sopenharmony_ci}; 45484543d1Sopenharmony_ci 46484543d1Sopenharmony_cistruct TimeoutStatus { 47484543d1Sopenharmony_ci explicit TimeoutStatus(TimeoutState state) : status(state) 48484543d1Sopenharmony_ci { 49484543d1Sopenharmony_ci } 50484543d1Sopenharmony_ci TimeoutState status; 51484543d1Sopenharmony_ci mutex lock; 52484543d1Sopenharmony_ci}; 53484543d1Sopenharmony_ci 54484543d1Sopenharmony_cistruct TaskWithNode : public TaskListNode { 55484543d1Sopenharmony_ci TaskWithNode(); 56484543d1Sopenharmony_ci CPUEUTask* task = nullptr; 57484543d1Sopenharmony_ci std::mutex lk; 58484543d1Sopenharmony_ci std::condition_variable cv; 59484543d1Sopenharmony_ci}; 60484543d1Sopenharmony_ci 61484543d1Sopenharmony_ciclass WaitQueue { 62484543d1Sopenharmony_ciprivate: 63484543d1Sopenharmony_ci spin_mutex wqlock; 64484543d1Sopenharmony_ci WaitUntilEntry* whead; 65484543d1Sopenharmony_ci 66484543d1Sopenharmony_cipublic: 67484543d1Sopenharmony_ci using TimePoint = std::chrono::steady_clock::time_point; 68484543d1Sopenharmony_ci void SuspendAndWait(mutexPrivate* lk); 69484543d1Sopenharmony_ci bool SuspendAndWaitUntil(mutexPrivate* lk, const TimePoint& tp) noexcept; 70484543d1Sopenharmony_ci void NotifyAll() noexcept { Notify(false); } 71484543d1Sopenharmony_ci void NotifyOne() noexcept { Notify(true); } 72484543d1Sopenharmony_ci 73484543d1Sopenharmony_ci WaitQueue() 74484543d1Sopenharmony_ci { 75484543d1Sopenharmony_ci whead = new WaitUntilEntry(); 76484543d1Sopenharmony_ci whead->next = whead; 77484543d1Sopenharmony_ci whead->prev = whead; 78484543d1Sopenharmony_ci } 79484543d1Sopenharmony_ci WaitQueue(WaitQueue const&) = delete; 80484543d1Sopenharmony_ci void operator=(WaitQueue const&) = delete; 81484543d1Sopenharmony_ci 82484543d1Sopenharmony_ci ~WaitQueue() 83484543d1Sopenharmony_ci { 84484543d1Sopenharmony_ci wqlock.lock(); 85484543d1Sopenharmony_ci ReleaseAll(); 86484543d1Sopenharmony_ci delete whead; 87484543d1Sopenharmony_ci whead = nullptr; 88484543d1Sopenharmony_ci wqlock.unlock(); 89484543d1Sopenharmony_ci } 90484543d1Sopenharmony_ci 91484543d1Sopenharmony_ciprivate: 92484543d1Sopenharmony_ci bool WeNotifyProc(WaitUntilEntry* we); 93484543d1Sopenharmony_ci void ThreadWait(WaitUntilEntry* wn, mutexPrivate* lk, bool legacyMode, CPUEUTask* task); 94484543d1Sopenharmony_ci bool ThreadWaitUntil(WaitUntilEntry* wn, mutexPrivate* lk, const TimePoint& tp, bool legacyMode, CPUEUTask* task); 95484543d1Sopenharmony_ci void Notify(bool one) noexcept; 96484543d1Sopenharmony_ci 97484543d1Sopenharmony_ci inline bool empty() const 98484543d1Sopenharmony_ci { 99484543d1Sopenharmony_ci if (whead == nullptr) { 100484543d1Sopenharmony_ci return true; 101484543d1Sopenharmony_ci } 102484543d1Sopenharmony_ci return (whead->next == whead); 103484543d1Sopenharmony_ci } 104484543d1Sopenharmony_ci 105484543d1Sopenharmony_ci void ReleaseAll() 106484543d1Sopenharmony_ci { 107484543d1Sopenharmony_ci while (!empty()) { 108484543d1Sopenharmony_ci FFRT_LOGE("There are still tasks in cv that have not been awakened"); 109484543d1Sopenharmony_ci WaitUntilEntry *wue = pop_front(); 110484543d1Sopenharmony_ci (void)WeNotifyProc(wue); 111484543d1Sopenharmony_ci } 112484543d1Sopenharmony_ci } 113484543d1Sopenharmony_ci 114484543d1Sopenharmony_ci inline void push_back(WaitUntilEntry* we) 115484543d1Sopenharmony_ci { 116484543d1Sopenharmony_ci if ((we == nullptr) || (whead == nullptr) || (whead->prev == nullptr)) { 117484543d1Sopenharmony_ci FFRT_LOGE("we or whead or whead->prev is nullptr"); 118484543d1Sopenharmony_ci return; 119484543d1Sopenharmony_ci } 120484543d1Sopenharmony_ci we->next = whead; 121484543d1Sopenharmony_ci we->prev = whead->prev; 122484543d1Sopenharmony_ci whead->prev->next = we; 123484543d1Sopenharmony_ci whead->prev = we; 124484543d1Sopenharmony_ci } 125484543d1Sopenharmony_ci 126484543d1Sopenharmony_ci inline WaitUntilEntry* pop_front() 127484543d1Sopenharmony_ci { 128484543d1Sopenharmony_ci if ((whead->next == nullptr) || (whead->next->next == nullptr)) { 129484543d1Sopenharmony_ci FFRT_LOGE("whead->next or whead->next->next is nullptr"); 130484543d1Sopenharmony_ci return nullptr; 131484543d1Sopenharmony_ci } 132484543d1Sopenharmony_ci WaitEntry *we = whead->next; 133484543d1Sopenharmony_ci whead->next = we->next; 134484543d1Sopenharmony_ci we->next->prev = whead; 135484543d1Sopenharmony_ci we->next = nullptr; 136484543d1Sopenharmony_ci we->prev = nullptr; 137484543d1Sopenharmony_ci return static_cast<WaitUntilEntry*>(we); 138484543d1Sopenharmony_ci } 139484543d1Sopenharmony_ci 140484543d1Sopenharmony_ci inline void remove(WaitUntilEntry* we) 141484543d1Sopenharmony_ci { 142484543d1Sopenharmony_ci if ((we->next == nullptr) || (we->prev == nullptr)) { 143484543d1Sopenharmony_ci return; 144484543d1Sopenharmony_ci } 145484543d1Sopenharmony_ci we->prev->next = we->next; 146484543d1Sopenharmony_ci we->next->prev = we->prev; 147484543d1Sopenharmony_ci we->next = nullptr; 148484543d1Sopenharmony_ci we->prev = nullptr; 149484543d1Sopenharmony_ci return; 150484543d1Sopenharmony_ci } 151484543d1Sopenharmony_ci friend bool WeTimeoutProc(WaitQueue* wq, WaitUntilEntry* wue); 152484543d1Sopenharmony_ci}; 153484543d1Sopenharmony_ci} // namespace ffrt 154484543d1Sopenharmony_ci#endif // _WAITQUEUE_H_ 155