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