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