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