]> CyberLeo.Net >> Repos - FreeBSD/releng/10.2.git/blob - contrib/llvm/tools/lldb/source/Core/Communication.cpp
- Copy stable/10@285827 to releng/10.2 in preparation for 10.2-RC1
[FreeBSD/releng/10.2.git] / contrib / llvm / tools / lldb / source / Core / Communication.cpp
1 //===-- Communication.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 // C Includes
11 // C++ Includes
12 // Other libraries and framework includes
13 // Project includes
14 #include "lldb/lldb-private-log.h"
15 #include "lldb/Core/Communication.h"
16 #include "lldb/Core/Connection.h"
17 #include "lldb/Core/Log.h"
18 #include "lldb/Core/Timer.h"
19 #include "lldb/Core/Event.h"
20 #include "lldb/Host/Host.h"
21 #include <string.h>
22
23 using namespace lldb;
24 using namespace lldb_private;
25
26 ConstString &
27 Communication::GetStaticBroadcasterClass ()
28 {
29     static ConstString class_name ("lldb.communication");
30     return class_name;
31 }
32
33 //----------------------------------------------------------------------
34 // Constructor
35 //----------------------------------------------------------------------
36 Communication::Communication(const char *name) :
37     Broadcaster (NULL, name),
38     m_connection_sp (),
39     m_read_thread (LLDB_INVALID_HOST_THREAD),
40     m_read_thread_enabled (false),
41     m_bytes(),
42     m_bytes_mutex (Mutex::eMutexTypeRecursive),
43     m_write_mutex (Mutex::eMutexTypeNormal),
44     m_callback (NULL),
45     m_callback_baton (NULL),
46     m_close_on_eof (true)
47
48 {
49     lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_OBJECT | LIBLLDB_LOG_COMMUNICATION,
50                                  "%p Communication::Communication (name = %s)",
51                                  this, name);
52
53     SetEventName (eBroadcastBitDisconnected, "disconnected");
54     SetEventName (eBroadcastBitReadThreadGotBytes, "got bytes");
55     SetEventName (eBroadcastBitReadThreadDidExit, "read thread did exit");
56     SetEventName (eBroadcastBitReadThreadShouldExit, "read thread should exit");
57     SetEventName (eBroadcastBitPacketAvailable, "packet available");
58     
59     CheckInWithManager();
60 }
61
62 //----------------------------------------------------------------------
63 // Destructor
64 //----------------------------------------------------------------------
65 Communication::~Communication()
66 {
67     lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_OBJECT | LIBLLDB_LOG_COMMUNICATION,
68                                  "%p Communication::~Communication (name = %s)",
69                                  this, m_broadcaster_name.AsCString(""));
70     Clear();
71 }
72
73 void
74 Communication::Clear()
75 {
76     SetReadThreadBytesReceivedCallback (NULL, NULL);
77     Disconnect (NULL);
78     StopReadThread (NULL);
79 }
80
81 ConnectionStatus
82 Communication::Connect (const char *url, Error *error_ptr)
83 {
84     Clear();
85
86     lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_COMMUNICATION, "%p Communication::Connect (url = %s)", this, url);
87
88     lldb::ConnectionSP connection_sp (m_connection_sp);
89     if (connection_sp.get())
90         return connection_sp->Connect (url, error_ptr);
91     if (error_ptr)
92         error_ptr->SetErrorString("Invalid connection.");
93     return eConnectionStatusNoConnection;
94 }
95
96 ConnectionStatus
97 Communication::Disconnect (Error *error_ptr)
98 {
99     lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_COMMUNICATION, "%p Communication::Disconnect ()", this);
100
101     lldb::ConnectionSP connection_sp (m_connection_sp);
102     if (connection_sp.get())
103     {
104         ConnectionStatus status = connection_sp->Disconnect (error_ptr);
105         // We currently don't protect connection_sp with any mutex for 
106         // multi-threaded environments. So lets not nuke our connection class 
107         // without putting some multi-threaded protections in. We also probably
108         // don't want to pay for the overhead it might cause if every time we
109         // access the connection we have to take a lock.
110         //
111         // This unique pointer will cleanup after itself when this object goes away,
112         // so there is no need to currently have it destroy itself immediately
113         // upon disconnnect.
114         //connection_sp.reset();
115         return status;
116     }
117     return eConnectionStatusNoConnection;
118 }
119
120 bool
121 Communication::IsConnected () const
122 {
123     lldb::ConnectionSP connection_sp (m_connection_sp);
124     if (connection_sp.get())
125         return connection_sp->IsConnected ();
126     return false;
127 }
128
129 bool
130 Communication::HasConnection () const
131 {
132     return m_connection_sp.get() != NULL;
133 }
134
135 size_t
136 Communication::Read (void *dst, size_t dst_len, uint32_t timeout_usec, ConnectionStatus &status, Error *error_ptr)
137 {
138     lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_COMMUNICATION,
139                                          "%p Communication::Read (dst = %p, dst_len = %" PRIu64 ", timeout = %u usec) connection = %p",
140                                          this, 
141                                          dst, 
142                                          (uint64_t)dst_len,
143                                          timeout_usec, 
144                                          m_connection_sp.get());
145
146     if (m_read_thread_enabled)
147     {
148         // We have a dedicated read thread that is getting data for us
149         size_t cached_bytes = GetCachedBytes (dst, dst_len);
150         if (cached_bytes > 0 || timeout_usec == 0)
151         {
152             status = eConnectionStatusSuccess;
153             return cached_bytes;
154         }
155
156         if (m_connection_sp.get() == NULL)
157         {
158             if (error_ptr)
159                 error_ptr->SetErrorString("Invalid connection.");
160             status = eConnectionStatusNoConnection;
161             return 0;
162         }
163         // Set the timeout appropriately
164         TimeValue timeout_time;
165         if (timeout_usec != UINT32_MAX)
166         {
167             timeout_time = TimeValue::Now();
168             timeout_time.OffsetWithMicroSeconds (timeout_usec);
169         }
170
171         Listener listener ("Communication::Read");
172         listener.StartListeningForEvents (this, eBroadcastBitReadThreadGotBytes | eBroadcastBitReadThreadDidExit);
173         EventSP event_sp;
174         while (listener.WaitForEvent (timeout_time.IsValid() ? &timeout_time : NULL, event_sp))
175         {
176             const uint32_t event_type = event_sp->GetType();
177             if (event_type & eBroadcastBitReadThreadGotBytes)
178             {
179                 return GetCachedBytes (dst, dst_len);
180             }
181
182             if (event_type & eBroadcastBitReadThreadDidExit)
183             {
184                 Disconnect (NULL);
185                 break;
186             }
187         }
188         return 0;
189     }
190
191     // We aren't using a read thread, just read the data synchronously in this
192     // thread.
193     lldb::ConnectionSP connection_sp (m_connection_sp);
194     if (connection_sp.get())
195     {
196         return connection_sp->Read (dst, dst_len, timeout_usec, status, error_ptr);
197     }
198
199     if (error_ptr)
200         error_ptr->SetErrorString("Invalid connection.");
201     status = eConnectionStatusNoConnection;
202     return 0;
203 }
204
205
206 size_t
207 Communication::Write (const void *src, size_t src_len, ConnectionStatus &status, Error *error_ptr)
208 {
209     lldb::ConnectionSP connection_sp (m_connection_sp);
210
211     Mutex::Locker locker(m_write_mutex);
212     lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_COMMUNICATION,
213                                          "%p Communication::Write (src = %p, src_len = %" PRIu64 ") connection = %p",
214                                          this, 
215                                          src, 
216                                          (uint64_t)src_len,
217                                          connection_sp.get());
218
219     if (connection_sp.get())
220         return connection_sp->Write (src, src_len, status, error_ptr);
221
222     if (error_ptr)
223         error_ptr->SetErrorString("Invalid connection.");
224     status = eConnectionStatusNoConnection;
225     return 0;
226 }
227
228
229 bool
230 Communication::StartReadThread (Error *error_ptr)
231 {
232     if (error_ptr)
233         error_ptr->Clear();
234
235     if (IS_VALID_LLDB_HOST_THREAD(m_read_thread))
236         return true;
237
238     lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_COMMUNICATION,
239                                  "%p Communication::StartReadThread ()", this);
240
241
242     char thread_name[1024];
243     snprintf(thread_name, sizeof(thread_name), "<lldb.comm.%s>", m_broadcaster_name.AsCString());
244
245     m_read_thread_enabled = true;
246     m_read_thread = Host::ThreadCreate (thread_name, Communication::ReadThread, this, error_ptr);
247     if (!IS_VALID_LLDB_HOST_THREAD(m_read_thread))
248         m_read_thread_enabled = false;
249     return m_read_thread_enabled;
250 }
251
252 bool
253 Communication::StopReadThread (Error *error_ptr)
254 {
255     if (!IS_VALID_LLDB_HOST_THREAD(m_read_thread))
256         return true;
257
258     lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_COMMUNICATION,
259                                  "%p Communication::StopReadThread ()", this);
260
261     m_read_thread_enabled = false;
262
263     BroadcastEvent (eBroadcastBitReadThreadShouldExit, NULL);
264
265     //Host::ThreadCancel (m_read_thread, error_ptr);
266
267     bool status = Host::ThreadJoin (m_read_thread, NULL, error_ptr);
268     m_read_thread = LLDB_INVALID_HOST_THREAD;
269     return status;
270 }
271
272 bool
273 Communication::JoinReadThread (Error *error_ptr)
274 {
275     if (!IS_VALID_LLDB_HOST_THREAD(m_read_thread))
276         return true;
277
278     bool success = Host::ThreadJoin (m_read_thread, NULL, error_ptr);
279     m_read_thread = LLDB_INVALID_HOST_THREAD;
280     return success;
281 }
282
283 size_t
284 Communication::GetCachedBytes (void *dst, size_t dst_len)
285 {
286     Mutex::Locker locker(m_bytes_mutex);
287     if (m_bytes.size() > 0)
288     {
289         // If DST is NULL and we have a thread, then return the number
290         // of bytes that are available so the caller can call again
291         if (dst == NULL)
292             return m_bytes.size();
293
294         const size_t len = std::min<size_t>(dst_len, m_bytes.size());
295
296         ::memcpy (dst, m_bytes.c_str(), len);
297         m_bytes.erase(m_bytes.begin(), m_bytes.begin() + len);
298
299         return len;
300     }
301     return 0;
302 }
303
304 void
305 Communication::AppendBytesToCache (const uint8_t * bytes, size_t len, bool broadcast, ConnectionStatus status)
306 {
307     lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_COMMUNICATION,
308                                  "%p Communication::AppendBytesToCache (src = %p, src_len = %" PRIu64 ", broadcast = %i)",
309                                  this, bytes, (uint64_t)len, broadcast);
310     if ((bytes == NULL || len == 0)
311         && (status != lldb::eConnectionStatusEndOfFile))
312         return;
313     if (m_callback)
314     {
315         // If the user registered a callback, then call it and do not broadcast
316         m_callback (m_callback_baton, bytes, len);
317     }
318     else if (bytes != NULL && len > 0)
319     {
320         Mutex::Locker locker(m_bytes_mutex);
321         m_bytes.append ((const char *)bytes, len);
322         if (broadcast)
323             BroadcastEventIfUnique (eBroadcastBitReadThreadGotBytes);
324     }
325 }
326
327 size_t
328 Communication::ReadFromConnection (void *dst, 
329                                    size_t dst_len, 
330                                    uint32_t timeout_usec,
331                                    ConnectionStatus &status, 
332                                    Error *error_ptr)
333 {
334     lldb::ConnectionSP connection_sp (m_connection_sp);
335     if (connection_sp.get())
336         return connection_sp->Read (dst, dst_len, timeout_usec, status, error_ptr);
337     return 0;
338 }
339
340 bool
341 Communication::ReadThreadIsRunning ()
342 {
343     return m_read_thread_enabled;
344 }
345
346 lldb::thread_result_t
347 Communication::ReadThread (lldb::thread_arg_t p)
348 {
349     Communication *comm = (Communication *)p;
350
351     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_COMMUNICATION));
352
353     if (log)
354         log->Printf ("%p Communication::ReadThread () thread starting...", p);
355
356     uint8_t buf[1024];
357
358     Error error;
359     ConnectionStatus status = eConnectionStatusSuccess;
360     bool done = false;
361     while (!done && comm->m_read_thread_enabled)
362     {
363         size_t bytes_read = comm->ReadFromConnection (buf, sizeof(buf), 5 * TimeValue::MicroSecPerSec, status, &error);
364         if (bytes_read > 0)
365             comm->AppendBytesToCache (buf, bytes_read, true, status);
366         else if ((bytes_read == 0)
367                 && status == eConnectionStatusEndOfFile)
368         {
369             if (comm->GetCloseOnEOF ())
370                 comm->Disconnect ();
371             comm->AppendBytesToCache (buf, bytes_read, true, status);
372         }
373
374         switch (status)
375         {
376         case eConnectionStatusSuccess:
377             break;
378
379         case eConnectionStatusEndOfFile:
380             if (comm->GetCloseOnEOF())
381                  done = true;
382              break;
383         case eConnectionStatusNoConnection:     // No connection
384         case eConnectionStatusLostConnection:   // Lost connection while connected to a valid connection
385             done = true;
386             // Fall through...
387         case eConnectionStatusError:            // Check GetError() for details
388         case eConnectionStatusTimedOut:         // Request timed out
389             if (log)
390                 error.LogIfError (log,
391                                   "%p Communication::ReadFromConnection () => status = %s",
392                                   p,
393                                   Communication::ConnectionStatusAsCString (status));
394             break;
395         }
396     }
397     log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_COMMUNICATION);
398     if (log)
399         log->Printf ("%p Communication::ReadThread () thread exiting...", p);
400
401     // Let clients know that this thread is exiting
402     comm->BroadcastEvent (eBroadcastBitReadThreadDidExit);
403     return NULL;
404 }
405
406 void
407 Communication::SetReadThreadBytesReceivedCallback
408 (
409     ReadThreadBytesReceived callback,
410     void *callback_baton
411 )
412 {
413     m_callback = callback;
414     m_callback_baton = callback_baton;
415 }
416
417 void
418 Communication::SetConnection (Connection *connection)
419 {
420     Disconnect (NULL);
421     StopReadThread(NULL);
422     m_connection_sp.reset(connection);
423 }
424
425 const char *
426 Communication::ConnectionStatusAsCString (lldb::ConnectionStatus status)
427 {
428     switch (status)
429     {
430     case eConnectionStatusSuccess:        return "success";
431     case eConnectionStatusError:          return "error";
432     case eConnectionStatusTimedOut:       return "timed out";
433     case eConnectionStatusNoConnection:   return "no connection";
434     case eConnectionStatusLostConnection: return "lost connection";
435     case eConnectionStatusEndOfFile:      return "end of file";
436     }
437
438     static char unknown_state_string[64];
439     snprintf(unknown_state_string, sizeof (unknown_state_string), "ConnectionStatus = %i", status);
440     return unknown_state_string;
441 }