1*03ce13f7SAndroid Build Coastguard Worker // Copyright 2019 The SwiftShader Authors. All Rights Reserved.
2*03ce13f7SAndroid Build Coastguard Worker //
3*03ce13f7SAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License");
4*03ce13f7SAndroid Build Coastguard Worker // you may not use this file except in compliance with the License.
5*03ce13f7SAndroid Build Coastguard Worker // You may obtain a copy of the License at
6*03ce13f7SAndroid Build Coastguard Worker //
7*03ce13f7SAndroid Build Coastguard Worker // http://www.apache.org/licenses/LICENSE-2.0
8*03ce13f7SAndroid Build Coastguard Worker //
9*03ce13f7SAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
10*03ce13f7SAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS,
11*03ce13f7SAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*03ce13f7SAndroid Build Coastguard Worker // See the License for the specific language governing permissions and
13*03ce13f7SAndroid Build Coastguard Worker // limitations under the License.
14*03ce13f7SAndroid Build Coastguard Worker
15*03ce13f7SAndroid Build Coastguard Worker #include "Thread.hpp"
16*03ce13f7SAndroid Build Coastguard Worker
17*03ce13f7SAndroid Build Coastguard Worker #include "Context.hpp"
18*03ce13f7SAndroid Build Coastguard Worker #include "EventListener.hpp"
19*03ce13f7SAndroid Build Coastguard Worker #include "File.hpp"
20*03ce13f7SAndroid Build Coastguard Worker
21*03ce13f7SAndroid Build Coastguard Worker namespace vk {
22*03ce13f7SAndroid Build Coastguard Worker namespace dbg {
23*03ce13f7SAndroid Build Coastguard Worker
Thread(ID id,Context * ctx)24*03ce13f7SAndroid Build Coastguard Worker Thread::Thread(ID id, Context *ctx)
25*03ce13f7SAndroid Build Coastguard Worker : id(id)
26*03ce13f7SAndroid Build Coastguard Worker , ctx(ctx)
27*03ce13f7SAndroid Build Coastguard Worker {}
28*03ce13f7SAndroid Build Coastguard Worker
setName(const std::string & name)29*03ce13f7SAndroid Build Coastguard Worker void Thread::setName(const std::string &name)
30*03ce13f7SAndroid Build Coastguard Worker {
31*03ce13f7SAndroid Build Coastguard Worker marl::lock lock(mutex);
32*03ce13f7SAndroid Build Coastguard Worker name_ = name;
33*03ce13f7SAndroid Build Coastguard Worker }
34*03ce13f7SAndroid Build Coastguard Worker
name() const35*03ce13f7SAndroid Build Coastguard Worker std::string Thread::name() const
36*03ce13f7SAndroid Build Coastguard Worker {
37*03ce13f7SAndroid Build Coastguard Worker marl::lock lock(mutex);
38*03ce13f7SAndroid Build Coastguard Worker return name_;
39*03ce13f7SAndroid Build Coastguard Worker }
40*03ce13f7SAndroid Build Coastguard Worker
onLocationUpdate(marl::lock & lock)41*03ce13f7SAndroid Build Coastguard Worker void Thread::onLocationUpdate(marl::lock &lock)
42*03ce13f7SAndroid Build Coastguard Worker {
43*03ce13f7SAndroid Build Coastguard Worker auto location = frames.back()->location;
44*03ce13f7SAndroid Build Coastguard Worker
45*03ce13f7SAndroid Build Coastguard Worker if(state_ == State::Running)
46*03ce13f7SAndroid Build Coastguard Worker {
47*03ce13f7SAndroid Build Coastguard Worker if(location.file->hasBreakpoint(location.line))
48*03ce13f7SAndroid Build Coastguard Worker {
49*03ce13f7SAndroid Build Coastguard Worker ctx->serverEventBroadcast()->onLineBreakpointHit(id);
50*03ce13f7SAndroid Build Coastguard Worker state_ = State::Paused;
51*03ce13f7SAndroid Build Coastguard Worker }
52*03ce13f7SAndroid Build Coastguard Worker }
53*03ce13f7SAndroid Build Coastguard Worker
54*03ce13f7SAndroid Build Coastguard Worker switch(state_)
55*03ce13f7SAndroid Build Coastguard Worker {
56*03ce13f7SAndroid Build Coastguard Worker case State::Paused:
57*03ce13f7SAndroid Build Coastguard Worker lock.wait(stateCV, [this]() REQUIRES(mutex) { return state_ != State::Paused; });
58*03ce13f7SAndroid Build Coastguard Worker break;
59*03ce13f7SAndroid Build Coastguard Worker
60*03ce13f7SAndroid Build Coastguard Worker case State::Stepping:
61*03ce13f7SAndroid Build Coastguard Worker {
62*03ce13f7SAndroid Build Coastguard Worker bool pause = false;
63*03ce13f7SAndroid Build Coastguard Worker
64*03ce13f7SAndroid Build Coastguard Worker {
65*03ce13f7SAndroid Build Coastguard Worker auto frame = pauseAtFrame.lock();
66*03ce13f7SAndroid Build Coastguard Worker pause = !frame; // Pause if there's no pause-at-frame...
67*03ce13f7SAndroid Build Coastguard Worker if(frame == frames.back()) // ... or if we've reached the pause-at-frame
68*03ce13f7SAndroid Build Coastguard Worker {
69*03ce13f7SAndroid Build Coastguard Worker pause = true;
70*03ce13f7SAndroid Build Coastguard Worker pauseAtFrame.reset();
71*03ce13f7SAndroid Build Coastguard Worker }
72*03ce13f7SAndroid Build Coastguard Worker }
73*03ce13f7SAndroid Build Coastguard Worker
74*03ce13f7SAndroid Build Coastguard Worker if(pause)
75*03ce13f7SAndroid Build Coastguard Worker {
76*03ce13f7SAndroid Build Coastguard Worker ctx->serverEventBroadcast()->onThreadStepped(id);
77*03ce13f7SAndroid Build Coastguard Worker state_ = State::Paused;
78*03ce13f7SAndroid Build Coastguard Worker lock.wait(stateCV, [this]() REQUIRES(mutex) { return state_ != State::Paused; });
79*03ce13f7SAndroid Build Coastguard Worker }
80*03ce13f7SAndroid Build Coastguard Worker }
81*03ce13f7SAndroid Build Coastguard Worker break;
82*03ce13f7SAndroid Build Coastguard Worker
83*03ce13f7SAndroid Build Coastguard Worker case State::Running:
84*03ce13f7SAndroid Build Coastguard Worker break;
85*03ce13f7SAndroid Build Coastguard Worker }
86*03ce13f7SAndroid Build Coastguard Worker }
87*03ce13f7SAndroid Build Coastguard Worker
enter(const std::shared_ptr<File> & file,const std::string & function,const UpdateFrame & f)88*03ce13f7SAndroid Build Coastguard Worker void Thread::enter(const std::shared_ptr<File> &file, const std::string &function, const UpdateFrame &f)
89*03ce13f7SAndroid Build Coastguard Worker {
90*03ce13f7SAndroid Build Coastguard Worker std::shared_ptr<Frame> frame;
91*03ce13f7SAndroid Build Coastguard Worker bool isFunctionBreakpoint;
92*03ce13f7SAndroid Build Coastguard Worker {
93*03ce13f7SAndroid Build Coastguard Worker auto lock = ctx->lock();
94*03ce13f7SAndroid Build Coastguard Worker frame = lock.createFrame(file, function);
95*03ce13f7SAndroid Build Coastguard Worker isFunctionBreakpoint = lock.isFunctionBreakpoint(function);
96*03ce13f7SAndroid Build Coastguard Worker }
97*03ce13f7SAndroid Build Coastguard Worker
98*03ce13f7SAndroid Build Coastguard Worker {
99*03ce13f7SAndroid Build Coastguard Worker marl::lock lock(mutex);
100*03ce13f7SAndroid Build Coastguard Worker frames.push_back(frame);
101*03ce13f7SAndroid Build Coastguard Worker
102*03ce13f7SAndroid Build Coastguard Worker if(f) { f(*frame); }
103*03ce13f7SAndroid Build Coastguard Worker
104*03ce13f7SAndroid Build Coastguard Worker if(isFunctionBreakpoint)
105*03ce13f7SAndroid Build Coastguard Worker {
106*03ce13f7SAndroid Build Coastguard Worker ctx->serverEventBroadcast()->onFunctionBreakpointHit(id);
107*03ce13f7SAndroid Build Coastguard Worker state_ = State::Paused;
108*03ce13f7SAndroid Build Coastguard Worker }
109*03ce13f7SAndroid Build Coastguard Worker
110*03ce13f7SAndroid Build Coastguard Worker onLocationUpdate(lock);
111*03ce13f7SAndroid Build Coastguard Worker }
112*03ce13f7SAndroid Build Coastguard Worker }
113*03ce13f7SAndroid Build Coastguard Worker
exit(bool isStep)114*03ce13f7SAndroid Build Coastguard Worker void Thread::exit(bool isStep /* = false */)
115*03ce13f7SAndroid Build Coastguard Worker {
116*03ce13f7SAndroid Build Coastguard Worker marl::lock lock(mutex);
117*03ce13f7SAndroid Build Coastguard Worker frames.pop_back();
118*03ce13f7SAndroid Build Coastguard Worker if(isStep)
119*03ce13f7SAndroid Build Coastguard Worker {
120*03ce13f7SAndroid Build Coastguard Worker onLocationUpdate(lock);
121*03ce13f7SAndroid Build Coastguard Worker }
122*03ce13f7SAndroid Build Coastguard Worker }
123*03ce13f7SAndroid Build Coastguard Worker
update(bool isStep,const UpdateFrame & f)124*03ce13f7SAndroid Build Coastguard Worker void Thread::update(bool isStep, const UpdateFrame &f)
125*03ce13f7SAndroid Build Coastguard Worker {
126*03ce13f7SAndroid Build Coastguard Worker marl::lock lock(mutex);
127*03ce13f7SAndroid Build Coastguard Worker auto &frame = *frames.back();
128*03ce13f7SAndroid Build Coastguard Worker if(isStep)
129*03ce13f7SAndroid Build Coastguard Worker {
130*03ce13f7SAndroid Build Coastguard Worker auto oldLocation = frame.location;
131*03ce13f7SAndroid Build Coastguard Worker f(frame);
132*03ce13f7SAndroid Build Coastguard Worker if(frame.location != oldLocation)
133*03ce13f7SAndroid Build Coastguard Worker {
134*03ce13f7SAndroid Build Coastguard Worker onLocationUpdate(lock);
135*03ce13f7SAndroid Build Coastguard Worker }
136*03ce13f7SAndroid Build Coastguard Worker }
137*03ce13f7SAndroid Build Coastguard Worker else
138*03ce13f7SAndroid Build Coastguard Worker {
139*03ce13f7SAndroid Build Coastguard Worker f(frame);
140*03ce13f7SAndroid Build Coastguard Worker }
141*03ce13f7SAndroid Build Coastguard Worker }
142*03ce13f7SAndroid Build Coastguard Worker
frame() const143*03ce13f7SAndroid Build Coastguard Worker Frame Thread::frame() const
144*03ce13f7SAndroid Build Coastguard Worker {
145*03ce13f7SAndroid Build Coastguard Worker marl::lock lock(mutex);
146*03ce13f7SAndroid Build Coastguard Worker return *frames.back();
147*03ce13f7SAndroid Build Coastguard Worker }
148*03ce13f7SAndroid Build Coastguard Worker
stack() const149*03ce13f7SAndroid Build Coastguard Worker std::vector<Frame> Thread::stack() const
150*03ce13f7SAndroid Build Coastguard Worker {
151*03ce13f7SAndroid Build Coastguard Worker marl::lock lock(mutex);
152*03ce13f7SAndroid Build Coastguard Worker std::vector<Frame> out;
153*03ce13f7SAndroid Build Coastguard Worker out.reserve(frames.size());
154*03ce13f7SAndroid Build Coastguard Worker for(auto frame : frames)
155*03ce13f7SAndroid Build Coastguard Worker {
156*03ce13f7SAndroid Build Coastguard Worker out.push_back(*frame);
157*03ce13f7SAndroid Build Coastguard Worker }
158*03ce13f7SAndroid Build Coastguard Worker return out;
159*03ce13f7SAndroid Build Coastguard Worker }
160*03ce13f7SAndroid Build Coastguard Worker
depth() const161*03ce13f7SAndroid Build Coastguard Worker size_t Thread::depth() const
162*03ce13f7SAndroid Build Coastguard Worker {
163*03ce13f7SAndroid Build Coastguard Worker marl::lock lock(mutex);
164*03ce13f7SAndroid Build Coastguard Worker return frames.size();
165*03ce13f7SAndroid Build Coastguard Worker }
166*03ce13f7SAndroid Build Coastguard Worker
state() const167*03ce13f7SAndroid Build Coastguard Worker Thread::State Thread::state() const
168*03ce13f7SAndroid Build Coastguard Worker {
169*03ce13f7SAndroid Build Coastguard Worker marl::lock lock(mutex);
170*03ce13f7SAndroid Build Coastguard Worker return state_;
171*03ce13f7SAndroid Build Coastguard Worker }
172*03ce13f7SAndroid Build Coastguard Worker
resume()173*03ce13f7SAndroid Build Coastguard Worker void Thread::resume()
174*03ce13f7SAndroid Build Coastguard Worker {
175*03ce13f7SAndroid Build Coastguard Worker {
176*03ce13f7SAndroid Build Coastguard Worker marl::lock lock(mutex);
177*03ce13f7SAndroid Build Coastguard Worker state_ = State::Running;
178*03ce13f7SAndroid Build Coastguard Worker }
179*03ce13f7SAndroid Build Coastguard Worker stateCV.notify_all();
180*03ce13f7SAndroid Build Coastguard Worker }
181*03ce13f7SAndroid Build Coastguard Worker
pause()182*03ce13f7SAndroid Build Coastguard Worker void Thread::pause()
183*03ce13f7SAndroid Build Coastguard Worker {
184*03ce13f7SAndroid Build Coastguard Worker marl::lock lock(mutex);
185*03ce13f7SAndroid Build Coastguard Worker state_ = State::Paused;
186*03ce13f7SAndroid Build Coastguard Worker }
187*03ce13f7SAndroid Build Coastguard Worker
stepIn()188*03ce13f7SAndroid Build Coastguard Worker void Thread::stepIn()
189*03ce13f7SAndroid Build Coastguard Worker {
190*03ce13f7SAndroid Build Coastguard Worker marl::lock lock(mutex);
191*03ce13f7SAndroid Build Coastguard Worker state_ = State::Stepping;
192*03ce13f7SAndroid Build Coastguard Worker pauseAtFrame.reset();
193*03ce13f7SAndroid Build Coastguard Worker stateCV.notify_all();
194*03ce13f7SAndroid Build Coastguard Worker }
195*03ce13f7SAndroid Build Coastguard Worker
stepOver()196*03ce13f7SAndroid Build Coastguard Worker void Thread::stepOver()
197*03ce13f7SAndroid Build Coastguard Worker {
198*03ce13f7SAndroid Build Coastguard Worker marl::lock lock(mutex);
199*03ce13f7SAndroid Build Coastguard Worker state_ = State::Stepping;
200*03ce13f7SAndroid Build Coastguard Worker pauseAtFrame = frames.back();
201*03ce13f7SAndroid Build Coastguard Worker stateCV.notify_all();
202*03ce13f7SAndroid Build Coastguard Worker }
203*03ce13f7SAndroid Build Coastguard Worker
stepOut()204*03ce13f7SAndroid Build Coastguard Worker void Thread::stepOut()
205*03ce13f7SAndroid Build Coastguard Worker {
206*03ce13f7SAndroid Build Coastguard Worker marl::lock lock(mutex);
207*03ce13f7SAndroid Build Coastguard Worker state_ = State::Stepping;
208*03ce13f7SAndroid Build Coastguard Worker pauseAtFrame = (frames.size() > 1) ? frames[frames.size() - 2] : nullptr;
209*03ce13f7SAndroid Build Coastguard Worker stateCV.notify_all();
210*03ce13f7SAndroid Build Coastguard Worker }
211*03ce13f7SAndroid Build Coastguard Worker
212*03ce13f7SAndroid Build Coastguard Worker } // namespace dbg
213*03ce13f7SAndroid Build Coastguard Worker } // namespace vk
214