73 lines · cpp
1//===-- sanitizer_thread_history.cpp --------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "sanitizer_thread_history.h"10 11#include "sanitizer_stackdepot.h"12namespace __sanitizer {13 14void PrintThreadHistory(ThreadRegistry ®istry, InternalScopedString &out) {15 ThreadRegistryLock l(®istry);16 // Stack traces are largest part of printout and they often the same for17 // multiple threads, so we will deduplicate them.18 InternalMmapVector<const ThreadContextBase *> stacks;19 20 registry.RunCallbackForEachThreadLocked(21 [](ThreadContextBase *context, void *arg) {22 static_cast<decltype(&stacks)>(arg)->push_back(context);23 },24 &stacks);25 26 Sort(stacks.data(), stacks.size(),27 [](const ThreadContextBase *a, const ThreadContextBase *b) {28 if (a->stack_id < b->stack_id)29 return true;30 if (a->stack_id > b->stack_id)31 return false;32 return a->unique_id < b->unique_id;33 });34 35 auto describe_thread = [&](const ThreadContextBase *context) {36 if (!context) {37 out.Append("T-1");38 return;39 }40 out.AppendF("T%llu/%llu", context->unique_id, context->os_id);41 if (internal_strlen(context->name))42 out.AppendF(" (%s)", context->name);43 };44 45 auto get_parent =46 [&](const ThreadContextBase *context) -> const ThreadContextBase * {47 if (!context)48 return nullptr;49 ThreadContextBase *parent = registry.GetThreadLocked(context->parent_tid);50 if (!parent)51 return nullptr;52 if (parent->unique_id >= context->unique_id)53 return nullptr;54 return parent;55 };56 57 const ThreadContextBase *prev = nullptr;58 for (const ThreadContextBase *context : stacks) {59 if (prev && prev->stack_id != context->stack_id)60 StackDepotGet(prev->stack_id).PrintTo(&out);61 prev = context;62 out.Append("Thread ");63 describe_thread(context);64 out.Append(" was created by ");65 describe_thread(get_parent(context));66 out.Append("\n");67 }68 if (prev)69 StackDepotGet(prev->stack_id).PrintTo(&out);70}71 72} // namespace __sanitizer73