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