• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024 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 #ifndef ECMASCRIPT_DAEMON_THREAD_H
17 #define ECMASCRIPT_DAEMON_THREAD_H
18 
19 #include <atomic>
20 #include <deque>
21 #include <thread>
22 
23 #include "common_components/taskpool/runner.h"
24 #include "ecmascript/daemon/daemon_task.h"
25 #include "ecmascript/js_thread.h"
26 #include "ecmascript/mutator_lock.h"
27 #include "ecmascript/platform/mutex.h"
28 
29 namespace panda::ecmascript {
30 
31 static constexpr uint32_t DAEMON_THREAD_INDEX = 0;
32 
33 class DaemonThread : public JSThread {
34 public:
35     static void CreateNewInstance();
36     static DaemonThread *GetInstance();
37     static void DestroyInstance();
38 
39     using ThreadId = uint32_t;
40 
41     void StartRunning();
42 
43     void EnsureRunning();
44 
45     bool IsRunning() const;
46 
47     void MarkTerminate();       // In daemon thread
48 
49     // Wait daemon thread finished, and then call TaskPool.Destroy
50     void WaitFinished();
51 
52     bool CheckAndPostTask(DaemonTask task);
53 
54     /**
55      * Called in daemon thread, and manually call this in DaemonTask at the appropriate time,
56      * e.g. for GC task, call this before ResumeAll instead of the task complete ended, to prevent in some
57      * time sequence, all js_thread is resumed and one of these post another GC task, but the PostedGroup
58      * have not been cleaned, leading the task lost.
59     */
60     void FinishRunningTask();
61 
GetSharedMarkStatus()62     SharedMarkStatus GetSharedMarkStatus() const
63     {
64         return markStatus_.load(std::memory_order_acquire);
65     }
66 
67     void SetSharedMarkStatus(SharedMarkStatus markStatus);
68 
IsReadyToConcurrentMark()69     bool IsReadyToConcurrentMark() const
70     {
71         return GetSharedMarkStatus() == SharedMarkStatus::READY_TO_CONCURRENT_MARK;
72     }
73 
IsConcurrentMarkingOrFinished()74     bool IsConcurrentMarkingOrFinished() const
75     {
76         return GetSharedMarkStatus() == SharedMarkStatus::CONCURRENT_MARKING_OR_FINISHED;
77     }
78 
79     void SetQosPriority(common::PriorityMode mode);
80 #ifndef NDEBUG
81     MutatorLock::MutatorLockState GetMutatorLockState() const;
82     void SetMutatorLockState(MutatorLock::MutatorLockState newState);
83 #endif
84 
85 private:
DaemonThread()86     DaemonThread() : JSThread(ThreadType::DAEMON_THREAD) {}
87     ~DaemonThread() = default;
88 
89     void Run();
90 
91     bool AddTaskGroup(DaemonTaskGroup taskGroup);
92 
93     DaemonTask PopTask();
94 
95     static DaemonThread *instance_;
96 
97     // In js thread, load the running need atomic, but in daemon do not need, since only daemon thread
98     // will set running_ to false
99     std::atomic<bool> running_ {false};
100 
101     std::atomic<SharedMarkStatus> markStatus_ {SharedMarkStatus::READY_TO_CONCURRENT_MARK};
102 
103     std::unique_ptr<std::thread> thread_;
104 
105     std::deque<DaemonTask> tasks_;
106     DaemonTaskGroup runningGroup_ {DaemonTaskGroup::NONE};
107     uint32_t postedGroups_ {0};
108     Mutex mtx_;
109     ConditionVariable cv_;
110 #ifndef NDEBUG
111     MutatorLock::MutatorLockState mutatorLockState_ = MutatorLock::MutatorLockState::UNLOCKED;
112 #endif
113 };
114 }  // namespace panda::ecmascript
115 #endif  // ECMASCRIPT_DAEMON_THREAD_H