timemory 3.3.0
Modular C++ Toolkit for Performance Analysis and Logging. Profiling API and Tools for C, C++, CUDA, Fortran, and Python. The C++ template API is essentially a framework to creating tools: it is designed to provide a unifying interface for recording various performance measurements alongside data logging and interfaces to other tools.
weak.cpp
Go to the documentation of this file.
1// MIT License
2//
3// Copyright (c) 2020, The Regents of the University of California,
4// through Lawrence Berkeley National Laboratory (subject to receipt of any
5// required approvals from the U.S. Dept. of Energy). All rights reserved.
6//
7// Permission is hereby granted, free of charge, to any person obtaining a copy
8// of this software and associated documentation files (the "Software"), to deal
9// in the Software without restriction, including without limitation the rights
10// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11// copies of the Software, and to permit persons to whom the Software is
12// furnished to do so, subject to the following conditions:
13//
14// The above copyright notice and this permission notice shall be included in all
15// copies or substantial portions of the Software.
16//
17// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23// SOFTWARE.
24
25#if !defined(TIMEMORY_LIBRARY_SOURCE)
26# define TIMEMORY_LIBRARY_SOURCE 1
27#endif
28
29#include "timemory/backends/process.hpp"
33#include "timemory/library.h"
34#include "timemory/settings.hpp"
35
36#include <cstdint>
37#include <limits>
38#include <numeric>
39
40#if !defined(TIMEMORY_WINDOWS)
41# include <dlfcn.h>
42#endif
43
44// Macro for obtaining jump pointer function association
45#if defined(TIMEMORY_WINDOWS)
46# define DLSYM_FUNCTION(VARNAME, HANDLE, FUNCNAME)
47#else
48# define DLSYM_FUNCTION(VARNAME, HANDLE, FUNCNAME) \
49 if(HANDLE) \
50 { \
51 *(void**) (&VARNAME) = dlsym(HANDLE, FUNCNAME.c_str()); \
52 if(VARNAME == nullptr) \
53 { \
54 fprintf(stderr, "[%s][pid=%i]> %s\n", FUNCNAME.c_str(), \
55 tim::process::get_id(), dlerror()); \
56 } \
57 } \
58 else \
59 { \
60 VARNAME = nullptr; \
61 }
62#endif
63
64#if !defined(OS_DYNAMIC_LIBRARY_EXT)
65# if defined(TIMEMORY_MACOS)
66# define OS_DYNAMIC_LIBRARY_EXT "dylib"
67# elif defined(TIMEMORY_WINDOWS)
68# define OS_DYNAMIC_LIBRARY_EXT "dll"
69# else
70# define OS_DYNAMIC_LIBRARY_EXT "so"
71# endif
72#endif
73
74struct tools_stubs_dlsym
75{
76 using ctor_function_t = void (*)();
77 using register_function_t = void (*)();
78 using deregister_function_t = void (*)();
79 using start_function_t = uint64_t (*)();
80 using stop_function_t = uint64_t (*)(uint64_t);
81
82 TIMEMORY_DEFAULT_OBJECT(tools_stubs_dlsym)
83
84 tools_stubs_dlsym(std::string id, std::string libname = "")
85 : m_id{ std::move(id) }
86 , m_libname{ std::move(libname) }
87 {
88 DEBUG_PRINT_HERE("id: %s, libname: %s", m_id.c_str(), m_libname.c_str());
89 load();
90 }
91
92 void load()
93 {
94#if !defined(TIMEMORY_WINDOWS)
95 if(m_libname.empty())
96 m_libname =
97 TIMEMORY_JOIN("", "libtimemory-", m_id, '.', OS_DYNAMIC_LIBRARY_EXT);
98
99 auto* libhandle = dlopen(m_libname.c_str(), RTLD_LAZY | RTLD_GLOBAL);
100
101 if(!libhandle)
102 {
104 fprintf(stderr, "%s\n", dlerror());
105 }
106
107 dlerror(); /* Clear any existing error */
108
109 auto ctor_name = TIMEMORY_JOIN("", "timemory_", m_id, "_library_ctor");
110 auto register_name = TIMEMORY_JOIN("", "timemory_register_", m_id);
111 auto deregister_name = TIMEMORY_JOIN("", "timemory_deregister_", m_id);
112 auto start_name = TIMEMORY_JOIN("", "timemory_start_", m_id);
113 auto stop_name = TIMEMORY_JOIN("", "timemory_stop_", m_id);
114
115 // Initialize all pointers
116 DLSYM_FUNCTION(m_ctor, libhandle, ctor_name);
117 DLSYM_FUNCTION(m_register, libhandle, register_name);
118 DLSYM_FUNCTION(m_deregister, libhandle, deregister_name);
119 DLSYM_FUNCTION(m_start, libhandle, start_name);
120 DLSYM_FUNCTION(m_stop, libhandle, stop_name);
121#endif
122 }
123
124 void invoke_ctor()
125 {
126 if(m_ctor)
127 (*m_ctor)();
128 }
129
130 void invoke_register()
131 {
132 if(m_register)
133 (*m_register)();
134 }
135
136 void invoke_deregister()
137 {
138 if(m_deregister)
139 (*m_deregister)();
140 }
141
142 uint64_t invoke_start()
143 {
144 if(m_start)
145 return (*m_start)();
146 return 0;
147 }
148
149 uint64_t invoke_stop(uint64_t val)
150 {
151 if(m_stop)
152 return (*m_stop)(val);
153 return 0;
154 }
155
156private:
157 std::string m_id = {};
158 std::string m_libname = {};
159 ctor_function_t m_ctor = nullptr;
160 register_function_t m_register = nullptr;
161 deregister_function_t m_deregister = nullptr;
162 start_function_t m_start = nullptr;
163 stop_function_t m_stop = nullptr;
164};
165
167{
172};
173
174template <int Idx>
175tools_stubs_dlsym*
177
178#define TOOL_DLSYM_SPECIALIZAITON(INDEX, ID, ENV_VAR) \
179 template <> \
180 tools_stubs_dlsym* get_tool_stubs<INDEX>() \
181 { \
182 static auto _instance = std::unique_ptr<tools_stubs_dlsym>{}; \
183 if(!_instance) \
184 { \
185 auto _env = tim::get_env<std::string>(ENV_VAR, ""); \
186 _instance = std::make_unique<tools_stubs_dlsym>(ID, _env); \
187 } \
188 return _instance.get(); \
189 }
190
191TOOL_DLSYM_SPECIALIZAITON(mpip_idx, "mpip", "TIMEMORY_MPIP_LIBRARY")
192TOOL_DLSYM_SPECIALIZAITON(ompt_idx, "ompt", "TIMEMORY_OMPT_LIBRARY")
193TOOL_DLSYM_SPECIALIZAITON(ncclp_idx, "ncclp", "TIMEMORY_NCCLP_LIBRARY")
194TOOL_DLSYM_SPECIALIZAITON(mallocp_idx, "mallocp", "TIMEMORY_MALLOCP_LIBRARY")
195
196#define TOOL_INDEX(NAME) NAME##_idx
197#define TOOL_DLSYM(NAME) get_tool_stubs<TOOL_INDEX(NAME)>()
198#define TOOL_PREFIX TIMEMORY_WEAK_PREFIX
199#define TOOL_SUFFIX TIMEMORY_WEAK_POSTFIX TIMEMORY_VISIBILITY("default")
200#define TOOL_STUBS(NAME) \
201 TOOL_PREFIX \
202 void timemory_##NAME##_library_ctor() TOOL_SUFFIX; \
203 TOOL_PREFIX \
204 void timemory_register_##NAME() TOOL_SUFFIX; \
205 TOOL_PREFIX \
206 void timemory_deregister_##NAME() TOOL_SUFFIX; \
207 TOOL_PREFIX \
208 uint64_t timemory_start_##NAME() TOOL_SUFFIX; \
209 TOOL_PREFIX \
210 uint64_t timemory_stop_##NAME(uint64_t) TOOL_SUFFIX; \
211 \
212 void timemory_##NAME##_library_ctor() { TOOL_DLSYM(NAME)->invoke_ctor(); } \
213 void timemory_register_##NAME() { TOOL_DLSYM(NAME)->invoke_register(); } \
214 void timemory_deregister_##NAME() { TOOL_DLSYM(NAME)->invoke_deregister(); } \
215 uint64_t timemory_start_##NAME() { return TOOL_DLSYM(NAME)->invoke_start(); } \
216 uint64_t timemory_stop_##NAME(uint64_t v) { return TOOL_DLSYM(NAME)->invoke_stop(v); }
217
218extern "C"
219{
220 //
221 //----------------------------------------------------------------------------------//
222 //
226 TOOL_STUBS(mallocp)
227 //
228 //----------------------------------------------------------------------------------//
229 //
230}
void load(Archive &ar, tim::node::graph< Tp > &d)
Definition: node.hpp:520
tim::mpl::apply< std::string > string
Definition: macros.hpp:53
#define DEBUG_PRINT_HERE(...)
Definition: macros.hpp:168
#define TIMEMORY_JOIN(delim,...)
Definition: macros.hpp:90
TOOL_STUB_IDS
Definition: weak.cpp:167
@ mpip_idx
Definition: weak.cpp:168
@ ncclp_idx
Definition: weak.cpp:170
@ ompt_idx
Definition: weak.cpp:169
@ mallocp_idx
Definition: weak.cpp:171
#define DLSYM_FUNCTION(VARNAME, HANDLE, FUNCNAME)
Definition: weak.cpp:48
#define TOOL_DLSYM_SPECIALIZAITON(INDEX, ID, ENV_VAR)
Definition: weak.cpp:178
#define OS_DYNAMIC_LIBRARY_EXT
Definition: weak.cpp:70
#define TOOL_STUBS(NAME)
Definition: weak.cpp:200
tools_stubs_dlsym * get_tool_stubs()