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 #include "ecmascript/pgo_profiler/pgo_state.h"
17
18 #include "ecmascript/pgo_profiler/pgo_profiler.h"
19 #include "ecmascript/pgo_profiler/pgo_profiler_manager.h"
20
21 namespace panda::ecmascript::pgo {
22 using State = PGOState::State;
23 using GCState = PGOState::GCState;
PGOState()24 PGOState::PGOState()
25 {
26 manager_ = PGOProfilerManager::GetInstance();
27 }
28
ToString(State state)29 std::string PGOState::ToString(State state)
30 {
31 switch (state) {
32 case State::STOP:
33 return "STOP";
34 case State::SAVE:
35 return "SAVE";
36 case State::START:
37 return "START";
38 default:
39 return "UNKNOWN";
40 }
41 }
42
ToString(GCState state)43 std::string PGOState::ToString(GCState state)
44 {
45 switch (state) {
46 case GCState::STOP:
47 return "STOP";
48 case GCState::WAITING:
49 return "WAITING";
50 case GCState::RUNNING:
51 return "RUNNING";
52 default:
53 return "UNKNOWN";
54 }
55 }
56
GetState() const57 State PGOState::GetState() const
58 {
59 return state_.load(std::memory_order_acquire);
60 }
61
SetState(State state)62 void PGOState::SetState(State state)
63 {
64 #if PRINT_STATE_CHANGE
65 PrintStateChange(GetState(), state);
66 #endif
67 state_.store(state, std::memory_order_release);
68 }
69
GCIsWaiting() const70 bool PGOState::GCIsWaiting() const
71 {
72 GCState gcState = GetGCState();
73 return gcState == GCState::WAITING;
74 }
75
GCIsRunning() const76 bool PGOState::GCIsRunning() const
77 {
78 GCState gcState = GetGCState();
79 return gcState == GCState::RUNNING;
80 }
81
GCIsStop() const82 bool PGOState::GCIsStop() const
83 {
84 GCState gcState = GetGCState();
85 return gcState == GCState::STOP;
86 }
87
StateIsStop() const88 bool PGOState::StateIsStop() const
89 {
90 State state = GetState();
91 return state == State::STOP;
92 }
93
StateIsStart() const94 bool PGOState::StateIsStart() const
95 {
96 State state = GetState();
97 return state == State::START;
98 }
99
StateIsSave() const100 bool PGOState::StateIsSave() const
101 {
102 State state = GetState();
103 return state == State::SAVE;
104 }
105
106 #if PRINT_STATE_CHANGE
TryChangeState(State expected,State desired)107 bool PGOState::TryChangeState(State expected, State desired)
108 {
109 auto original = expected;
110 if (state_.compare_exchange_strong(expected, desired, std::memory_order_acq_rel)) {
111 PrintStateChange(expected, desired);
112 return true;
113 }
114 PrintStateChange(original, expected, desired);
115 return false;
116 }
117 #endif
118
119 #if !PRINT_STATE_CHANGE
TryChangeState(State expected,State desired)120 bool PGOState::TryChangeState(State expected, State desired)
121 {
122 if (state_.compare_exchange_strong(expected, desired, std::memory_order_acq_rel)) {
123 return true;
124 }
125 return false;
126 }
127 #endif
128
SetGCState(GCState state)129 void PGOState::SetGCState(GCState state)
130 {
131 gcState_.store(state, std::memory_order_release);
132 }
133
GetGCState() const134 GCState PGOState::GetGCState() const
135 {
136 return gcState_.load(std::memory_order_acquire);
137 }
138
SuspendByGC()139 void PGOState::SuspendByGC()
140 {
141 LockHolder lock(stateMutex_);
142 // possible state: START, SAVE, STOP
143 if (StateIsStart()) {
144 // possible gc state: STOP
145 SetGCState(GCState::WAITING);
146 needRedump_ = true;
147 WaitDump();
148 }
149 // possible gc state: STOP, WAITING
150 SetGCState(GCState::RUNNING);
151 }
152
ResumeByGC(PGOProfiler * profiler)153 void PGOState::ResumeByGC(PGOProfiler* profiler)
154 {
155 LockHolder lock(stateMutex_);
156 // possible state: START, SAVE, STOP
157 SetGCState(GCState::STOP);
158 if (needRedump_) {
159 manager_->TryDispatchDumpTask(profiler);
160 needRedump_ = false;
161 }
162 NotifyAllGCWaiters();
163 }
164
SetStartIfStop()165 bool PGOState::SetStartIfStop()
166 {
167 LockHolder lock(stateMutex_);
168 // possible state: STOP, SAVE
169 // possible gc state: STOP, WAITING, RUNNING
170 if (GCIsStop() && TryChangeState(State::STOP, State::START)) {
171 return true;
172 }
173 return false;
174 }
175
SetStopAndNotify()176 void PGOState::SetStopAndNotify()
177 {
178 LockHolder lock(stateMutex_);
179 // possible state: START, SAVE
180 SetState(State::STOP);
181 NotifyAllDumpWaiters();
182 }
183
SetSaveAndNotify()184 void PGOState::SetSaveAndNotify()
185 {
186 LockHolder lock(stateMutex_);
187 // possible state: START
188 SetState(State::SAVE);
189 NotifyAllDumpWaiters();
190 }
191
StartDumpBeforeDestroy()192 void PGOState::StartDumpBeforeDestroy()
193 {
194 LockHolder lock(stateMutex_);
195 // possible state: STOP, SAVE, START
196 // may notify after change to STOP and SAVE, we need to make sure state is STOP
197 while (!StateIsStop()) {
198 WaitDump();
199 }
200 // possible gc state: STOP, WAITING, RUNNING
201 if (!GCIsStop()) {
202 WaitGC();
203 }
204 SetState(State::START);
205 }
206
WaitDump()207 void PGOState::WaitDump()
208 {
209 stateCondition_.Wait(&stateMutex_);
210 }
211
NotifyAllDumpWaiters()212 void PGOState::NotifyAllDumpWaiters()
213 {
214 stateCondition_.SignalAll();
215 }
216
WaitGC()217 void PGOState::WaitGC()
218 {
219 gcCondition_.Wait(&stateMutex_);
220 }
221
NotifyAllGCWaiters()222 void PGOState::NotifyAllGCWaiters()
223 {
224 gcCondition_.SignalAll();
225 }
226 } // namespace panda::ecmascript::pgo
227