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 "Context.hpp"
16*03ce13f7SAndroid Build Coastguard Worker
17*03ce13f7SAndroid Build Coastguard Worker #include "EventListener.hpp"
18*03ce13f7SAndroid Build Coastguard Worker #include "File.hpp"
19*03ce13f7SAndroid Build Coastguard Worker #include "Thread.hpp"
20*03ce13f7SAndroid Build Coastguard Worker #include "Variable.hpp"
21*03ce13f7SAndroid Build Coastguard Worker #include "WeakMap.hpp"
22*03ce13f7SAndroid Build Coastguard Worker
23*03ce13f7SAndroid Build Coastguard Worker #include "System/Debug.hpp"
24*03ce13f7SAndroid Build Coastguard Worker
25*03ce13f7SAndroid Build Coastguard Worker #include <memory>
26*03ce13f7SAndroid Build Coastguard Worker #include <mutex>
27*03ce13f7SAndroid Build Coastguard Worker #include <thread>
28*03ce13f7SAndroid Build Coastguard Worker #include <unordered_map>
29*03ce13f7SAndroid Build Coastguard Worker #include <unordered_set>
30*03ce13f7SAndroid Build Coastguard Worker
31*03ce13f7SAndroid Build Coastguard Worker #if !defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)
32*03ce13f7SAndroid Build Coastguard Worker # define CHECK_REENTRANT_CONTEXT_LOCKS 1
33*03ce13f7SAndroid Build Coastguard Worker #else
34*03ce13f7SAndroid Build Coastguard Worker # define CHECK_REENTRANT_CONTEXT_LOCKS 0
35*03ce13f7SAndroid Build Coastguard Worker #endif
36*03ce13f7SAndroid Build Coastguard Worker
37*03ce13f7SAndroid Build Coastguard Worker namespace {
38*03ce13f7SAndroid Build Coastguard Worker
39*03ce13f7SAndroid Build Coastguard Worker #if CHECK_REENTRANT_CONTEXT_LOCKS
40*03ce13f7SAndroid Build Coastguard Worker thread_local std::unordered_set<const void *> contextsWithLock;
41*03ce13f7SAndroid Build Coastguard Worker #endif
42*03ce13f7SAndroid Build Coastguard Worker
43*03ce13f7SAndroid Build Coastguard Worker ////////////////////////////////////////////////////////////////////////////////
44*03ce13f7SAndroid Build Coastguard Worker // Broadcaster - template base class for ServerEventBroadcaster and
45*03ce13f7SAndroid Build Coastguard Worker // ClientEventBroadcaster
46*03ce13f7SAndroid Build Coastguard Worker ////////////////////////////////////////////////////////////////////////////////
47*03ce13f7SAndroid Build Coastguard Worker template<typename Listener>
48*03ce13f7SAndroid Build Coastguard Worker class Broadcaster : public Listener
49*03ce13f7SAndroid Build Coastguard Worker {
50*03ce13f7SAndroid Build Coastguard Worker public:
51*03ce13f7SAndroid Build Coastguard Worker void add(Listener *);
52*03ce13f7SAndroid Build Coastguard Worker void remove(Listener *);
53*03ce13f7SAndroid Build Coastguard Worker
54*03ce13f7SAndroid Build Coastguard Worker protected:
55*03ce13f7SAndroid Build Coastguard Worker template<typename F>
56*03ce13f7SAndroid Build Coastguard Worker inline void foreach(F &&);
57*03ce13f7SAndroid Build Coastguard Worker
58*03ce13f7SAndroid Build Coastguard Worker template<typename F>
59*03ce13f7SAndroid Build Coastguard Worker inline void modify(F &&);
60*03ce13f7SAndroid Build Coastguard Worker
61*03ce13f7SAndroid Build Coastguard Worker using ListenerSet = std::unordered_set<Listener *>;
62*03ce13f7SAndroid Build Coastguard Worker std::recursive_mutex mutex;
63*03ce13f7SAndroid Build Coastguard Worker std::shared_ptr<ListenerSet> listeners = std::make_shared<ListenerSet>();
64*03ce13f7SAndroid Build Coastguard Worker int listenersInUse = 0;
65*03ce13f7SAndroid Build Coastguard Worker };
66*03ce13f7SAndroid Build Coastguard Worker
67*03ce13f7SAndroid Build Coastguard Worker template<typename Listener>
add(Listener * l)68*03ce13f7SAndroid Build Coastguard Worker void Broadcaster<Listener>::add(Listener *l)
69*03ce13f7SAndroid Build Coastguard Worker {
70*03ce13f7SAndroid Build Coastguard Worker modify([&]() { listeners->emplace(l); });
71*03ce13f7SAndroid Build Coastguard Worker }
72*03ce13f7SAndroid Build Coastguard Worker
73*03ce13f7SAndroid Build Coastguard Worker template<typename Listener>
remove(Listener * l)74*03ce13f7SAndroid Build Coastguard Worker void Broadcaster<Listener>::remove(Listener *l)
75*03ce13f7SAndroid Build Coastguard Worker {
76*03ce13f7SAndroid Build Coastguard Worker modify([&]() { listeners->erase(l); });
77*03ce13f7SAndroid Build Coastguard Worker }
78*03ce13f7SAndroid Build Coastguard Worker
79*03ce13f7SAndroid Build Coastguard Worker template<typename Listener>
80*03ce13f7SAndroid Build Coastguard Worker template<typename F>
foreach(F && f)81*03ce13f7SAndroid Build Coastguard Worker void Broadcaster<Listener>::foreach(F &&f)
82*03ce13f7SAndroid Build Coastguard Worker {
83*03ce13f7SAndroid Build Coastguard Worker std::unique_lock<std::recursive_mutex> lock(mutex);
84*03ce13f7SAndroid Build Coastguard Worker ++listenersInUse;
85*03ce13f7SAndroid Build Coastguard Worker auto copy = listeners;
86*03ce13f7SAndroid Build Coastguard Worker for(auto l : *copy) { f(l); }
87*03ce13f7SAndroid Build Coastguard Worker --listenersInUse;
88*03ce13f7SAndroid Build Coastguard Worker }
89*03ce13f7SAndroid Build Coastguard Worker
90*03ce13f7SAndroid Build Coastguard Worker template<typename Listener>
91*03ce13f7SAndroid Build Coastguard Worker template<typename F>
modify(F && f)92*03ce13f7SAndroid Build Coastguard Worker void Broadcaster<Listener>::modify(F &&f)
93*03ce13f7SAndroid Build Coastguard Worker {
94*03ce13f7SAndroid Build Coastguard Worker std::unique_lock<std::recursive_mutex> lock(mutex);
95*03ce13f7SAndroid Build Coastguard Worker if(listenersInUse > 0)
96*03ce13f7SAndroid Build Coastguard Worker {
97*03ce13f7SAndroid Build Coastguard Worker // The listeners map is current being iterated over.
98*03ce13f7SAndroid Build Coastguard Worker // Make a copy before making the edit.
99*03ce13f7SAndroid Build Coastguard Worker listeners = std::make_shared<ListenerSet>(*listeners);
100*03ce13f7SAndroid Build Coastguard Worker }
101*03ce13f7SAndroid Build Coastguard Worker f();
102*03ce13f7SAndroid Build Coastguard Worker }
103*03ce13f7SAndroid Build Coastguard Worker
104*03ce13f7SAndroid Build Coastguard Worker ////////////////////////////////////////////////////////////////////////////////
105*03ce13f7SAndroid Build Coastguard Worker // ServerEventBroadcaster
106*03ce13f7SAndroid Build Coastguard Worker ////////////////////////////////////////////////////////////////////////////////
107*03ce13f7SAndroid Build Coastguard Worker class ServerEventBroadcaster : public Broadcaster<vk::dbg::ServerEventListener>
108*03ce13f7SAndroid Build Coastguard Worker {
109*03ce13f7SAndroid Build Coastguard Worker public:
110*03ce13f7SAndroid Build Coastguard Worker using Thread = vk::dbg::Thread;
111*03ce13f7SAndroid Build Coastguard Worker
onThreadStarted(Thread::ID id)112*03ce13f7SAndroid Build Coastguard Worker void onThreadStarted(Thread::ID id) override
113*03ce13f7SAndroid Build Coastguard Worker {
114*03ce13f7SAndroid Build Coastguard Worker foreach([&](auto *l) { l->onThreadStarted(id); });
115*03ce13f7SAndroid Build Coastguard Worker }
116*03ce13f7SAndroid Build Coastguard Worker
onThreadStepped(Thread::ID id)117*03ce13f7SAndroid Build Coastguard Worker void onThreadStepped(Thread::ID id) override
118*03ce13f7SAndroid Build Coastguard Worker {
119*03ce13f7SAndroid Build Coastguard Worker foreach([&](auto *l) { l->onThreadStepped(id); });
120*03ce13f7SAndroid Build Coastguard Worker }
121*03ce13f7SAndroid Build Coastguard Worker
onLineBreakpointHit(Thread::ID id)122*03ce13f7SAndroid Build Coastguard Worker void onLineBreakpointHit(Thread::ID id) override
123*03ce13f7SAndroid Build Coastguard Worker {
124*03ce13f7SAndroid Build Coastguard Worker foreach([&](auto *l) { l->onLineBreakpointHit(id); });
125*03ce13f7SAndroid Build Coastguard Worker }
126*03ce13f7SAndroid Build Coastguard Worker
onFunctionBreakpointHit(Thread::ID id)127*03ce13f7SAndroid Build Coastguard Worker void onFunctionBreakpointHit(Thread::ID id) override
128*03ce13f7SAndroid Build Coastguard Worker {
129*03ce13f7SAndroid Build Coastguard Worker foreach([&](auto *l) { l->onFunctionBreakpointHit(id); });
130*03ce13f7SAndroid Build Coastguard Worker }
131*03ce13f7SAndroid Build Coastguard Worker };
132*03ce13f7SAndroid Build Coastguard Worker
133*03ce13f7SAndroid Build Coastguard Worker ////////////////////////////////////////////////////////////////////////////////
134*03ce13f7SAndroid Build Coastguard Worker // ClientEventBroadcaster
135*03ce13f7SAndroid Build Coastguard Worker ////////////////////////////////////////////////////////////////////////////////
136*03ce13f7SAndroid Build Coastguard Worker class ClientEventBroadcaster : public Broadcaster<vk::dbg::ClientEventListener>
137*03ce13f7SAndroid Build Coastguard Worker {
138*03ce13f7SAndroid Build Coastguard Worker public:
onSetBreakpoint(const vk::dbg::Location & location,bool & handled)139*03ce13f7SAndroid Build Coastguard Worker void onSetBreakpoint(const vk::dbg::Location &location, bool &handled) override
140*03ce13f7SAndroid Build Coastguard Worker {
141*03ce13f7SAndroid Build Coastguard Worker foreach([&](auto *l) { l->onSetBreakpoint(location, handled); });
142*03ce13f7SAndroid Build Coastguard Worker }
143*03ce13f7SAndroid Build Coastguard Worker
onSetBreakpoint(const std::string & func,bool & handled)144*03ce13f7SAndroid Build Coastguard Worker void onSetBreakpoint(const std::string &func, bool &handled) override
145*03ce13f7SAndroid Build Coastguard Worker {
146*03ce13f7SAndroid Build Coastguard Worker foreach([&](auto *l) { l->onSetBreakpoint(func, handled); });
147*03ce13f7SAndroid Build Coastguard Worker }
148*03ce13f7SAndroid Build Coastguard Worker
onBreakpointsChanged()149*03ce13f7SAndroid Build Coastguard Worker void onBreakpointsChanged() override
150*03ce13f7SAndroid Build Coastguard Worker {
151*03ce13f7SAndroid Build Coastguard Worker foreach([&](auto *l) { l->onBreakpointsChanged(); });
152*03ce13f7SAndroid Build Coastguard Worker }
153*03ce13f7SAndroid Build Coastguard Worker };
154*03ce13f7SAndroid Build Coastguard Worker
155*03ce13f7SAndroid Build Coastguard Worker } // namespace
156*03ce13f7SAndroid Build Coastguard Worker
157*03ce13f7SAndroid Build Coastguard Worker namespace vk {
158*03ce13f7SAndroid Build Coastguard Worker namespace dbg {
159*03ce13f7SAndroid Build Coastguard Worker
160*03ce13f7SAndroid Build Coastguard Worker ////////////////////////////////////////////////////////////////////////////////
161*03ce13f7SAndroid Build Coastguard Worker // Context::Impl
162*03ce13f7SAndroid Build Coastguard Worker ////////////////////////////////////////////////////////////////////////////////
163*03ce13f7SAndroid Build Coastguard Worker class Context::Impl : public Context
164*03ce13f7SAndroid Build Coastguard Worker {
165*03ce13f7SAndroid Build Coastguard Worker public:
166*03ce13f7SAndroid Build Coastguard Worker // Context compliance
167*03ce13f7SAndroid Build Coastguard Worker Lock lock() override;
168*03ce13f7SAndroid Build Coastguard Worker void addListener(ClientEventListener *) override;
169*03ce13f7SAndroid Build Coastguard Worker void removeListener(ClientEventListener *) override;
170*03ce13f7SAndroid Build Coastguard Worker ClientEventListener *clientEventBroadcast() override;
171*03ce13f7SAndroid Build Coastguard Worker void addListener(ServerEventListener *) override;
172*03ce13f7SAndroid Build Coastguard Worker void removeListener(ServerEventListener *) override;
173*03ce13f7SAndroid Build Coastguard Worker ServerEventListener *serverEventBroadcast() override;
174*03ce13f7SAndroid Build Coastguard Worker
175*03ce13f7SAndroid Build Coastguard Worker void addFile(const std::shared_ptr<File> &file);
176*03ce13f7SAndroid Build Coastguard Worker
177*03ce13f7SAndroid Build Coastguard Worker ServerEventBroadcaster serverEventBroadcaster;
178*03ce13f7SAndroid Build Coastguard Worker ClientEventBroadcaster clientEventBroadcaster;
179*03ce13f7SAndroid Build Coastguard Worker
180*03ce13f7SAndroid Build Coastguard Worker std::mutex mutex;
181*03ce13f7SAndroid Build Coastguard Worker std::unordered_map<std::thread::id, std::shared_ptr<Thread>> threadsByStdId;
182*03ce13f7SAndroid Build Coastguard Worker std::unordered_set<std::string> functionBreakpoints;
183*03ce13f7SAndroid Build Coastguard Worker std::unordered_map<std::string, std::vector<int>> pendingBreakpoints;
184*03ce13f7SAndroid Build Coastguard Worker WeakMap<Thread::ID, Thread> threads;
185*03ce13f7SAndroid Build Coastguard Worker WeakMap<File::ID, File> files;
186*03ce13f7SAndroid Build Coastguard Worker WeakMap<Frame::ID, Frame> frames;
187*03ce13f7SAndroid Build Coastguard Worker WeakMap<Scope::ID, Scope> scopes;
188*03ce13f7SAndroid Build Coastguard Worker WeakMap<Variables::ID, Variables> variables;
189*03ce13f7SAndroid Build Coastguard Worker Thread::ID nextThreadID = 1;
190*03ce13f7SAndroid Build Coastguard Worker File::ID nextFileID = 1;
191*03ce13f7SAndroid Build Coastguard Worker Frame::ID nextFrameID = 1;
192*03ce13f7SAndroid Build Coastguard Worker Scope::ID nextScopeID = 1;
193*03ce13f7SAndroid Build Coastguard Worker };
194*03ce13f7SAndroid Build Coastguard Worker
lock()195*03ce13f7SAndroid Build Coastguard Worker Context::Lock Context::Impl::lock()
196*03ce13f7SAndroid Build Coastguard Worker {
197*03ce13f7SAndroid Build Coastguard Worker return Lock(this);
198*03ce13f7SAndroid Build Coastguard Worker }
199*03ce13f7SAndroid Build Coastguard Worker
addListener(ClientEventListener * l)200*03ce13f7SAndroid Build Coastguard Worker void Context::Impl::addListener(ClientEventListener *l)
201*03ce13f7SAndroid Build Coastguard Worker {
202*03ce13f7SAndroid Build Coastguard Worker clientEventBroadcaster.add(l);
203*03ce13f7SAndroid Build Coastguard Worker }
204*03ce13f7SAndroid Build Coastguard Worker
removeListener(ClientEventListener * l)205*03ce13f7SAndroid Build Coastguard Worker void Context::Impl::removeListener(ClientEventListener *l)
206*03ce13f7SAndroid Build Coastguard Worker {
207*03ce13f7SAndroid Build Coastguard Worker clientEventBroadcaster.remove(l);
208*03ce13f7SAndroid Build Coastguard Worker }
209*03ce13f7SAndroid Build Coastguard Worker
clientEventBroadcast()210*03ce13f7SAndroid Build Coastguard Worker ClientEventListener *Context::Impl::clientEventBroadcast()
211*03ce13f7SAndroid Build Coastguard Worker {
212*03ce13f7SAndroid Build Coastguard Worker return &clientEventBroadcaster;
213*03ce13f7SAndroid Build Coastguard Worker }
214*03ce13f7SAndroid Build Coastguard Worker
addListener(ServerEventListener * l)215*03ce13f7SAndroid Build Coastguard Worker void Context::Impl::addListener(ServerEventListener *l)
216*03ce13f7SAndroid Build Coastguard Worker {
217*03ce13f7SAndroid Build Coastguard Worker serverEventBroadcaster.add(l);
218*03ce13f7SAndroid Build Coastguard Worker }
219*03ce13f7SAndroid Build Coastguard Worker
removeListener(ServerEventListener * l)220*03ce13f7SAndroid Build Coastguard Worker void Context::Impl::removeListener(ServerEventListener *l)
221*03ce13f7SAndroid Build Coastguard Worker {
222*03ce13f7SAndroid Build Coastguard Worker serverEventBroadcaster.remove(l);
223*03ce13f7SAndroid Build Coastguard Worker }
224*03ce13f7SAndroid Build Coastguard Worker
serverEventBroadcast()225*03ce13f7SAndroid Build Coastguard Worker ServerEventListener *Context::Impl::serverEventBroadcast()
226*03ce13f7SAndroid Build Coastguard Worker {
227*03ce13f7SAndroid Build Coastguard Worker return &serverEventBroadcaster;
228*03ce13f7SAndroid Build Coastguard Worker }
229*03ce13f7SAndroid Build Coastguard Worker
addFile(const std::shared_ptr<File> & file)230*03ce13f7SAndroid Build Coastguard Worker void Context::Impl::addFile(const std::shared_ptr<File> &file)
231*03ce13f7SAndroid Build Coastguard Worker {
232*03ce13f7SAndroid Build Coastguard Worker files.add(file->id, file);
233*03ce13f7SAndroid Build Coastguard Worker
234*03ce13f7SAndroid Build Coastguard Worker auto it = pendingBreakpoints.find(file->name);
235*03ce13f7SAndroid Build Coastguard Worker if(it != pendingBreakpoints.end())
236*03ce13f7SAndroid Build Coastguard Worker {
237*03ce13f7SAndroid Build Coastguard Worker for(auto line : it->second)
238*03ce13f7SAndroid Build Coastguard Worker {
239*03ce13f7SAndroid Build Coastguard Worker file->addBreakpoint(line);
240*03ce13f7SAndroid Build Coastguard Worker }
241*03ce13f7SAndroid Build Coastguard Worker }
242*03ce13f7SAndroid Build Coastguard Worker }
243*03ce13f7SAndroid Build Coastguard Worker
244*03ce13f7SAndroid Build Coastguard Worker ////////////////////////////////////////////////////////////////////////////////
245*03ce13f7SAndroid Build Coastguard Worker // Context
246*03ce13f7SAndroid Build Coastguard Worker ////////////////////////////////////////////////////////////////////////////////
create()247*03ce13f7SAndroid Build Coastguard Worker std::shared_ptr<Context> Context::create()
248*03ce13f7SAndroid Build Coastguard Worker {
249*03ce13f7SAndroid Build Coastguard Worker return std::shared_ptr<Context>(new Context::Impl());
250*03ce13f7SAndroid Build Coastguard Worker }
251*03ce13f7SAndroid Build Coastguard Worker
252*03ce13f7SAndroid Build Coastguard Worker ////////////////////////////////////////////////////////////////////////////////
253*03ce13f7SAndroid Build Coastguard Worker // Context::Lock
254*03ce13f7SAndroid Build Coastguard Worker ////////////////////////////////////////////////////////////////////////////////
Lock(Impl * ctx)255*03ce13f7SAndroid Build Coastguard Worker Context::Lock::Lock(Impl *ctx)
256*03ce13f7SAndroid Build Coastguard Worker : ctx(ctx)
257*03ce13f7SAndroid Build Coastguard Worker {
258*03ce13f7SAndroid Build Coastguard Worker #if CHECK_REENTRANT_CONTEXT_LOCKS
259*03ce13f7SAndroid Build Coastguard Worker ASSERT_MSG(contextsWithLock.count(ctx) == 0, "Attempting to acquire Context lock twice on same thread. This will deadlock");
260*03ce13f7SAndroid Build Coastguard Worker contextsWithLock.emplace(ctx);
261*03ce13f7SAndroid Build Coastguard Worker #endif
262*03ce13f7SAndroid Build Coastguard Worker ctx->mutex.lock();
263*03ce13f7SAndroid Build Coastguard Worker }
264*03ce13f7SAndroid Build Coastguard Worker
Lock(Lock && o)265*03ce13f7SAndroid Build Coastguard Worker Context::Lock::Lock(Lock &&o)
266*03ce13f7SAndroid Build Coastguard Worker : ctx(o.ctx)
267*03ce13f7SAndroid Build Coastguard Worker {
268*03ce13f7SAndroid Build Coastguard Worker o.ctx = nullptr;
269*03ce13f7SAndroid Build Coastguard Worker }
270*03ce13f7SAndroid Build Coastguard Worker
~Lock()271*03ce13f7SAndroid Build Coastguard Worker Context::Lock::~Lock()
272*03ce13f7SAndroid Build Coastguard Worker {
273*03ce13f7SAndroid Build Coastguard Worker unlock();
274*03ce13f7SAndroid Build Coastguard Worker }
275*03ce13f7SAndroid Build Coastguard Worker
operator =(Lock && o)276*03ce13f7SAndroid Build Coastguard Worker Context::Lock &Context::Lock::operator=(Lock &&o)
277*03ce13f7SAndroid Build Coastguard Worker {
278*03ce13f7SAndroid Build Coastguard Worker ctx = o.ctx;
279*03ce13f7SAndroid Build Coastguard Worker o.ctx = nullptr;
280*03ce13f7SAndroid Build Coastguard Worker return *this;
281*03ce13f7SAndroid Build Coastguard Worker }
282*03ce13f7SAndroid Build Coastguard Worker
unlock()283*03ce13f7SAndroid Build Coastguard Worker void Context::Lock::unlock()
284*03ce13f7SAndroid Build Coastguard Worker {
285*03ce13f7SAndroid Build Coastguard Worker if(ctx)
286*03ce13f7SAndroid Build Coastguard Worker {
287*03ce13f7SAndroid Build Coastguard Worker #if CHECK_REENTRANT_CONTEXT_LOCKS
288*03ce13f7SAndroid Build Coastguard Worker contextsWithLock.erase(ctx);
289*03ce13f7SAndroid Build Coastguard Worker #endif
290*03ce13f7SAndroid Build Coastguard Worker
291*03ce13f7SAndroid Build Coastguard Worker ctx->mutex.unlock();
292*03ce13f7SAndroid Build Coastguard Worker ctx = nullptr;
293*03ce13f7SAndroid Build Coastguard Worker }
294*03ce13f7SAndroid Build Coastguard Worker }
295*03ce13f7SAndroid Build Coastguard Worker
currentThread()296*03ce13f7SAndroid Build Coastguard Worker std::shared_ptr<Thread> Context::Lock::currentThread()
297*03ce13f7SAndroid Build Coastguard Worker {
298*03ce13f7SAndroid Build Coastguard Worker auto threadIt = ctx->threadsByStdId.find(std::this_thread::get_id());
299*03ce13f7SAndroid Build Coastguard Worker if(threadIt != ctx->threadsByStdId.end())
300*03ce13f7SAndroid Build Coastguard Worker {
301*03ce13f7SAndroid Build Coastguard Worker return threadIt->second;
302*03ce13f7SAndroid Build Coastguard Worker }
303*03ce13f7SAndroid Build Coastguard Worker auto id = ++ctx->nextThreadID;
304*03ce13f7SAndroid Build Coastguard Worker char name[256];
305*03ce13f7SAndroid Build Coastguard Worker snprintf(name, sizeof(name), "Thread<0x%x>", id.value());
306*03ce13f7SAndroid Build Coastguard Worker
307*03ce13f7SAndroid Build Coastguard Worker auto thread = std::make_shared<Thread>(id, ctx);
308*03ce13f7SAndroid Build Coastguard Worker ctx->threads.add(id, thread);
309*03ce13f7SAndroid Build Coastguard Worker thread->setName(name);
310*03ce13f7SAndroid Build Coastguard Worker ctx->threadsByStdId.emplace(std::this_thread::get_id(), thread);
311*03ce13f7SAndroid Build Coastguard Worker
312*03ce13f7SAndroid Build Coastguard Worker ctx->serverEventBroadcast()->onThreadStarted(id);
313*03ce13f7SAndroid Build Coastguard Worker
314*03ce13f7SAndroid Build Coastguard Worker return thread;
315*03ce13f7SAndroid Build Coastguard Worker }
316*03ce13f7SAndroid Build Coastguard Worker
get(Thread::ID id)317*03ce13f7SAndroid Build Coastguard Worker std::shared_ptr<Thread> Context::Lock::get(Thread::ID id)
318*03ce13f7SAndroid Build Coastguard Worker {
319*03ce13f7SAndroid Build Coastguard Worker return ctx->threads.get(id);
320*03ce13f7SAndroid Build Coastguard Worker }
321*03ce13f7SAndroid Build Coastguard Worker
threads()322*03ce13f7SAndroid Build Coastguard Worker std::vector<std::shared_ptr<Thread>> Context::Lock::threads()
323*03ce13f7SAndroid Build Coastguard Worker {
324*03ce13f7SAndroid Build Coastguard Worker std::vector<std::shared_ptr<Thread>> out;
325*03ce13f7SAndroid Build Coastguard Worker out.reserve(ctx->threads.approx_size());
326*03ce13f7SAndroid Build Coastguard Worker for(auto it : ctx->threads)
327*03ce13f7SAndroid Build Coastguard Worker {
328*03ce13f7SAndroid Build Coastguard Worker out.push_back(it.second);
329*03ce13f7SAndroid Build Coastguard Worker }
330*03ce13f7SAndroid Build Coastguard Worker return out;
331*03ce13f7SAndroid Build Coastguard Worker }
332*03ce13f7SAndroid Build Coastguard Worker
createVirtualFile(const std::string & name,const std::string & source)333*03ce13f7SAndroid Build Coastguard Worker std::shared_ptr<File> Context::Lock::createVirtualFile(const std::string &name,
334*03ce13f7SAndroid Build Coastguard Worker const std::string &source)
335*03ce13f7SAndroid Build Coastguard Worker {
336*03ce13f7SAndroid Build Coastguard Worker auto file = File::createVirtual(ctx->nextFileID++, name, source);
337*03ce13f7SAndroid Build Coastguard Worker ctx->addFile(file);
338*03ce13f7SAndroid Build Coastguard Worker return file;
339*03ce13f7SAndroid Build Coastguard Worker }
340*03ce13f7SAndroid Build Coastguard Worker
createPhysicalFile(const std::string & path)341*03ce13f7SAndroid Build Coastguard Worker std::shared_ptr<File> Context::Lock::createPhysicalFile(const std::string &path)
342*03ce13f7SAndroid Build Coastguard Worker {
343*03ce13f7SAndroid Build Coastguard Worker auto file = File::createPhysical(ctx->nextFileID++, path);
344*03ce13f7SAndroid Build Coastguard Worker ctx->addFile(file);
345*03ce13f7SAndroid Build Coastguard Worker return file;
346*03ce13f7SAndroid Build Coastguard Worker }
347*03ce13f7SAndroid Build Coastguard Worker
get(File::ID id)348*03ce13f7SAndroid Build Coastguard Worker std::shared_ptr<File> Context::Lock::get(File::ID id)
349*03ce13f7SAndroid Build Coastguard Worker {
350*03ce13f7SAndroid Build Coastguard Worker return ctx->files.get(id);
351*03ce13f7SAndroid Build Coastguard Worker }
352*03ce13f7SAndroid Build Coastguard Worker
findFile(const std::string & path)353*03ce13f7SAndroid Build Coastguard Worker std::shared_ptr<File> Context::Lock::findFile(const std::string &path)
354*03ce13f7SAndroid Build Coastguard Worker {
355*03ce13f7SAndroid Build Coastguard Worker for(auto it : ctx->files)
356*03ce13f7SAndroid Build Coastguard Worker {
357*03ce13f7SAndroid Build Coastguard Worker auto &file = it.second;
358*03ce13f7SAndroid Build Coastguard Worker if(file->path() == path)
359*03ce13f7SAndroid Build Coastguard Worker {
360*03ce13f7SAndroid Build Coastguard Worker return file;
361*03ce13f7SAndroid Build Coastguard Worker }
362*03ce13f7SAndroid Build Coastguard Worker }
363*03ce13f7SAndroid Build Coastguard Worker return nullptr;
364*03ce13f7SAndroid Build Coastguard Worker }
365*03ce13f7SAndroid Build Coastguard Worker
files()366*03ce13f7SAndroid Build Coastguard Worker std::vector<std::shared_ptr<File>> Context::Lock::files()
367*03ce13f7SAndroid Build Coastguard Worker {
368*03ce13f7SAndroid Build Coastguard Worker std::vector<std::shared_ptr<File>> out;
369*03ce13f7SAndroid Build Coastguard Worker out.reserve(ctx->files.approx_size());
370*03ce13f7SAndroid Build Coastguard Worker for(auto it : ctx->files)
371*03ce13f7SAndroid Build Coastguard Worker {
372*03ce13f7SAndroid Build Coastguard Worker out.push_back(it.second);
373*03ce13f7SAndroid Build Coastguard Worker }
374*03ce13f7SAndroid Build Coastguard Worker return out;
375*03ce13f7SAndroid Build Coastguard Worker }
376*03ce13f7SAndroid Build Coastguard Worker
createFrame(const std::shared_ptr<File> & file,std::string function)377*03ce13f7SAndroid Build Coastguard Worker std::shared_ptr<Frame> Context::Lock::createFrame(
378*03ce13f7SAndroid Build Coastguard Worker const std::shared_ptr<File> &file, std::string function)
379*03ce13f7SAndroid Build Coastguard Worker {
380*03ce13f7SAndroid Build Coastguard Worker auto frame = std::make_shared<Frame>(ctx->nextFrameID++, std::move(function));
381*03ce13f7SAndroid Build Coastguard Worker ctx->frames.add(frame->id, frame);
382*03ce13f7SAndroid Build Coastguard Worker frame->arguments = createScope(file);
383*03ce13f7SAndroid Build Coastguard Worker frame->locals = createScope(file);
384*03ce13f7SAndroid Build Coastguard Worker frame->registers = createScope(file);
385*03ce13f7SAndroid Build Coastguard Worker frame->hovers = createScope(file);
386*03ce13f7SAndroid Build Coastguard Worker frame->location.file = file;
387*03ce13f7SAndroid Build Coastguard Worker return frame;
388*03ce13f7SAndroid Build Coastguard Worker }
389*03ce13f7SAndroid Build Coastguard Worker
get(Frame::ID id)390*03ce13f7SAndroid Build Coastguard Worker std::shared_ptr<Frame> Context::Lock::get(Frame::ID id)
391*03ce13f7SAndroid Build Coastguard Worker {
392*03ce13f7SAndroid Build Coastguard Worker return ctx->frames.get(id);
393*03ce13f7SAndroid Build Coastguard Worker }
394*03ce13f7SAndroid Build Coastguard Worker
createScope(const std::shared_ptr<File> & file)395*03ce13f7SAndroid Build Coastguard Worker std::shared_ptr<Scope> Context::Lock::createScope(
396*03ce13f7SAndroid Build Coastguard Worker const std::shared_ptr<File> &file)
397*03ce13f7SAndroid Build Coastguard Worker {
398*03ce13f7SAndroid Build Coastguard Worker auto scope = std::make_shared<Scope>(ctx->nextScopeID++, file, std::make_shared<VariableContainer>());
399*03ce13f7SAndroid Build Coastguard Worker ctx->scopes.add(scope->id, scope);
400*03ce13f7SAndroid Build Coastguard Worker return scope;
401*03ce13f7SAndroid Build Coastguard Worker }
402*03ce13f7SAndroid Build Coastguard Worker
get(Scope::ID id)403*03ce13f7SAndroid Build Coastguard Worker std::shared_ptr<Scope> Context::Lock::get(Scope::ID id)
404*03ce13f7SAndroid Build Coastguard Worker {
405*03ce13f7SAndroid Build Coastguard Worker return ctx->scopes.get(id);
406*03ce13f7SAndroid Build Coastguard Worker }
407*03ce13f7SAndroid Build Coastguard Worker
track(const std::shared_ptr<Variables> & vars)408*03ce13f7SAndroid Build Coastguard Worker void Context::Lock::track(const std::shared_ptr<Variables> &vars)
409*03ce13f7SAndroid Build Coastguard Worker {
410*03ce13f7SAndroid Build Coastguard Worker ctx->variables.add(vars->id, vars);
411*03ce13f7SAndroid Build Coastguard Worker }
412*03ce13f7SAndroid Build Coastguard Worker
get(Variables::ID id)413*03ce13f7SAndroid Build Coastguard Worker std::shared_ptr<Variables> Context::Lock::get(Variables::ID id)
414*03ce13f7SAndroid Build Coastguard Worker {
415*03ce13f7SAndroid Build Coastguard Worker return ctx->variables.get(id);
416*03ce13f7SAndroid Build Coastguard Worker }
417*03ce13f7SAndroid Build Coastguard Worker
clearFunctionBreakpoints()418*03ce13f7SAndroid Build Coastguard Worker void Context::Lock::clearFunctionBreakpoints()
419*03ce13f7SAndroid Build Coastguard Worker {
420*03ce13f7SAndroid Build Coastguard Worker ctx->functionBreakpoints.clear();
421*03ce13f7SAndroid Build Coastguard Worker }
422*03ce13f7SAndroid Build Coastguard Worker
addFunctionBreakpoint(const std::string & name)423*03ce13f7SAndroid Build Coastguard Worker void Context::Lock::addFunctionBreakpoint(const std::string &name)
424*03ce13f7SAndroid Build Coastguard Worker {
425*03ce13f7SAndroid Build Coastguard Worker ctx->functionBreakpoints.emplace(name);
426*03ce13f7SAndroid Build Coastguard Worker }
427*03ce13f7SAndroid Build Coastguard Worker
addPendingBreakpoints(const std::string & filename,const std::vector<int> & lines)428*03ce13f7SAndroid Build Coastguard Worker void Context::Lock::addPendingBreakpoints(const std::string &filename, const std::vector<int> &lines)
429*03ce13f7SAndroid Build Coastguard Worker {
430*03ce13f7SAndroid Build Coastguard Worker ctx->pendingBreakpoints.emplace(filename, lines);
431*03ce13f7SAndroid Build Coastguard Worker }
432*03ce13f7SAndroid Build Coastguard Worker
isFunctionBreakpoint(const std::string & name)433*03ce13f7SAndroid Build Coastguard Worker bool Context::Lock::isFunctionBreakpoint(const std::string &name)
434*03ce13f7SAndroid Build Coastguard Worker {
435*03ce13f7SAndroid Build Coastguard Worker return ctx->functionBreakpoints.count(name) > 0;
436*03ce13f7SAndroid Build Coastguard Worker }
437*03ce13f7SAndroid Build Coastguard Worker
getFunctionBreakpoints()438*03ce13f7SAndroid Build Coastguard Worker std::unordered_set<std::string> Context::Lock::getFunctionBreakpoints()
439*03ce13f7SAndroid Build Coastguard Worker {
440*03ce13f7SAndroid Build Coastguard Worker return ctx->functionBreakpoints;
441*03ce13f7SAndroid Build Coastguard Worker }
442*03ce13f7SAndroid Build Coastguard Worker
443*03ce13f7SAndroid Build Coastguard Worker } // namespace dbg
444*03ce13f7SAndroid Build Coastguard Worker } // namespace vk
445