summaryrefslogtreecommitdiffstats
path: root/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
diff options
context:
space:
mode:
authorHan Ming Ong <hanming@apple.com>2013-01-18 23:11:53 +0000
committerHan Ming Ong <hanming@apple.com>2013-01-18 23:11:53 +0000
commit4b6459f33f8a345b6c5b60feee3b67c8aa318d2a (patch)
treea78cf04330ef686d971be89aeb8ea194cebd5f95 /lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
parent7431211214d54d0cd8cc0d069447abd22c5da0cb (diff)
downloadbcm5719-llvm-4b6459f33f8a345b6c5b60feee3b67c8aa318d2a.tar.gz
bcm5719-llvm-4b6459f33f8a345b6c5b60feee3b67c8aa318d2a.zip
<rdar://problem/12976277>
Swap in index ids for thread ids in GDBRemoteCommunicationClient. Besides dealing with the async logic, I have to take care of the situation when the inferior paused as well. llvm-svn: 172869
Diffstat (limited to 'lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp')
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp123
1 files changed, 119 insertions, 4 deletions
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
index 63ddc5d957d..1de76a44690 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
@@ -12,6 +12,8 @@
// C Includes
// C++ Includes
+#include <sstream>
+
// Other libraries and framework includes
#include "llvm/ADT/Triple.h"
#include "lldb/Interpreter/Args.h"
@@ -71,6 +73,7 @@ GDBRemoteCommunicationClient::GDBRemoteCommunicationClient(bool is_platform) :
m_async_packet (),
m_async_response (),
m_async_signal (-1),
+ m_thread_id_to_used_usec_map (),
m_host_arch(),
m_process_arch(),
m_os_version_major (UINT32_MAX),
@@ -421,6 +424,99 @@ GDBRemoteCommunicationClient::SendPacketAndWaitForResponse
return response_len;
}
+static const char *end_delimiter = "--end--;";
+static const int end_delimiter_len = 8;
+
+std::string
+GDBRemoteCommunicationClient::HarmonizeThreadIdsForProfileData
+( ProcessGDBRemote *process,
+ StringExtractorGDBRemote& profileDataExtractor
+)
+{
+ std::map<uint64_t, uint32_t> new_thread_id_to_used_usec_map;
+ std::stringstream final_output;
+ std::string name, value;
+
+ // Going to assuming thread_used_usec comes first, else bail out.
+ while (profileDataExtractor.GetNameColonValue(name, value))
+ {
+ if (name.compare("thread_used_id") == 0)
+ {
+ StringExtractor threadIDHexExtractor(value.c_str());
+ uint64_t thread_id = threadIDHexExtractor.GetHexMaxU64(false, 0);
+
+ bool has_used_usec = false;
+ uint32_t curr_used_usec = 0;
+ std::string usec_name, usec_value;
+ uint32_t input_file_pos = profileDataExtractor.GetFilePos();
+ if (profileDataExtractor.GetNameColonValue(usec_name, usec_value))
+ {
+ if (usec_name.compare("thread_used_usec") == 0)
+ {
+ has_used_usec = true;
+ curr_used_usec = strtoull(usec_value.c_str(), NULL, 0);
+ }
+ else
+ {
+ // We didn't find what we want, it is probably
+ // an older version. Bail out.
+ profileDataExtractor.SetFilePos(input_file_pos);
+ }
+ }
+
+ if (has_used_usec)
+ {
+ uint32_t prev_used_usec = 0;
+ std::map<uint64_t, uint32_t>::iterator iterator = m_thread_id_to_used_usec_map.find(thread_id);
+ if (iterator != m_thread_id_to_used_usec_map.end())
+ {
+ prev_used_usec = m_thread_id_to_used_usec_map[thread_id];
+ }
+
+ uint32_t real_used_usec = curr_used_usec - prev_used_usec;
+ // A good first time record is one that runs for at least 0.25 sec
+ bool good_first_time = (prev_used_usec == 0) && (real_used_usec > 250000);
+ bool good_subsequent_time = (prev_used_usec > 0) &&
+ ((real_used_usec > 0) || (process->HasAssignedIndexIDToThread(thread_id)));
+
+ if (good_first_time || good_subsequent_time)
+ {
+ // We try to avoid doing too many index id reservation,
+ // resulting in fast increase of index ids.
+
+ final_output << name << ":";
+ int32_t index_id = process->AssignIndexIDToThread(thread_id);
+ final_output << index_id << ";";
+
+ final_output << usec_name << ":" << usec_value << ";";
+ }
+ else
+ {
+ // Skip past 'thread_used_name'.
+ std::string local_name, local_value;
+ profileDataExtractor.GetNameColonValue(local_name, local_value);
+ }
+
+ // Store current time as previous time so that they can be compared later.
+ new_thread_id_to_used_usec_map[thread_id] = curr_used_usec;
+ }
+ else
+ {
+ // Bail out and use old string.
+ final_output << name << ":" << value << ";";
+ }
+ }
+ else
+ {
+ final_output << name << ":" << value << ";";
+ }
+ }
+ final_output << end_delimiter;
+ m_thread_id_to_used_usec_map = new_thread_id_to_used_usec_map;
+
+ return final_output.str();
+}
+
StateType
GDBRemoteCommunicationClient::SendContinuePacketAndWaitForResponse
(
@@ -654,10 +750,29 @@ GDBRemoteCommunicationClient::SendContinuePacketAndWaitForResponse
case 'A':
// Async miscellaneous reply. Right now, only profile data is coming through this channel.
{
- const std::string& profile_data = response.GetStringRef();
- const char *data_cstr = profile_data.c_str();
- data_cstr++; // Move beyond 'A'
- process->BroadcastAsyncProfileData (data_cstr, profile_data.size()-1);
+ std::string input = response.GetStringRef().substr(1); // '1' to move beyond 'A'
+ if (m_partial_profile_data.length() > 0)
+ {
+ m_partial_profile_data.append(input);
+ input = m_partial_profile_data;
+ m_partial_profile_data.clear();
+ }
+
+ size_t found, pos = 0, len = input.length();
+ while ((found = input.find(end_delimiter, pos)) != std::string::npos)
+ {
+ StringExtractorGDBRemote profileDataExtractor(input.substr(pos, found).c_str());
+ const std::string& profile_data = HarmonizeThreadIdsForProfileData(process, profileDataExtractor);
+ process->BroadcastAsyncProfileData (profile_data.c_str(), profile_data.length());
+
+ pos = found + end_delimiter_len;
+ }
+
+ if (pos < len)
+ {
+ // Last incomplete chunk.
+ m_partial_profile_data = input.substr(pos);
+ }
}
break;
OpenPOWER on IntegriCloud