The open source OpenXR runtime
at main 214 lines 4.1 kB view raw
1// Copyright 2019-2022, Collabora, Ltd. 2// SPDX-License-Identifier: BSL-1.0 3/*! 4 * @file 5 * @brief Variable tracking code. 6 * @author Jakob Bornecrantz <jakob@collabora.com> 7 * @ingroup aux_util 8 */ 9 10#include "util/u_var.h" 11#include "util/u_debug.h" 12 13#include <string> 14#include <sstream> 15#include <vector> 16#include <unordered_map> 17#include <mutex> 18 19 20namespace xrt::auxiliary::util { 21 22 23/* 24 * 25 * Enums, Classes and Defines. 26 * 27 */ 28 29/*! 30 * Simple container for the variable information. 31 */ 32class Var 33{ 34public: 35 struct u_var_info info = {}; 36}; 37 38/*! 39 * Object that has a series of tracked variables. 40 */ 41class Obj 42{ 43public: 44 std::string name = {}; 45 std::string raw_name = {}; 46 struct u_var_root_info info = {}; 47 std::vector<Var> vars = {}; 48}; 49 50/*! 51 * Object that has a series of tracked variables. 52 */ 53class Tracker 54{ 55public: 56 std::unordered_map<std::string, uint32_t> counters = {}; 57 std::unordered_map<ptrdiff_t, Obj> map = {}; 58 std::mutex mutex = {}; 59 bool on = false; 60 bool tested = false; 61 62public: 63 uint32_t 64 getNumber(const std::string &name) 65 { 66 auto s = counters.find(name); 67 uint32_t count = (s != counters.end() ? s->second : 0u) + 1u; 68 counters[name] = count; 69 70 return count; 71 } 72}; 73 74/*! 75 * Global variable tracking state. 76 */ 77static class Tracker gTracker; 78 79 80/* 81 * 82 * Helper functions. 83 * 84 */ 85 86static bool 87get_on() 88{ 89 if (gTracker.tested) { 90 return gTracker.on; 91 } 92 gTracker.on = debug_get_bool_option("XRT_TRACK_VARIABLES", false); 93 gTracker.tested = true; 94 95 return gTracker.on; 96} 97 98static void 99add_var(void *root, void *ptr, u_var_kind kind, const char *c_name) 100{ 101 auto s = gTracker.map.find((ptrdiff_t)root); 102 if (s == gTracker.map.end()) { 103 return; 104 } 105 106 Var var; 107 snprintf(var.info.name, U_VAR_NAME_STRING_SIZE, "%s", c_name); 108 var.info.kind = kind; 109 var.info.ptr = ptr; 110 111 s->second.vars.push_back(var); 112} 113 114 115/* 116 * 117 * Exported functions. 118 * 119 */ 120 121extern "C" void 122u_var_force_on(void) 123{ 124 gTracker.on = true; 125 gTracker.tested = true; 126} 127 128extern "C" void 129u_var_add_root(void *root, const char *c_name, bool suffix_with_number) 130{ 131 if (!get_on()) { 132 return; 133 } 134 135 std::unique_lock<std::mutex> lock(gTracker.mutex); 136 137 auto name = std::string(c_name); 138 auto raw_name = name; 139 uint32_t count = 0; // Zero means no number. 140 141 if (suffix_with_number) { 142 count = gTracker.getNumber(name); 143 144 std::stringstream ss; 145 ss << name << " #" << count; 146 name = ss.str(); 147 } 148 149 auto &obj = gTracker.map[(ptrdiff_t)root] = Obj(); 150 obj.name = name; 151 obj.raw_name = raw_name; 152 obj.info.name = obj.name.c_str(); 153 obj.info.raw_name = obj.raw_name.c_str(); 154 obj.info.number = count; 155} 156 157extern "C" void 158u_var_remove_root(void *root) 159{ 160 if (!get_on()) { 161 return; 162 } 163 164 std::unique_lock<std::mutex> lock(gTracker.mutex); 165 166 auto s = gTracker.map.find((ptrdiff_t)root); 167 if (s == gTracker.map.end()) { 168 return; 169 } 170 171 gTracker.map.erase(s); 172} 173 174extern "C" void 175u_var_visit(u_var_root_cb enter_cb, u_var_root_cb exit_cb, u_var_elm_cb elem_cb, void *priv) 176{ 177 if (!get_on()) { 178 return; 179 } 180 181 std::unique_lock<std::mutex> lock(gTracker.mutex); 182 183 std::vector<Obj *> tmp; 184 tmp.reserve(gTracker.map.size()); 185 186 for (auto &n : gTracker.map) { 187 tmp.push_back(&n.second); 188 } 189 190 for (Obj *obj : tmp) { 191 enter_cb(&obj->info, priv); 192 193 for (auto &var : obj->vars) { 194 elem_cb(&var.info, priv); 195 } 196 197 exit_cb(&obj->info, priv); 198 } 199} 200 201#define ADD_FUNC(SUFFIX, TYPE, ENUM) \ 202 extern "C" void u_var_add_##SUFFIX(void *obj, TYPE *ptr, const char *c_name) \ 203 { \ 204 if (!get_on()) { \ 205 return; \ 206 } \ 207 add_var(obj, (void *)ptr, U_VAR_KIND_##ENUM, c_name); \ 208 } 209 210U_VAR_ADD_FUNCS() 211 212#undef ADD_FUNC 213 214} // namespace xrt::auxiliary::util