SharingPtr.cpp revision 360660
1//===---------------------SharingPtr.cpp ------------------------*- C++ -*-===//
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-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "lldb/Utility/SharingPtr.h"
10
11#if defined(ENABLE_SP_LOGGING)
12
13// If ENABLE_SP_LOGGING is defined, then log all shared pointer assignments and
14// allow them to be queried using a pointer by a call to:
15#include <assert.h>
16#include <execinfo.h>
17
18#include "llvm/ADT/STLExtras.h"
19
20#include <map>
21#include <mutex>
22#include <vector>
23
24class Backtrace {
25public:
26  Backtrace();
27
28  ~Backtrace();
29
30  void GetFrames();
31
32  void Dump() const;
33
34private:
35  void *m_sp_this;
36  std::vector<void *> m_frames;
37};
38
39Backtrace::Backtrace() : m_frames() {}
40
41Backtrace::~Backtrace() {}
42
43void Backtrace::GetFrames() {
44  void *frames[1024];
45  const int count = ::backtrace(frames, llvm::array_lengthof(frames));
46  if (count > 2)
47    m_frames.assign(frames + 2, frames + (count - 2));
48}
49
50void Backtrace::Dump() const {
51  if (!m_frames.empty())
52    ::backtrace_symbols_fd(m_frames.data(), m_frames.size(), STDOUT_FILENO);
53  write(STDOUT_FILENO, "\n\n", 2);
54}
55
56extern "C" void track_sp(void *sp_this, void *ptr, long use_count) {
57  typedef std::pair<void *, Backtrace> PtrBacktracePair;
58  typedef std::map<void *, PtrBacktracePair> PtrToBacktraceMap;
59  static std::mutex g_mutex;
60  std::lock_guard<std::mutex> guard(g_mutex);
61  static PtrToBacktraceMap g_map;
62
63  if (sp_this) {
64    printf("sp(%p) -> %p %lu\n", sp_this, ptr, use_count);
65
66    if (ptr) {
67      Backtrace bt;
68      bt.GetFrames();
69      g_map[sp_this] = std::make_pair(ptr, bt);
70    } else {
71      g_map.erase(sp_this);
72    }
73  } else {
74    if (ptr)
75      printf("Searching for shared pointers that are tracking %p: ", ptr);
76    else
77      printf("Dump all live shared pointres: ");
78
79    uint32_t matches = 0;
80    PtrToBacktraceMap::iterator pos, end = g_map.end();
81    for (pos = g_map.begin(); pos != end; ++pos) {
82      if (ptr == NULL || pos->second.first == ptr) {
83        ++matches;
84        printf("\nsp(%p): %p\n", pos->first, pos->second.first);
85        pos->second.second.Dump();
86      }
87    }
88    if (matches == 0) {
89      printf("none.\n");
90    }
91  }
92}
93// Put dump_sp_refs in the lldb namespace to it gets through our exports lists
94// filter in the LLDB.framework or lldb.so
95namespace lldb {
96
97void dump_sp_refs(void *ptr) {
98  // Use a specially crafted call to "track_sp" which will dump info on all
99  // live shared pointers that reference "ptr"
100  track_sp(NULL, ptr, 0);
101}
102}
103
104#endif
105
106namespace lldb_private {
107
108namespace imp {
109
110shared_count::~shared_count() {}
111
112void shared_count::add_shared() {
113#ifdef _MSC_VER
114  _InterlockedIncrement(&shared_owners_);
115#else
116  ++shared_owners_;
117#endif
118}
119
120void shared_count::release_shared() {
121#ifdef _MSC_VER
122  if (_InterlockedDecrement(&shared_owners_) == -1)
123#else
124  if (--shared_owners_ == -1)
125#endif
126  {
127    on_zero_shared();
128    delete this;
129  }
130}
131
132} // imp
133
134} // namespace lldb
135