• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2022-2025 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 #ifndef PANDA_RUNTIME_COROUTINES_THREADED_COROUTINE_MANAGER_H
16 #define PANDA_RUNTIME_COROUTINES_THREADED_COROUTINE_MANAGER_H
17 
18 #include "libpandabase/os/mutex.h"
19 #include "runtime/coroutines/coroutine_manager.h"
20 #include "runtime/coroutines/coroutine.h"
21 #include "runtime/coroutines/priority_queue.h"
22 #include "runtime/include/value.h"
23 
24 namespace ark {
25 
26 /**
27  * @brief Thread-based coroutine manager implementation.
28  *
29  * In this implementation coroutines are OS threads. The invariants (only N coroutines are running simultaniously, etc.)
30  * are kept with the help of mutexes and condition variables.
31  *
32  * For interface function descriptions see CoroutineManager class declaration.
33  */
34 class ThreadedCoroutineManager : public CoroutineManager {
35 public:
36     NO_COPY_SEMANTIC(ThreadedCoroutineManager);
37     NO_MOVE_SEMANTIC(ThreadedCoroutineManager);
38 
ThreadedCoroutineManager(CoroutineFactory factory)39     explicit ThreadedCoroutineManager(CoroutineFactory factory) : CoroutineManager(factory) {}
40     ~ThreadedCoroutineManager() override = default;
41 
42     /* CoroutineManager interfaces, see CoroutineManager class for the details */
43     void Initialize(CoroutineManagerConfig config, Runtime *runtime, PandaVM *vm) override;
44     void Finalize() override;
45     void RegisterCoroutine(Coroutine *co) override;
46     bool TerminateCoroutine(Coroutine *co) override;
47     bool Launch(CompletionEvent *completionEvent, Method *entrypoint, PandaVector<Value> &&arguments,
48                 CoroutineLaunchMode mode, CoroutinePriority priority, bool abortFlag) override;
49     bool LaunchImmediately(CompletionEvent *completionEvent, Method *entrypoint, PandaVector<Value> &&arguments,
50                            CoroutineLaunchMode mode, CoroutinePriority priority, bool abortFlag) override;
51     bool LaunchNative(NativeEntrypointFunc epFunc, void *param, PandaString coroName, CoroutineLaunchMode mode,
52                       CoroutinePriority priority, bool abortFlag) override;
53     void Schedule() override;
54     void Await(CoroutineEvent *awaitee) RELEASE(awaitee) override;
55     void UnblockWaiters(CoroutineEvent *blocker) override;
PreZygoteFork()56     void PreZygoteFork() override {};
PostZygoteFork()57     void PostZygoteFork() override {};
58 
59     /* ThreadManager interfaces, see ThreadManager class for the details */
60     void WaitForDeregistration() override;
61     void SuspendAllThreads() override;
62     void ResumeAllThreads() override;
63     bool IsRunningThreadExist() override;
64 
65     /* debugging tools */
66     /**
67      * For ThreadedCoroutineManager implementation: no action performed if an attempt to switch coroutines on current
68      * worker is detected when coroutine switch is disabled.
69      */
DisableCoroutineSwitch()70     void DisableCoroutineSwitch() override {};
EnableCoroutineSwitch()71     void EnableCoroutineSwitch() override {};
IsCoroutineSwitchDisabled()72     bool IsCoroutineSwitchDisabled() override
73     {
74         return false;
75     };
76 
77     bool IsMainWorker(Coroutine *co) const override;
78 
79 protected:
80     bool EnumerateThreadsImpl(const ThreadManager::Callback &cb, unsigned int incMask,
81                               unsigned int xorMask) const override;
82     CoroutineContext *CreateCoroutineContext(bool coroHasEntrypoint) override;
83     void DeleteCoroutineContext(CoroutineContext *ctx) override;
84 
85     size_t GetCoroutineCount() override;
86     size_t GetCoroutineCountLimit() override;
87 
88     /// @return number of coroutines that can execute simultaniously
89     uint32_t GetActiveWorkersCount() const;
90     /**
91      * Create the required number of worker instances. They are required only for the interface
92      * level compatibility with other parts of the runtime.
93      */
94     void CreateWorkers(size_t howMany, Runtime *runtime, PandaVM *vm) REQUIRES(workersLock_) override;
95     CoroutineWorker *ChooseWorkerForCoroutine([[maybe_unused]] Coroutine *co);
96 
97 private:
98     bool LaunchImpl(EntrypointInfo &&epInfo, PandaString &&coroName, CoroutinePriority priority,
99                     bool startSuspended = true);
100     void ScheduleImpl();
101     void UnblockWaitersImpl(CoroutineEvent *blocker) REQUIRES(coroSwitchLock_);
102 
103     /* runnables queue management */
104     void PushToRunnableQueue(Coroutine *co, CoroutinePriority priority);
105     Coroutine *PopFromRunnableQueue();
106 #ifndef NDEBUG
107     void PrintRunnableQueue(const PandaString &requester);
108 #endif
109     bool RunnableCoroutinesExist();
110 
111     /* coroutine registry management */
112     void AddToRegistry(Coroutine *co) REQUIRES(coroListLock_);
113     void RemoveFromRegistry(Coroutine *co) REQUIRES(coroListLock_);
114 
115     void DeleteCoroutineInstance(Coroutine *co);
116     bool RegisterWaiter(Coroutine *waiter, CoroutineEvent *awaitee) RELEASE(awaitee);
117     void ScheduleNextCoroutine();
118     void MainCoroutineCompleted();
119 
120     os::memory::Mutex coroSwitchLock_;
121     os::memory::Mutex waitersLock_;
122     mutable os::memory::Mutex coroListLock_;
123     // all registered coros
124     PandaSet<Coroutine *> coroutines_ GUARDED_BY(coroListLock_);
125     // ready coros
126     PriorityQueue runnablesQueue_;
127     // blocked coros: Coroutine AWAITS CoroutineEvent
128     PandaMap<CoroutineEvent *, Coroutine *> waiters_;
129 
130     os::memory::ConditionVariable cvAwaitAll_;
131     os::memory::Mutex cvAwaitAllMutex_;
132 
133     // worker related members
134     PandaVector<CoroutineWorker *> workers_ GUARDED_BY(workersLock_);
135     size_t activeWorkersCount_ GUARDED_BY(workersLock_) = 0;
136     mutable os::memory::RecursiveMutex workersLock_;
137     mutable os::memory::ConditionVariable workersCv_;
138 
139     // main is running from the very beginning
140     std::atomic_uint32_t runningCorosCount_ = 1;
141     std::atomic_uint32_t coroutineCount_ = 0;
142 };
143 
144 }  // namespace ark
145 
146 #endif /* PANDA_RUNTIME_COROUTINES_THREADED_COROUTINE_MANAGER_H */
147