Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,6 @@
__pycache__/
*.py[cod]
*.tmp

# Coretrace StackAnalyzer cache and temporary files
*.cache
92 changes: 79 additions & 13 deletions src/app/AnalyzerApp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,19 @@
#include <new>
#include <optional>
#include <sstream>
#include <string>
#include <system_error>
#include <thread>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>

#if defined(__APPLE__) || defined(__unix__)
#include <pthread.h>
#define CTRACE_STACK_ANALYZER_HAS_PTHREAD 1
#endif

#include <llvm/IR/InstrTypes.h>
#include <llvm/IR/LLVMContext.h>
#include <llvm/IR/Module.h>
Expand Down Expand Up @@ -87,6 +94,18 @@
return hw == 0 ? 1u : hw;
}

#if defined(CTRACE_STACK_ANALYZER_HAS_PTHREAD)
static std::size_t resolveParallelWorkerStackBytes()
{
constexpr std::size_t kDefaultWorkerStackBytes = 8u * 1024u * 1024u;
#if defined(PTHREAD_STACK_MIN)
return std::max(kDefaultWorkerStackBytes, static_cast<std::size_t>(PTHREAD_STACK_MIN));
#else
return kDefaultWorkerStackBytes;
#endif
}
#endif

template <typename T> struct AppResult
{
std::optional<T> value;
Expand Down Expand Up @@ -310,29 +329,76 @@

std::vector<WorkerState> workerStates(workerCount);
std::atomic_size_t nextIndex{0};

auto workerBody = [&](WorkerState* workerState)
{
WorkerState& state = *workerState;
while (true)
{
const std::size_t index = nextIndex.fetch_add(1, std::memory_order_relaxed);
if (index >= workItemCount)
break;
workFn(index);
++state.processedCount;
}
};

#if defined(CTRACE_STACK_ANALYZER_HAS_PTHREAD)
struct PthreadWorkerContext
{
decltype(workerBody)* body = nullptr;
WorkerState* state = nullptr;
};

pthread_attr_t attr;
if (pthread_attr_init(&attr) != 0)
{
llvm::report_fatal_error("failed to initialize parallel worker thread attributes");
}
const int stackErr = pthread_attr_setstacksize(&attr, resolveParallelWorkerStackBytes());
if (stackErr != 0)
{
pthread_attr_destroy(&attr);
llvm::report_fatal_error("failed to configure parallel worker stack size");
}

std::vector<PthreadWorkerContext> contexts(workerCount);
std::vector<pthread_t> workers(workerCount);
for (unsigned workerId = 0; workerId < workerCount; ++workerId)
{
contexts[workerId] = {&workerBody, &workerStates[workerId]};
const int createErr = pthread_create(
&workers[workerId], &attr,
[](void* rawContext) -> void*

Check notice

Code scanning / coretrace-stack-analyzer

[ !Info! ] ConstParameterNotModified.Pointer: parameter 'rawContext' in function 'runParallelWork<analyzeWithSharedModuleLoading(std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > const&, ctrace::stack::AnalysisConfig&, bool, bool, bool, bool, std::vector<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, ctrace::stack::AnalysisResult>, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, ctrace::stack::AnalysisResult> > >&)::$_0>(unsigned long, unsigned int, analyzeWithSharedModuleLoading(std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > const&, ctrace::stack::AnalysisConfig&, bool, bool, bool, bool, std::vector<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, ctrace::stack::AnalysisResult>, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, ctrace::stack::AnalysisResult> > >&)::$_0&&)::{lambda(void*)#1}::operator()(void*) const' is never used to modify the pointed object ↳ current type: <unknown type> *rawContext ↳ suggested type: const <unknown type> *rawContext Note

[ !Info! ] ConstParameterNotModified.Pointer: parameter 'rawContext' in function 'runParallelWork<analyzeWithSharedModuleLoading(std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > const&, ctrace::stack::AnalysisConfig&, bool, bool, bool, bool, std::vector<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, ctrace::stack::AnalysisResult>, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, ctrace::stack::AnalysisResult> > >&)::$_0>(unsigned long, unsigned int, analyzeWithSharedModuleLoading(std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > const&, ctrace::stack::AnalysisConfig&, bool, bool, bool, bool, std::vector<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, ctrace::stack::AnalysisResult>, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, ctrace::stack::AnalysisResult> > >&)::$_0&&)::{lambda(void*)#1}::operator()(void*) const' is never used to modify the pointed object ↳ current type: <unknown type> *rawContext ↳ suggested type: const <unknown type> *rawContext

Check notice

Code scanning / coretrace-stack-analyzer

[ !Info! ] ConstParameterNotModified.Pointer: parameter 'rawContext' in function 'runParallelWork<buildCrossTUSummaryIndex(std::vector<LoadedInputModule, std::allocator<LoadedInputModule> > const&, ctrace::stack::AnalysisConfig const&)::$_2>(unsigned long, unsigned int, buildCrossTUSummaryIndex(std::vector<LoadedInputModule, std::allocator<LoadedInputModule> > const&, ctrace::stack::AnalysisConfig const&)::$_2&&)::{lambda(void*)#1}::operator()(void*) const' is never used to modify the pointed object ↳ current type: <unknown type> *rawContext ↳ suggested type: const <unknown type> *rawContext Note

[ !Info! ] ConstParameterNotModified.Pointer: parameter 'rawContext' in function 'runParallelWork<buildCrossTUSummaryIndex(std::vector<LoadedInputModule, std::allocator<LoadedInputModule> > const&, ctrace::stack::AnalysisConfig const&)::$_2>(unsigned long, unsigned int, buildCrossTUSummaryIndex(std::vector<LoadedInputModule, std::allocator<LoadedInputModule> > const&, ctrace::stack::AnalysisConfig const&)::$_2&&)::{lambda(void*)#1}::operator()(void*) const' is never used to modify the pointed object ↳ current type: <unknown type> *rawContext ↳ suggested type: const <unknown type> *rawContext

Check notice

Code scanning / coretrace-stack-analyzer

[ !Info! ] ConstParameterNotModified.Pointer: parameter 'rawContext' in function 'runParallelWork<buildCrossTUUninitializedSummaryIndex(std::vector<LoadedInputModule, std::allocator<LoadedInputModule> > const&, ctrace::stack::AnalysisConfig const&)::$_3>(unsigned long, unsigned int, buildCrossTUUninitializedSummaryIndex(std::vector<LoadedInputModule, std::allocator<LoadedInputModule> > const&, ctrace::stack::AnalysisConfig const&)::$_3&&)::{lambda(void*)#1}::operator()(void*) const' is never used to modify the pointed object ↳ current type: <unknown type> *rawContext ↳ suggested type: const <unknown type> *rawContext Note

[ !Info! ] ConstParameterNotModified.Pointer: parameter 'rawContext' in function 'runParallelWork<buildCrossTUUninitializedSummaryIndex(std::vector<LoadedInputModule, std::allocator<LoadedInputModule> > const&, ctrace::stack::AnalysisConfig const&)::$_3>(unsigned long, unsigned int, buildCrossTUUninitializedSummaryIndex(std::vector<LoadedInputModule, std::allocator<LoadedInputModule> > const&, ctrace::stack::AnalysisConfig const&)::$_3&&)::{lambda(void*)#1}::operator()(void*) const' is never used to modify the pointed object ↳ current type: <unknown type> *rawContext ↳ suggested type: const <unknown type> *rawContext

Check notice

Code scanning / coretrace-stack-analyzer

[ !Info! ] ConstParameterNotModified.Pointer: parameter 'rawContext' in function 'runParallelWork<buildCrossTUGlobalReadBeforeWriteSummaryIndex(std::vector<LoadedInputModule, std::allocator<LoadedInputModule> > const&, ctrace::stack::AnalysisConfig const&)::$_1>(unsigned long, unsigned int, buildCrossTUGlobalReadBeforeWriteSummaryIndex(std::vector<LoadedInputModule, std::allocator<LoadedInputModule> > const&, ctrace::stack::AnalysisConfig const&)::$_1&&)::{lambda(void*)#1}::operator()(void*) const' is never used to modify the pointed object ↳ current type: <unknown type> *rawContext ↳ suggested type: const <unknown type> *rawContext Note

[ !Info! ] ConstParameterNotModified.Pointer: parameter 'rawContext' in function 'runParallelWork<buildCrossTUGlobalReadBeforeWriteSummaryIndex(std::vector<LoadedInputModule, std::allocator<LoadedInputModule> > const&, ctrace::stack::AnalysisConfig const&)::$_1>(unsigned long, unsigned int, buildCrossTUGlobalReadBeforeWriteSummaryIndex(std::vector<LoadedInputModule, std::allocator<LoadedInputModule> > const&, ctrace::stack::AnalysisConfig const&)::$_1&&)::{lambda(void*)#1}::operator()(void*) const' is never used to modify the pointed object ↳ current type: <unknown type> *rawContext ↳ suggested type: const <unknown type> *rawContext

Check notice

Code scanning / coretrace-stack-analyzer

[ !Info! ] ConstParameterNotModified.Pointer: parameter 'rawContext' in function 'runParallelWork<analyzeWithoutSharedModuleLoading(std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > const&, ctrace::stack::AnalysisConfig const&, bool, std::vector<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, ctrace::stack::AnalysisResult>, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, ctrace::stack::AnalysisResult> > >&)::$_0>(unsigned long, unsigned int, analyzeWithoutSharedModuleLoading(std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > const&, ctrace::stack::AnalysisConfig const&, bool, std::vector<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, ctrace::stack::AnalysisResult>, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, ctrace::stack::AnalysisResult> > >&)::$_0&&)::{lambda(void*)#1}::operator()(void*) const' is never used to modify the pointed object ↳ current type: <unknown type> *rawContext ↳ suggested type: const <unknown type> *rawContext Note

[ !Info! ] ConstParameterNotModified.Pointer: parameter 'rawContext' in function 'runParallelWork<analyzeWithoutSharedModuleLoading(std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > const&, ctrace::stack::AnalysisConfig const&, bool, std::vector<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, ctrace::stack::AnalysisResult>, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, ctrace::stack::AnalysisResult> > >&)::$_0>(unsigned long, unsigned int, analyzeWithoutSharedModuleLoading(std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > const&, ctrace::stack::AnalysisConfig const&, bool, std::vector<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, ctrace::stack::AnalysisResult>, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, ctrace::stack::AnalysisResult> > >&)::$_0&&)::{lambda(void*)#1}::operator()(void*) const' is never used to modify the pointed object ↳ current type: <unknown type> *rawContext ↳ suggested type: const <unknown type> *rawContext
{
auto* context = static_cast<PthreadWorkerContext*>(rawContext);
(*context->body)(context->state);
return nullptr;
},
&contexts[workerId]);
if (createErr != 0)
{
pthread_attr_destroy(&attr);
llvm::report_fatal_error("failed to create parallel worker thread");
}
}
pthread_attr_destroy(&attr);

for (pthread_t worker : workers)
pthread_join(worker, nullptr);
#else
std::vector<std::thread> workers;
workers.reserve(workerCount);

for (unsigned workerId = 0; workerId < workerCount; ++workerId)
{
WorkerState* const workerState = &workerStates[workerId];
workers.emplace_back(
[&, workerState]()
{
WorkerState& state = *workerState;
while (true)
{
const std::size_t index = nextIndex.fetch_add(1, std::memory_order_relaxed);
if (index >= workItemCount)
break;
workFn(index);
++state.processedCount;
}
});
workers.emplace_back([&, workerState]() { workerBody(workerState); });
}

for (auto& worker : workers)
worker.join();
#endif

std::uint64_t processedTotal = 0;
for (const WorkerState& state : workerStates)
Expand Down
Loading