xref: /aosp_15_r20/external/swiftshader/src/Vulkan/Debug/Thread.hpp (revision 03ce13f70fcc45d86ee91b7ee4cab1936a95046e)
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 #ifndef VK_DEBUG_THREAD_HPP_
16*03ce13f7SAndroid Build Coastguard Worker #define VK_DEBUG_THREAD_HPP_
17*03ce13f7SAndroid Build Coastguard Worker 
18*03ce13f7SAndroid Build Coastguard Worker #include "Context.hpp"
19*03ce13f7SAndroid Build Coastguard Worker #include "ID.hpp"
20*03ce13f7SAndroid Build Coastguard Worker #include "Location.hpp"
21*03ce13f7SAndroid Build Coastguard Worker 
22*03ce13f7SAndroid Build Coastguard Worker #include "marl/mutex.h"
23*03ce13f7SAndroid Build Coastguard Worker #include "marl/tsa.h"
24*03ce13f7SAndroid Build Coastguard Worker 
25*03ce13f7SAndroid Build Coastguard Worker #include <condition_variable>
26*03ce13f7SAndroid Build Coastguard Worker #include <memory>
27*03ce13f7SAndroid Build Coastguard Worker #include <string>
28*03ce13f7SAndroid Build Coastguard Worker #include <vector>
29*03ce13f7SAndroid Build Coastguard Worker 
30*03ce13f7SAndroid Build Coastguard Worker namespace vk {
31*03ce13f7SAndroid Build Coastguard Worker namespace dbg {
32*03ce13f7SAndroid Build Coastguard Worker 
33*03ce13f7SAndroid Build Coastguard Worker class File;
34*03ce13f7SAndroid Build Coastguard Worker class VariableContainer;
35*03ce13f7SAndroid Build Coastguard Worker class ServerEventListener;
36*03ce13f7SAndroid Build Coastguard Worker 
37*03ce13f7SAndroid Build Coastguard Worker // Scope is a container for variables and is used to provide source data for the
38*03ce13f7SAndroid Build Coastguard Worker // DAP 'Scope' type:
39*03ce13f7SAndroid Build Coastguard Worker // https://microsoft.github.io/debug-adapter-protocol/specification#Types_Scope
40*03ce13f7SAndroid Build Coastguard Worker class Scope
41*03ce13f7SAndroid Build Coastguard Worker {
42*03ce13f7SAndroid Build Coastguard Worker public:
43*03ce13f7SAndroid Build Coastguard Worker 	using ID = dbg::ID<Scope>;
44*03ce13f7SAndroid Build Coastguard Worker 
45*03ce13f7SAndroid Build Coastguard Worker 	inline Scope(ID id,
46*03ce13f7SAndroid Build Coastguard Worker 	             const std::shared_ptr<File> &file,
47*03ce13f7SAndroid Build Coastguard Worker 	             const std::shared_ptr<VariableContainer> &variables);
48*03ce13f7SAndroid Build Coastguard Worker 
49*03ce13f7SAndroid Build Coastguard Worker 	// The unique identifier of the scope.
50*03ce13f7SAndroid Build Coastguard Worker 	const ID id;
51*03ce13f7SAndroid Build Coastguard Worker 
52*03ce13f7SAndroid Build Coastguard Worker 	// The file this scope is associated with.
53*03ce13f7SAndroid Build Coastguard Worker 	const std::shared_ptr<File> file;
54*03ce13f7SAndroid Build Coastguard Worker 
55*03ce13f7SAndroid Build Coastguard Worker 	// The scope's variables.
56*03ce13f7SAndroid Build Coastguard Worker 	const std::shared_ptr<VariableContainer> variables;
57*03ce13f7SAndroid Build Coastguard Worker };
58*03ce13f7SAndroid Build Coastguard Worker 
Scope(ID id,const std::shared_ptr<File> & file,const std::shared_ptr<VariableContainer> & variables)59*03ce13f7SAndroid Build Coastguard Worker Scope::Scope(ID id,
60*03ce13f7SAndroid Build Coastguard Worker              const std::shared_ptr<File> &file,
61*03ce13f7SAndroid Build Coastguard Worker              const std::shared_ptr<VariableContainer> &variables)
62*03ce13f7SAndroid Build Coastguard Worker     : id(id)
63*03ce13f7SAndroid Build Coastguard Worker     , file(file)
64*03ce13f7SAndroid Build Coastguard Worker     , variables(variables)
65*03ce13f7SAndroid Build Coastguard Worker {}
66*03ce13f7SAndroid Build Coastguard Worker 
67*03ce13f7SAndroid Build Coastguard Worker // Frame holds a number of variable scopes for one of a thread's stack frame,
68*03ce13f7SAndroid Build Coastguard Worker // and is used to provide source data for the DAP 'StackFrame' type:
69*03ce13f7SAndroid Build Coastguard Worker // https://microsoft.github.io/debug-adapter-protocol/specification#Types_StackFrame
70*03ce13f7SAndroid Build Coastguard Worker class Frame
71*03ce13f7SAndroid Build Coastguard Worker {
72*03ce13f7SAndroid Build Coastguard Worker public:
73*03ce13f7SAndroid Build Coastguard Worker 	using ID = dbg::ID<Frame>;
74*03ce13f7SAndroid Build Coastguard Worker 
75*03ce13f7SAndroid Build Coastguard Worker 	inline Frame(ID id, std::string function);
76*03ce13f7SAndroid Build Coastguard Worker 
77*03ce13f7SAndroid Build Coastguard Worker 	// The unique identifier of the stack frame.
78*03ce13f7SAndroid Build Coastguard Worker 	const ID id;
79*03ce13f7SAndroid Build Coastguard Worker 
80*03ce13f7SAndroid Build Coastguard Worker 	// The name of function for this stack frame.
81*03ce13f7SAndroid Build Coastguard Worker 	const std::string function;
82*03ce13f7SAndroid Build Coastguard Worker 
83*03ce13f7SAndroid Build Coastguard Worker 	// The current execution location within the stack frame.
84*03ce13f7SAndroid Build Coastguard Worker 	Location location;
85*03ce13f7SAndroid Build Coastguard Worker 
86*03ce13f7SAndroid Build Coastguard Worker 	// The scope for the frame's arguments.
87*03ce13f7SAndroid Build Coastguard Worker 	std::shared_ptr<Scope> arguments;
88*03ce13f7SAndroid Build Coastguard Worker 
89*03ce13f7SAndroid Build Coastguard Worker 	// The scope for the frame's locals.
90*03ce13f7SAndroid Build Coastguard Worker 	std::shared_ptr<Scope> locals;
91*03ce13f7SAndroid Build Coastguard Worker 
92*03ce13f7SAndroid Build Coastguard Worker 	// The scope for the frame's registers.
93*03ce13f7SAndroid Build Coastguard Worker 	std::shared_ptr<Scope> registers;
94*03ce13f7SAndroid Build Coastguard Worker 
95*03ce13f7SAndroid Build Coastguard Worker 	// The scope for variables that should only appear in hover tooltips.
96*03ce13f7SAndroid Build Coastguard Worker 	std::shared_ptr<Scope> hovers;
97*03ce13f7SAndroid Build Coastguard Worker };
98*03ce13f7SAndroid Build Coastguard Worker 
Frame(ID id,std::string function)99*03ce13f7SAndroid Build Coastguard Worker Frame::Frame(ID id, std::string function)
100*03ce13f7SAndroid Build Coastguard Worker     : id(id)
101*03ce13f7SAndroid Build Coastguard Worker     , function(std::move(function))
102*03ce13f7SAndroid Build Coastguard Worker {}
103*03ce13f7SAndroid Build Coastguard Worker 
104*03ce13f7SAndroid Build Coastguard Worker // Thread holds the state for a single thread of execution.
105*03ce13f7SAndroid Build Coastguard Worker class Thread
106*03ce13f7SAndroid Build Coastguard Worker {
107*03ce13f7SAndroid Build Coastguard Worker public:
108*03ce13f7SAndroid Build Coastguard Worker 	using ID = dbg::ID<Thread>;
109*03ce13f7SAndroid Build Coastguard Worker 
110*03ce13f7SAndroid Build Coastguard Worker 	using UpdateFrame = std::function<void(Frame &)>;
111*03ce13f7SAndroid Build Coastguard Worker 
112*03ce13f7SAndroid Build Coastguard Worker 	// The current execution state.
113*03ce13f7SAndroid Build Coastguard Worker 	enum class State
114*03ce13f7SAndroid Build Coastguard Worker 	{
115*03ce13f7SAndroid Build Coastguard Worker 		Running,   // Thread is running.
116*03ce13f7SAndroid Build Coastguard Worker 		Stepping,  // Thread is currently single line stepping.
117*03ce13f7SAndroid Build Coastguard Worker 		Paused     // Thread is currently paused.
118*03ce13f7SAndroid Build Coastguard Worker 	};
119*03ce13f7SAndroid Build Coastguard Worker 
120*03ce13f7SAndroid Build Coastguard Worker 	Thread(ID id, Context *ctx);
121*03ce13f7SAndroid Build Coastguard Worker 
122*03ce13f7SAndroid Build Coastguard Worker 	// setName() sets the name of the thread.
123*03ce13f7SAndroid Build Coastguard Worker 	void setName(const std::string &);
124*03ce13f7SAndroid Build Coastguard Worker 
125*03ce13f7SAndroid Build Coastguard Worker 	// name() returns the name of the thread.
126*03ce13f7SAndroid Build Coastguard Worker 	std::string name() const;
127*03ce13f7SAndroid Build Coastguard Worker 
128*03ce13f7SAndroid Build Coastguard Worker 	// enter() pushes the thread's stack with a new frame created with the given
129*03ce13f7SAndroid Build Coastguard Worker 	// file and function, then calls f to modify the new frame of the stack.
130*03ce13f7SAndroid Build Coastguard Worker 	void enter(const std::shared_ptr<File> &file, const std::string &function, const UpdateFrame &f = nullptr);
131*03ce13f7SAndroid Build Coastguard Worker 
132*03ce13f7SAndroid Build Coastguard Worker 	// exit() pops the thread's stack frame.
133*03ce13f7SAndroid Build Coastguard Worker 	// If isStep is true, then this will be considered a line-steppable event,
134*03ce13f7SAndroid Build Coastguard Worker 	// and the debugger may pause at the function call at the new top most stack
135*03ce13f7SAndroid Build Coastguard Worker 	// frame.
136*03ce13f7SAndroid Build Coastguard Worker 	void exit(bool isStep = false);
137*03ce13f7SAndroid Build Coastguard Worker 
138*03ce13f7SAndroid Build Coastguard Worker 	// frame() returns a copy of the thread's top most stack frame.
139*03ce13f7SAndroid Build Coastguard Worker 	Frame frame() const;
140*03ce13f7SAndroid Build Coastguard Worker 
141*03ce13f7SAndroid Build Coastguard Worker 	// stack() returns a copy of the thread's current stack frames.
142*03ce13f7SAndroid Build Coastguard Worker 	std::vector<Frame> stack() const;
143*03ce13f7SAndroid Build Coastguard Worker 
144*03ce13f7SAndroid Build Coastguard Worker 	// depth() returns the number of stack frames.
145*03ce13f7SAndroid Build Coastguard Worker 	size_t depth() const;
146*03ce13f7SAndroid Build Coastguard Worker 
147*03ce13f7SAndroid Build Coastguard Worker 	// state() returns the current thread's state.
148*03ce13f7SAndroid Build Coastguard Worker 	State state() const;
149*03ce13f7SAndroid Build Coastguard Worker 
150*03ce13f7SAndroid Build Coastguard Worker 	// update() calls f to modify the top most frame of the stack.
151*03ce13f7SAndroid Build Coastguard Worker 	// If the frame's location is changed and isStep is true, update()
152*03ce13f7SAndroid Build Coastguard Worker 	// potentially blocks until the thread is resumed with one of the methods
153*03ce13f7SAndroid Build Coastguard Worker 	// below.
154*03ce13f7SAndroid Build Coastguard Worker 	// isStep is used to distinguish same-statement column position updates
155*03ce13f7SAndroid Build Coastguard Worker 	// from full line updates. Note that we cannot simply examine line position
156*03ce13f7SAndroid Build Coastguard Worker 	// changes as single-line loops such as `while(true) { foo(); }` would not
157*03ce13f7SAndroid Build Coastguard Worker 	// be correctly steppable.
158*03ce13f7SAndroid Build Coastguard Worker 	void update(bool isStep, const UpdateFrame &f);
159*03ce13f7SAndroid Build Coastguard Worker 
160*03ce13f7SAndroid Build Coastguard Worker 	// resume() resumes execution of the thread by unblocking a call to
161*03ce13f7SAndroid Build Coastguard Worker 	// update() and setting the thread's state to State::Running.
162*03ce13f7SAndroid Build Coastguard Worker 	void resume();
163*03ce13f7SAndroid Build Coastguard Worker 
164*03ce13f7SAndroid Build Coastguard Worker 	// pause() suspends execution of the thread by blocking the next call to
165*03ce13f7SAndroid Build Coastguard Worker 	// update() and setting the thread's state to State::Paused.
166*03ce13f7SAndroid Build Coastguard Worker 	void pause();
167*03ce13f7SAndroid Build Coastguard Worker 
168*03ce13f7SAndroid Build Coastguard Worker 	// stepIn() temporarily resumes execution of the thread by unblocking a
169*03ce13f7SAndroid Build Coastguard Worker 	// call to update(), and setting the thread's state to State::Stepping.
170*03ce13f7SAndroid Build Coastguard Worker 	// The next call to update() will suspend execution again.
171*03ce13f7SAndroid Build Coastguard Worker 	void stepIn();
172*03ce13f7SAndroid Build Coastguard Worker 
173*03ce13f7SAndroid Build Coastguard Worker 	// stepOver() temporarily resumes execution of the thread by unblocking a
174*03ce13f7SAndroid Build Coastguard Worker 	// call to update(), and setting the thread's state to State::Stepping.
175*03ce13f7SAndroid Build Coastguard Worker 	// The next call to update() within the same stack frame will suspend
176*03ce13f7SAndroid Build Coastguard Worker 	// execution again.
177*03ce13f7SAndroid Build Coastguard Worker 	void stepOver();
178*03ce13f7SAndroid Build Coastguard Worker 
179*03ce13f7SAndroid Build Coastguard Worker 	// stepOut() temporarily resumes execution of the thread by unblocking a
180*03ce13f7SAndroid Build Coastguard Worker 	// call to update(), and setting the thread's state to State::Stepping.
181*03ce13f7SAndroid Build Coastguard Worker 	// The next call to update() at the stack frame above the current frame will
182*03ce13f7SAndroid Build Coastguard Worker 	// suspend execution again.
183*03ce13f7SAndroid Build Coastguard Worker 	void stepOut();
184*03ce13f7SAndroid Build Coastguard Worker 
185*03ce13f7SAndroid Build Coastguard Worker 	// The unique identifier of the thread.
186*03ce13f7SAndroid Build Coastguard Worker 	const ID id;
187*03ce13f7SAndroid Build Coastguard Worker 
188*03ce13f7SAndroid Build Coastguard Worker private:
189*03ce13f7SAndroid Build Coastguard Worker 	Context *const ctx;
190*03ce13f7SAndroid Build Coastguard Worker 
191*03ce13f7SAndroid Build Coastguard Worker 	void onLocationUpdate(marl::lock &lock) REQUIRES(mutex);
192*03ce13f7SAndroid Build Coastguard Worker 
193*03ce13f7SAndroid Build Coastguard Worker 	mutable marl::mutex mutex;
194*03ce13f7SAndroid Build Coastguard Worker 	std::string name_ GUARDED_BY(mutex);
195*03ce13f7SAndroid Build Coastguard Worker 	std::vector<std::shared_ptr<Frame>> frames GUARDED_BY(mutex);
196*03ce13f7SAndroid Build Coastguard Worker 	State state_ GUARDED_BY(mutex) = State::Running;
197*03ce13f7SAndroid Build Coastguard Worker 	std::weak_ptr<Frame> pauseAtFrame GUARDED_BY(mutex);
198*03ce13f7SAndroid Build Coastguard Worker 
199*03ce13f7SAndroid Build Coastguard Worker 	std::condition_variable stateCV;
200*03ce13f7SAndroid Build Coastguard Worker };
201*03ce13f7SAndroid Build Coastguard Worker 
202*03ce13f7SAndroid Build Coastguard Worker }  // namespace dbg
203*03ce13f7SAndroid Build Coastguard Worker }  // namespace vk
204*03ce13f7SAndroid Build Coastguard Worker 
205*03ce13f7SAndroid Build Coastguard Worker #endif  // VK_DEBUG_THREAD_HPP_
206