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