1ac7ddfbfSEd Maste //===---------------------SharingPtr.cpp ------------------------*- C++ -*-===//
2ac7ddfbfSEd Maste //
3ac7ddfbfSEd Maste // The LLVM Compiler Infrastructure
4ac7ddfbfSEd Maste //
5ac7ddfbfSEd Maste // This file is distributed under the University of Illinois Open Source
6ac7ddfbfSEd Maste // License. See LICENSE.TXT for details.
7ac7ddfbfSEd Maste //
8ac7ddfbfSEd Maste //===----------------------------------------------------------------------===//
9ac7ddfbfSEd Maste
10ac7ddfbfSEd Maste #include "lldb/Utility/SharingPtr.h"
11ac7ddfbfSEd Maste
12ac7ddfbfSEd Maste #if defined(ENABLE_SP_LOGGING)
13ac7ddfbfSEd Maste
14*4ba319b5SDimitry Andric // If ENABLE_SP_LOGGING is defined, then log all shared pointer assignments and
15*4ba319b5SDimitry Andric // allow them to be queried using a pointer by a call to:
16ac7ddfbfSEd Maste #include <assert.h>
17435933ddSDimitry Andric #include <execinfo.h>
18ac7ddfbfSEd Maste
190127ef0fSEd Maste #include "llvm/ADT/STLExtras.h"
200127ef0fSEd Maste
214bb0738eSEd Maste #include <map>
224bb0738eSEd Maste #include <mutex>
23ac7ddfbfSEd Maste #include <vector>
24ac7ddfbfSEd Maste
25435933ddSDimitry Andric class Backtrace {
26ac7ddfbfSEd Maste public:
27ac7ddfbfSEd Maste Backtrace();
28ac7ddfbfSEd Maste
29ac7ddfbfSEd Maste ~Backtrace();
30ac7ddfbfSEd Maste
31435933ddSDimitry Andric void GetFrames();
32ac7ddfbfSEd Maste
33435933ddSDimitry Andric void Dump() const;
34ac7ddfbfSEd Maste
35ac7ddfbfSEd Maste private:
36ac7ddfbfSEd Maste void *m_sp_this;
37ac7ddfbfSEd Maste std::vector<void *> m_frames;
38ac7ddfbfSEd Maste };
39ac7ddfbfSEd Maste
Backtrace()40435933ddSDimitry Andric Backtrace::Backtrace() : m_frames() {}
41ac7ddfbfSEd Maste
~Backtrace()42435933ddSDimitry Andric Backtrace::~Backtrace() {}
43ac7ddfbfSEd Maste
GetFrames()44435933ddSDimitry Andric void Backtrace::GetFrames() {
45ac7ddfbfSEd Maste void *frames[1024];
460127ef0fSEd Maste const int count = ::backtrace(frames, llvm::array_lengthof(frames));
47ac7ddfbfSEd Maste if (count > 2)
48ac7ddfbfSEd Maste m_frames.assign(frames + 2, frames + (count - 2));
49ac7ddfbfSEd Maste }
50ac7ddfbfSEd Maste
Dump() const51435933ddSDimitry Andric void Backtrace::Dump() const {
52ac7ddfbfSEd Maste if (!m_frames.empty())
53ac7ddfbfSEd Maste ::backtrace_symbols_fd(m_frames.data(), m_frames.size(), STDOUT_FILENO);
54ac7ddfbfSEd Maste write(STDOUT_FILENO, "\n\n", 2);
55ac7ddfbfSEd Maste }
56ac7ddfbfSEd Maste
track_sp(void * sp_this,void * ptr,long use_count)57435933ddSDimitry Andric extern "C" void track_sp(void *sp_this, void *ptr, long use_count) {
58ac7ddfbfSEd Maste typedef std::pair<void *, Backtrace> PtrBacktracePair;
59ac7ddfbfSEd Maste typedef std::map<void *, PtrBacktracePair> PtrToBacktraceMap;
604bb0738eSEd Maste static std::mutex g_mutex;
614bb0738eSEd Maste std::lock_guard<std::mutex> guard(g_mutex);
62ac7ddfbfSEd Maste static PtrToBacktraceMap g_map;
63ac7ddfbfSEd Maste
64435933ddSDimitry Andric if (sp_this) {
65ac7ddfbfSEd Maste printf("sp(%p) -> %p %lu\n", sp_this, ptr, use_count);
66ac7ddfbfSEd Maste
67435933ddSDimitry Andric if (ptr) {
68ac7ddfbfSEd Maste Backtrace bt;
69ac7ddfbfSEd Maste bt.GetFrames();
70ac7ddfbfSEd Maste g_map[sp_this] = std::make_pair(ptr, bt);
71435933ddSDimitry Andric } else {
72ac7ddfbfSEd Maste g_map.erase(sp_this);
73ac7ddfbfSEd Maste }
74435933ddSDimitry Andric } else {
75ac7ddfbfSEd Maste if (ptr)
76ac7ddfbfSEd Maste printf("Searching for shared pointers that are tracking %p: ", ptr);
77ac7ddfbfSEd Maste else
78ac7ddfbfSEd Maste printf("Dump all live shared pointres: ");
79ac7ddfbfSEd Maste
80ac7ddfbfSEd Maste uint32_t matches = 0;
81ac7ddfbfSEd Maste PtrToBacktraceMap::iterator pos, end = g_map.end();
82435933ddSDimitry Andric for (pos = g_map.begin(); pos != end; ++pos) {
83435933ddSDimitry Andric if (ptr == NULL || pos->second.first == ptr) {
84ac7ddfbfSEd Maste ++matches;
85ac7ddfbfSEd Maste printf("\nsp(%p): %p\n", pos->first, pos->second.first);
86ac7ddfbfSEd Maste pos->second.second.Dump();
87ac7ddfbfSEd Maste }
88ac7ddfbfSEd Maste }
89435933ddSDimitry Andric if (matches == 0) {
90ac7ddfbfSEd Maste printf("none.\n");
91ac7ddfbfSEd Maste }
92ac7ddfbfSEd Maste }
93ac7ddfbfSEd Maste }
94435933ddSDimitry Andric // Put dump_sp_refs in the lldb namespace to it gets through our exports lists
95435933ddSDimitry Andric // filter in the LLDB.framework or lldb.so
96ac7ddfbfSEd Maste namespace lldb {
97ac7ddfbfSEd Maste
dump_sp_refs(void * ptr)98435933ddSDimitry Andric void dump_sp_refs(void *ptr) {
99*4ba319b5SDimitry Andric // Use a specially crafted call to "track_sp" which will dump info on all
100*4ba319b5SDimitry Andric // live shared pointers that reference "ptr"
101ac7ddfbfSEd Maste track_sp(NULL, ptr, 0);
102ac7ddfbfSEd Maste }
103ac7ddfbfSEd Maste }
104ac7ddfbfSEd Maste
105ac7ddfbfSEd Maste #endif
106ac7ddfbfSEd Maste
107ac7ddfbfSEd Maste namespace lldb_private {
108ac7ddfbfSEd Maste
109435933ddSDimitry Andric namespace imp {
110ac7ddfbfSEd Maste
~shared_count()111435933ddSDimitry Andric shared_count::~shared_count() {}
112ac7ddfbfSEd Maste
add_shared()113435933ddSDimitry Andric void shared_count::add_shared() {
11435617911SEd Maste #ifdef _MSC_VER
11535617911SEd Maste _InterlockedIncrement(&shared_owners_);
11635617911SEd Maste #else
11735617911SEd Maste ++shared_owners_;
11835617911SEd Maste #endif
119ac7ddfbfSEd Maste }
120ac7ddfbfSEd Maste
release_shared()121435933ddSDimitry Andric void shared_count::release_shared() {
12235617911SEd Maste #ifdef _MSC_VER
12335617911SEd Maste if (_InterlockedDecrement(&shared_owners_) == -1)
12435617911SEd Maste #else
12535617911SEd Maste if (--shared_owners_ == -1)
12635617911SEd Maste #endif
127ac7ddfbfSEd Maste {
128ac7ddfbfSEd Maste on_zero_shared();
129ac7ddfbfSEd Maste delete this;
130ac7ddfbfSEd Maste }
131ac7ddfbfSEd Maste }
132ac7ddfbfSEd Maste
133ac7ddfbfSEd Maste } // imp
134ac7ddfbfSEd Maste
135ac7ddfbfSEd Maste } // namespace lldb
136