]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/lldb/source/Core/Listener.cpp
Import OpenCSD -- an ARM CoreSight(tm) Trace Decode Library.
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / lldb / source / Core / Listener.cpp
1 //===-- Listener.cpp --------------------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #include "lldb/Core/Listener.h"
11
12 #include "lldb/Core/Broadcaster.h"
13 #include "lldb/Core/Event.h"
14 #include "lldb/Utility/ConstString.h" // for ConstString
15 #include "lldb/Utility/Log.h"
16 #include "lldb/Utility/Logging.h" // for GetLogIfAllCategoriesSet, LIBL...
17
18 #include "llvm/ADT/Optional.h" // for Optional
19
20 #include <algorithm>
21 #include <memory>  // for make_shared
22 #include <utility> // for pair, make_pair
23
24 using namespace lldb;
25 using namespace lldb_private;
26
27 namespace {
28 class BroadcasterManagerWPMatcher {
29 public:
30   BroadcasterManagerWPMatcher(BroadcasterManagerSP manager_sp)
31       : m_manager_sp(manager_sp) {}
32   bool operator()(const BroadcasterManagerWP input_wp) const {
33     BroadcasterManagerSP input_sp = input_wp.lock();
34     return (input_sp && input_sp == m_manager_sp);
35   }
36
37   BroadcasterManagerSP m_manager_sp;
38 };
39 } // anonymous namespace
40
41 Listener::Listener(const char *name)
42     : m_name(name), m_broadcasters(), m_broadcasters_mutex(), m_events(),
43       m_events_mutex() {
44   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OBJECT));
45   if (log != nullptr)
46     log->Printf("%p Listener::Listener('%s')", static_cast<void *>(this),
47                 m_name.c_str());
48 }
49
50 Listener::~Listener() {
51   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OBJECT));
52
53   Clear();
54
55   if (log)
56     log->Printf("%p Listener::%s('%s')", static_cast<void *>(this),
57                 __FUNCTION__, m_name.c_str());
58 }
59
60 void Listener::Clear() {
61   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OBJECT));
62   std::lock_guard<std::recursive_mutex> broadcasters_guard(
63       m_broadcasters_mutex);
64   broadcaster_collection::iterator pos, end = m_broadcasters.end();
65   for (pos = m_broadcasters.begin(); pos != end; ++pos) {
66     Broadcaster::BroadcasterImplSP broadcaster_sp(pos->first.lock());
67     if (broadcaster_sp)
68       broadcaster_sp->RemoveListener(this, pos->second.event_mask);
69   }
70   m_broadcasters.clear();
71
72   std::lock_guard<std::mutex> events_guard(m_events_mutex);
73   m_events.clear();
74   size_t num_managers = m_broadcaster_managers.size();
75
76   for (size_t i = 0; i < num_managers; i++) {
77     BroadcasterManagerSP manager_sp(m_broadcaster_managers[i].lock());
78     if (manager_sp)
79       manager_sp->RemoveListener(this);
80   }
81
82   if (log)
83     log->Printf("%p Listener::%s('%s')", static_cast<void *>(this),
84                 __FUNCTION__, m_name.c_str());
85 }
86
87 uint32_t Listener::StartListeningForEvents(Broadcaster *broadcaster,
88                                            uint32_t event_mask) {
89   if (broadcaster) {
90     // Scope for "locker"
91     // Tell the broadcaster to add this object as a listener
92     {
93       std::lock_guard<std::recursive_mutex> broadcasters_guard(
94           m_broadcasters_mutex);
95       Broadcaster::BroadcasterImplWP impl_wp(broadcaster->GetBroadcasterImpl());
96       m_broadcasters.insert(
97           std::make_pair(impl_wp, BroadcasterInfo(event_mask)));
98     }
99
100     uint32_t acquired_mask =
101         broadcaster->AddListener(this->shared_from_this(), event_mask);
102
103     Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EVENTS));
104     if (log != nullptr)
105       log->Printf("%p Listener::StartListeningForEvents (broadcaster = %p, "
106                   "mask = 0x%8.8x) acquired_mask = 0x%8.8x for %s",
107                   static_cast<void *>(this), static_cast<void *>(broadcaster),
108                   event_mask, acquired_mask, m_name.c_str());
109
110     return acquired_mask;
111   }
112   return 0;
113 }
114
115 uint32_t Listener::StartListeningForEvents(Broadcaster *broadcaster,
116                                            uint32_t event_mask,
117                                            HandleBroadcastCallback callback,
118                                            void *callback_user_data) {
119   if (broadcaster) {
120     // Scope for "locker"
121     // Tell the broadcaster to add this object as a listener
122     {
123       std::lock_guard<std::recursive_mutex> broadcasters_guard(
124           m_broadcasters_mutex);
125       Broadcaster::BroadcasterImplWP impl_wp(broadcaster->GetBroadcasterImpl());
126       m_broadcasters.insert(std::make_pair(
127           impl_wp, BroadcasterInfo(event_mask, callback, callback_user_data)));
128     }
129
130     uint32_t acquired_mask =
131         broadcaster->AddListener(this->shared_from_this(), event_mask);
132
133     Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EVENTS));
134     if (log != nullptr) {
135       void **pointer = reinterpret_cast<void **>(&callback);
136       log->Printf("%p Listener::StartListeningForEvents (broadcaster = %p, "
137                   "mask = 0x%8.8x, callback = %p, user_data = %p) "
138                   "acquired_mask = 0x%8.8x for %s",
139                   static_cast<void *>(this), static_cast<void *>(broadcaster),
140                   event_mask, *pointer, static_cast<void *>(callback_user_data),
141                   acquired_mask, m_name.c_str());
142     }
143
144     return acquired_mask;
145   }
146   return 0;
147 }
148
149 bool Listener::StopListeningForEvents(Broadcaster *broadcaster,
150                                       uint32_t event_mask) {
151   if (broadcaster) {
152     // Scope for "locker"
153     {
154       std::lock_guard<std::recursive_mutex> broadcasters_guard(
155           m_broadcasters_mutex);
156       m_broadcasters.erase(broadcaster->GetBroadcasterImpl());
157     }
158     // Remove the broadcaster from our set of broadcasters
159     return broadcaster->RemoveListener(this->shared_from_this(), event_mask);
160   }
161
162   return false;
163 }
164
165 // Called when a Broadcaster is in its destructor. We need to remove all
166 // knowledge of this broadcaster and any events that it may have queued up
167 void Listener::BroadcasterWillDestruct(Broadcaster *broadcaster) {
168   // Scope for "broadcasters_locker"
169   {
170     std::lock_guard<std::recursive_mutex> broadcasters_guard(
171         m_broadcasters_mutex);
172     m_broadcasters.erase(broadcaster->GetBroadcasterImpl());
173   }
174
175   // Scope for "event_locker"
176   {
177     std::lock_guard<std::mutex> events_guard(m_events_mutex);
178     // Remove all events for this broadcaster object.
179     event_collection::iterator pos = m_events.begin();
180     while (pos != m_events.end()) {
181       if ((*pos)->GetBroadcaster() == broadcaster)
182         pos = m_events.erase(pos);
183       else
184         ++pos;
185     }
186   }
187 }
188
189 void Listener::BroadcasterManagerWillDestruct(BroadcasterManagerSP manager_sp) {
190   // Just need to remove this broadcast manager from the list of managers:
191   broadcaster_manager_collection::iterator iter,
192       end_iter = m_broadcaster_managers.end();
193   BroadcasterManagerWP manager_wp;
194
195   BroadcasterManagerWPMatcher matcher(manager_sp);
196   iter = std::find_if<broadcaster_manager_collection::iterator,
197                       BroadcasterManagerWPMatcher>(
198       m_broadcaster_managers.begin(), end_iter, matcher);
199   if (iter != end_iter)
200     m_broadcaster_managers.erase(iter);
201 }
202
203 void Listener::AddEvent(EventSP &event_sp) {
204   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EVENTS));
205   if (log != nullptr)
206     log->Printf("%p Listener('%s')::AddEvent (event_sp = {%p})",
207                 static_cast<void *>(this), m_name.c_str(),
208                 static_cast<void *>(event_sp.get()));
209
210   std::lock_guard<std::mutex> guard(m_events_mutex);
211   m_events.push_back(event_sp);
212   m_events_condition.notify_all();
213 }
214
215 class EventBroadcasterMatches {
216 public:
217   EventBroadcasterMatches(Broadcaster *broadcaster)
218       : m_broadcaster(broadcaster) {}
219
220   bool operator()(const EventSP &event_sp) const {
221     return event_sp->BroadcasterIs(m_broadcaster);
222   }
223
224 private:
225   Broadcaster *m_broadcaster;
226 };
227
228 class EventMatcher {
229 public:
230   EventMatcher(Broadcaster *broadcaster, const ConstString *broadcaster_names,
231                uint32_t num_broadcaster_names, uint32_t event_type_mask)
232       : m_broadcaster(broadcaster), m_broadcaster_names(broadcaster_names),
233         m_num_broadcaster_names(num_broadcaster_names),
234         m_event_type_mask(event_type_mask) {}
235
236   bool operator()(const EventSP &event_sp) const {
237     if (m_broadcaster && !event_sp->BroadcasterIs(m_broadcaster))
238       return false;
239
240     if (m_broadcaster_names) {
241       bool found_source = false;
242       const ConstString &event_broadcaster_name =
243           event_sp->GetBroadcaster()->GetBroadcasterName();
244       for (uint32_t i = 0; i < m_num_broadcaster_names; ++i) {
245         if (m_broadcaster_names[i] == event_broadcaster_name) {
246           found_source = true;
247           break;
248         }
249       }
250       if (!found_source)
251         return false;
252     }
253
254     if (m_event_type_mask == 0 || m_event_type_mask & event_sp->GetType())
255       return true;
256     return false;
257   }
258
259 private:
260   Broadcaster *m_broadcaster;
261   const ConstString *m_broadcaster_names;
262   const uint32_t m_num_broadcaster_names;
263   const uint32_t m_event_type_mask;
264 };
265
266 bool Listener::FindNextEventInternal(
267     std::unique_lock<std::mutex> &lock,
268     Broadcaster *broadcaster,             // nullptr for any broadcaster
269     const ConstString *broadcaster_names, // nullptr for any event
270     uint32_t num_broadcaster_names, uint32_t event_type_mask, EventSP &event_sp,
271     bool remove) {
272   // NOTE: callers of this function must lock m_events_mutex using a
273   // Mutex::Locker
274   // and pass the locker as the first argument. m_events_mutex is no longer
275   // recursive.
276   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EVENTS));
277
278   if (m_events.empty())
279     return false;
280
281   Listener::event_collection::iterator pos = m_events.end();
282
283   if (broadcaster == nullptr && broadcaster_names == nullptr &&
284       event_type_mask == 0) {
285     pos = m_events.begin();
286   } else {
287     pos = std::find_if(m_events.begin(), m_events.end(),
288                        EventMatcher(broadcaster, broadcaster_names,
289                                     num_broadcaster_names, event_type_mask));
290   }
291
292   if (pos != m_events.end()) {
293     event_sp = *pos;
294
295     if (log != nullptr)
296       log->Printf("%p '%s' Listener::FindNextEventInternal(broadcaster=%p, "
297                   "broadcaster_names=%p[%u], event_type_mask=0x%8.8x, "
298                   "remove=%i) event %p",
299                   static_cast<void *>(this), GetName(),
300                   static_cast<void *>(broadcaster),
301                   static_cast<const void *>(broadcaster_names),
302                   num_broadcaster_names, event_type_mask, remove,
303                   static_cast<void *>(event_sp.get()));
304
305     if (remove) {
306       m_events.erase(pos);
307       // Unlock the event queue here.  We've removed this event and are about to
308       // return
309       // it so it should be okay to get the next event off the queue here - and
310       // it might
311       // be useful to do that in the "DoOnRemoval".
312       lock.unlock();
313       event_sp->DoOnRemoval();
314     }
315     return true;
316   }
317
318   event_sp.reset();
319   return false;
320 }
321
322 Event *Listener::PeekAtNextEvent() {
323   std::unique_lock<std::mutex> guard(m_events_mutex);
324   EventSP event_sp;
325   if (FindNextEventInternal(guard, nullptr, nullptr, 0, 0, event_sp, false))
326     return event_sp.get();
327   return nullptr;
328 }
329
330 Event *Listener::PeekAtNextEventForBroadcaster(Broadcaster *broadcaster) {
331   std::unique_lock<std::mutex> guard(m_events_mutex);
332   EventSP event_sp;
333   if (FindNextEventInternal(guard, broadcaster, nullptr, 0, 0, event_sp, false))
334     return event_sp.get();
335   return nullptr;
336 }
337
338 Event *
339 Listener::PeekAtNextEventForBroadcasterWithType(Broadcaster *broadcaster,
340                                                 uint32_t event_type_mask) {
341   std::unique_lock<std::mutex> guard(m_events_mutex);
342   EventSP event_sp;
343   if (FindNextEventInternal(guard, broadcaster, nullptr, 0, event_type_mask,
344                             event_sp, false))
345     return event_sp.get();
346   return nullptr;
347 }
348
349 bool Listener::GetEventInternal(
350     const Timeout<std::micro> &timeout,
351     Broadcaster *broadcaster,             // nullptr for any broadcaster
352     const ConstString *broadcaster_names, // nullptr for any event
353     uint32_t num_broadcaster_names, uint32_t event_type_mask,
354     EventSP &event_sp) {
355   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EVENTS));
356   LLDB_LOG(log, "this = {0}, timeout = {1} for {2}", this, timeout, m_name);
357
358   std::unique_lock<std::mutex> lock(m_events_mutex);
359
360   while (true) {
361     if (FindNextEventInternal(lock, broadcaster, broadcaster_names,
362                               num_broadcaster_names, event_type_mask, event_sp,
363                               true)) {
364       return true;
365     } else {
366       std::cv_status result = std::cv_status::no_timeout;
367       if (!timeout)
368         m_events_condition.wait(lock);
369       else
370         result = m_events_condition.wait_for(lock, *timeout);
371
372       if (result == std::cv_status::timeout) {
373         log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EVENTS);
374         if (log)
375           log->Printf("%p Listener::GetEventInternal() timed out for %s",
376                       static_cast<void *>(this), m_name.c_str());
377         return false;
378       } else if (result != std::cv_status::no_timeout) {
379         log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EVENTS);
380         if (log)
381           log->Printf("%p Listener::GetEventInternal() unknown error for %s",
382                       static_cast<void *>(this), m_name.c_str());
383         return false;
384       }
385     }
386   }
387
388   return false;
389 }
390
391 bool Listener::GetEventForBroadcasterWithType(
392     Broadcaster *broadcaster, uint32_t event_type_mask, EventSP &event_sp,
393     const Timeout<std::micro> &timeout) {
394   return GetEventInternal(timeout, broadcaster, nullptr, 0, event_type_mask,
395                           event_sp);
396 }
397
398 bool Listener::GetEventForBroadcaster(Broadcaster *broadcaster,
399                                       EventSP &event_sp,
400                                       const Timeout<std::micro> &timeout) {
401   return GetEventInternal(timeout, broadcaster, nullptr, 0, 0, event_sp);
402 }
403
404 bool Listener::GetEvent(EventSP &event_sp, const Timeout<std::micro> &timeout) {
405   return GetEventInternal(timeout, nullptr, nullptr, 0, 0, event_sp);
406 }
407
408 size_t Listener::HandleBroadcastEvent(EventSP &event_sp) {
409   size_t num_handled = 0;
410   std::lock_guard<std::recursive_mutex> guard(m_broadcasters_mutex);
411   Broadcaster *broadcaster = event_sp->GetBroadcaster();
412   if (!broadcaster)
413     return 0;
414   broadcaster_collection::iterator pos;
415   broadcaster_collection::iterator end = m_broadcasters.end();
416   Broadcaster::BroadcasterImplSP broadcaster_impl_sp(
417       broadcaster->GetBroadcasterImpl());
418   for (pos = m_broadcasters.find(broadcaster_impl_sp);
419        pos != end && pos->first.lock() == broadcaster_impl_sp; ++pos) {
420     BroadcasterInfo info = pos->second;
421     if (event_sp->GetType() & info.event_mask) {
422       if (info.callback != nullptr) {
423         info.callback(event_sp, info.callback_user_data);
424         ++num_handled;
425       }
426     }
427   }
428   return num_handled;
429 }
430
431 uint32_t
432 Listener::StartListeningForEventSpec(BroadcasterManagerSP manager_sp,
433                                      const BroadcastEventSpec &event_spec) {
434   if (!manager_sp)
435     return 0;
436
437   // The BroadcasterManager mutex must be locked before m_broadcasters_mutex
438   // to avoid violating the lock hierarchy (manager before broadcasters).
439   std::lock_guard<std::recursive_mutex> manager_guard(
440       manager_sp->m_manager_mutex);
441   std::lock_guard<std::recursive_mutex> guard(m_broadcasters_mutex);
442
443   uint32_t bits_acquired = manager_sp->RegisterListenerForEvents(
444       this->shared_from_this(), event_spec);
445   if (bits_acquired) {
446     broadcaster_manager_collection::iterator iter,
447         end_iter = m_broadcaster_managers.end();
448     BroadcasterManagerWP manager_wp(manager_sp);
449     BroadcasterManagerWPMatcher matcher(manager_sp);
450     iter = std::find_if<broadcaster_manager_collection::iterator,
451                         BroadcasterManagerWPMatcher>(
452         m_broadcaster_managers.begin(), end_iter, matcher);
453     if (iter == end_iter)
454       m_broadcaster_managers.push_back(manager_wp);
455   }
456
457   return bits_acquired;
458 }
459
460 bool Listener::StopListeningForEventSpec(BroadcasterManagerSP manager_sp,
461                                          const BroadcastEventSpec &event_spec) {
462   if (!manager_sp)
463     return false;
464
465   std::lock_guard<std::recursive_mutex> guard(m_broadcasters_mutex);
466   return manager_sp->UnregisterListenerForEvents(this->shared_from_this(),
467                                                  event_spec);
468 }
469
470 ListenerSP Listener::MakeListener(const char *name) {
471   return ListenerSP(new Listener(name));
472 }