11188faa7SWalter Erquinigo //===-- IntelPTThreadTraceCollection.cpp ----------------------------------===//
21188faa7SWalter Erquinigo //
31188faa7SWalter Erquinigo // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
41188faa7SWalter Erquinigo // See https://llvm.org/LICENSE.txt for license information.
51188faa7SWalter Erquinigo // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
61188faa7SWalter Erquinigo //
71188faa7SWalter Erquinigo //===----------------------------------------------------------------------===//
81188faa7SWalter Erquinigo 
91188faa7SWalter Erquinigo #include "IntelPTThreadTraceCollection.h"
101188faa7SWalter Erquinigo 
111188faa7SWalter Erquinigo using namespace lldb;
121188faa7SWalter Erquinigo using namespace lldb_private;
131188faa7SWalter Erquinigo using namespace process_linux;
141188faa7SWalter Erquinigo using namespace llvm;
151188faa7SWalter Erquinigo 
161188faa7SWalter Erquinigo bool IntelPTThreadTraceCollection::TracesThread(lldb::tid_t tid) const {
171188faa7SWalter Erquinigo   return m_thread_traces.count(tid);
181188faa7SWalter Erquinigo }
191188faa7SWalter Erquinigo 
201188faa7SWalter Erquinigo Error IntelPTThreadTraceCollection::TraceStop(lldb::tid_t tid) {
211188faa7SWalter Erquinigo   auto it = m_thread_traces.find(tid);
221188faa7SWalter Erquinigo   if (it == m_thread_traces.end())
231188faa7SWalter Erquinigo     return createStringError(inconvertibleErrorCode(),
241188faa7SWalter Erquinigo                              "Thread %" PRIu64 " not currently traced", tid);
25a7582059SWalter Erquinigo   m_total_buffer_size -= it->second.GetTraceBufferSize();
261188faa7SWalter Erquinigo   m_thread_traces.erase(tid);
271188faa7SWalter Erquinigo   return Error::success();
281188faa7SWalter Erquinigo }
291188faa7SWalter Erquinigo 
301188faa7SWalter Erquinigo Error IntelPTThreadTraceCollection::TraceStart(
311188faa7SWalter Erquinigo     lldb::tid_t tid, const TraceIntelPTStartRequest &request) {
321188faa7SWalter Erquinigo   if (TracesThread(tid))
331188faa7SWalter Erquinigo     return createStringError(inconvertibleErrorCode(),
341188faa7SWalter Erquinigo                              "Thread %" PRIu64 " already traced", tid);
351188faa7SWalter Erquinigo 
36a7582059SWalter Erquinigo   Expected<IntelPTSingleBufferTrace> trace =
37a7582059SWalter Erquinigo       IntelPTSingleBufferTrace::Start(request, tid);
38a7582059SWalter Erquinigo   if (!trace)
39a7582059SWalter Erquinigo     return trace.takeError();
401188faa7SWalter Erquinigo 
41a7582059SWalter Erquinigo   m_total_buffer_size += trace->GetTraceBufferSize();
42a7582059SWalter Erquinigo   m_thread_traces.try_emplace(tid, std::move(*trace));
431188faa7SWalter Erquinigo   return Error::success();
441188faa7SWalter Erquinigo }
451188faa7SWalter Erquinigo 
461188faa7SWalter Erquinigo size_t IntelPTThreadTraceCollection::GetTotalBufferSize() const {
471188faa7SWalter Erquinigo   return m_total_buffer_size;
481188faa7SWalter Erquinigo }
491188faa7SWalter Erquinigo 
501188faa7SWalter Erquinigo void IntelPTThreadTraceCollection::ForEachThread(
511188faa7SWalter Erquinigo     std::function<void(lldb::tid_t tid, IntelPTSingleBufferTrace &thread_trace)>
521188faa7SWalter Erquinigo         callback) {
531188faa7SWalter Erquinigo   for (auto &it : m_thread_traces)
54a7582059SWalter Erquinigo     callback(it.first, it.second);
551188faa7SWalter Erquinigo }
561188faa7SWalter Erquinigo 
571188faa7SWalter Erquinigo Expected<IntelPTSingleBufferTrace &>
581188faa7SWalter Erquinigo IntelPTThreadTraceCollection::GetTracedThread(lldb::tid_t tid) {
591188faa7SWalter Erquinigo   auto it = m_thread_traces.find(tid);
601188faa7SWalter Erquinigo   if (it == m_thread_traces.end())
611188faa7SWalter Erquinigo     return createStringError(inconvertibleErrorCode(),
621188faa7SWalter Erquinigo                              "Thread %" PRIu64 " not currently traced", tid);
63a7582059SWalter Erquinigo   return it->second;
641188faa7SWalter Erquinigo }
651188faa7SWalter Erquinigo 
661188faa7SWalter Erquinigo void IntelPTThreadTraceCollection::Clear() {
671188faa7SWalter Erquinigo   m_thread_traces.clear();
681188faa7SWalter Erquinigo   m_total_buffer_size = 0;
691188faa7SWalter Erquinigo }
701188faa7SWalter Erquinigo 
711188faa7SWalter Erquinigo size_t IntelPTThreadTraceCollection::GetTracedThreadsCount() const {
721188faa7SWalter Erquinigo   return m_thread_traces.size();
731188faa7SWalter Erquinigo }
74*fc5ef57cSWalter Erquinigo 
75*fc5ef57cSWalter Erquinigo llvm::Expected<llvm::Optional<std::vector<uint8_t>>>
76*fc5ef57cSWalter Erquinigo IntelPTThreadTraceCollection::TryGetBinaryData(
77*fc5ef57cSWalter Erquinigo     const TraceGetBinaryDataRequest &request) {
78*fc5ef57cSWalter Erquinigo   if (!request.tid)
79*fc5ef57cSWalter Erquinigo     return None;
80*fc5ef57cSWalter Erquinigo   if (request.kind != IntelPTDataKinds::kTraceBuffer)
81*fc5ef57cSWalter Erquinigo     return None;
82*fc5ef57cSWalter Erquinigo 
83*fc5ef57cSWalter Erquinigo   if (!TracesThread(*request.tid))
84*fc5ef57cSWalter Erquinigo     return None;
85*fc5ef57cSWalter Erquinigo 
86*fc5ef57cSWalter Erquinigo   if (Expected<IntelPTSingleBufferTrace &> trace =
87*fc5ef57cSWalter Erquinigo           GetTracedThread(*request.tid))
88*fc5ef57cSWalter Erquinigo     return trace->GetTraceBuffer(request.offset, request.size);
89*fc5ef57cSWalter Erquinigo   else
90*fc5ef57cSWalter Erquinigo     return trace.takeError();
91*fc5ef57cSWalter Erquinigo }
92