brintos

brintos / llvm-project-archived public Read only

0
0
Text · 2.3 KiB · 0f5bec3 Raw
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 &registry, InternalScopedString &out) {15  ThreadRegistryLock l(&registry);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