1 //---------------------------------------------------------------------- 2 // This software is part of the Haiku distribution and is covered 3 // by the MIT License. 4 // 5 // This version copyright (c) 2003 Tyler Dauwalder, tyler@dauwalder.net 6 // Initial version copyright (c) 2002 Axel Dörfler, axeld@pinc-software.de 7 //---------------------------------------------------------------------- 8 9 /*! \file Debug.cpp 10 11 Support code for handy debugging macros. 12 */ 13 14 #include "UdfDebug.h" 15 16 #include <stdlib.h> 17 #include <string.h> 18 #include <KernelExport.h> 19 #include <TLS.h> 20 21 //---------------------------------------------------------------------- 22 // Long-winded overview of the debug output macros: 23 //---------------------------------------------------------------------- 24 /*! \def DEBUG_INIT() 25 \brief Increases the indentation level, prints out the enclosing function's 26 name, and creates a \c DebugHelper object on the stack to automatically 27 decrease the indentation level upon function exit. 28 29 This macro should be called at the very beginning of any function in 30 which you wish to use any of the other debugging macros. 31 32 If DEBUG is undefined, does nothing. 33 */ 34 //---------------------------------------------------------------------- 35 /*! \def PRINT(x) 36 \brief Prints out the enclosing function's name followed by the contents 37 of \a x at the current indentation level. 38 39 \param x A printf-style format string enclosed in an extra set of parenteses, 40 e.g. PRINT(("%d\n", 0)); 41 42 If DEBUG is undefined, does nothing. 43 */ 44 //---------------------------------------------------------------------- 45 /*! \def LPRINT(x) 46 \brief Identical to \c PRINT(x), except that the line number in the source 47 file at which the macro is invoked is also printed. 48 49 \param x A printf-style format string enclosed in an extra set of parenteses, 50 e.g. PRINT(("%d\n", 0)); 51 52 If DEBUG is undefined, does nothing. 53 */ 54 //---------------------------------------------------------------------- 55 /*! \def SIMPLE_PRINT(x) 56 \brief Directly prints the contents of \a x with no extra formatting or 57 information included (just like a straight \c printf() call). 58 59 \param x A printf-style format string enclosed in an extra set of parenteses, 60 e.g. PRINT(("%d\n", 0)); 61 62 If DEBUG is undefined, does nothing. 63 */ 64 //---------------------------------------------------------------------- 65 /*! \def PRINT_INDENT() 66 \brief Prints out enough indentation characters to indent the current line 67 to the current indentation level (assuming the cursor was flush left to 68 begin with...). 69 70 This function is called by the other \c *PRINT* macros, and isn't really 71 intended for general consumption, but you might find it useful. 72 73 If DEBUG is undefined, does nothing. 74 */ 75 //---------------------------------------------------------------------- 76 /*! \def REPORT_ERROR(error) 77 \brief Calls \c LPRINT(x) with a format string listing the error 78 code in \c error (assumed to be a \c status_t value) and the 79 corresponding text error code returned by a call to \c strerror(). 80 81 This function is called by the \c RETURN* macros, and isn't really 82 intended for general consumption, but you might find it useful. 83 84 \param error A \c status_t error code to report. 85 86 If DEBUG is undefined, does nothing. 87 */ 88 //---------------------------------------------------------------------- 89 /*! \def RETURN_ERROR(error) 90 \brief Calls \c REPORT_ERROR(error) if error is a an error code (i.e. 91 negative), otherwise remains silent. In either case, the enclosing 92 function is then exited with a call to \c "return error;". 93 94 \param error A \c status_t error code to report (if negative) and return. 95 96 If DEBUG is undefined, silently returns the value in \c error. 97 */ 98 //---------------------------------------------------------------------- 99 /*! \def RETURN(error) 100 \brief Prints out a description of the error code being returned 101 (which, in this case, may be either "erroneous" or "successful") 102 and then exits the enclosing function with a call to \c "return error;". 103 104 \param error A \c status_t error code to report and return. 105 106 If DEBUG is undefined, silently returns the value in \c error. 107 */ 108 //---------------------------------------------------------------------- 109 /*! \def FATAL(x) 110 \brief Prints out a fatal error message. 111 112 This one's still a work in progress... 113 114 \param x A printf-style format string enclosed in an extra set of parenteses, 115 e.g. PRINT(("%d\n", 0)); 116 117 If DEBUG is undefined, does nothing. 118 */ 119 //---------------------------------------------------------------------- 120 /*! \def INFORM(x) 121 \brief Directly prints the contents of \a x with no extra formatting or 122 information included (just like a straight \c printf() call). Does so 123 whether \c DEBUG is defined or not. 124 125 \param x A printf-style format string enclosed in an extra set of parenteses, 126 e.g. PRINT(("%d\n", 0)); 127 128 I'll say it again: Prints its output regardless to DEBUG being defined or 129 undefined. 130 */ 131 //---------------------------------------------------------------------- 132 /*! \def DBG(x) 133 \brief If debug is defined, \a x is passed along to the code and 134 executed unmodified. If \c DEBUG is undefined, the contents of 135 \a x disappear into the ether. 136 137 \param x Damn near anything resembling valid C\C++. 138 */ 139 //---------------------------------------------------------------------- 140 /*! \def DIE(x) 141 \brief Drops the user into the appropriate debugger (user or kernel) 142 after printing out the handy message bundled in the parenthesee 143 enclosed printf-style format string found in \a x. 144 145 \param x A printf-style format string enclosed in an extra set of parenteses, 146 e.g. PRINT(("%d\n", 0)); 147 */ 148 149 150 //---------------------------------------------------------------------- 151 // declarations 152 //---------------------------------------------------------------------- 153 154 static void indent(uint8 tabCount); 155 static void unindent(uint8 tabCount); 156 #if !_KERNEL_MODE 157 static int32 get_tls_handle(); 158 #endif 159 160 //! Used to keep the tls handle from being allocated more than once. 161 int32 tls_spinlock = 0; 162 163 /*! \brief Used to flag whether the tls handle has been allocated yet. 164 165 Not sure if this really needs to be \c volatile or not... 166 */ 167 volatile bool tls_handle_initialized = false; 168 169 //! The tls handle of the tls var used to store indentation info. 170 int32 tls_handle = 0; 171 172 //---------------------------------------------------------------------- 173 // public functions 174 //---------------------------------------------------------------------- 175 176 /*! \brief Returns the current debug indentation level for the 177 current thread. 178 179 NOTE: indentation is currently unsupported for R5::kernelland due 180 to lack of thread local storage support. 181 */ 182 int32 183 _get_debug_indent_level() 184 { 185 #if !_KERNEL_MODE 186 return (addr_t)tls_get(get_tls_handle()); 187 #else 188 return 1; 189 #endif 190 } 191 192 //---------------------------------------------------------------------- 193 // static functions 194 //---------------------------------------------------------------------- 195 196 /*! \brief Increases the current debug indentation level for 197 the current thread by 1. 198 */ 199 void 200 indent(uint8 tabCount) 201 { 202 #if !_KERNEL_MODE 203 tls_set(get_tls_handle(), 204 (void*)(addr_t(_get_debug_indent_level()+tabCount))); 205 #endif 206 } 207 208 /*! \brief Decreases the current debug indentation level for 209 the current thread by 1. 210 */ 211 void 212 unindent(uint8 tabCount) 213 { 214 #if !_KERNEL_MODE 215 tls_set(get_tls_handle(), 216 (void*)(addr_t(_get_debug_indent_level()-tabCount))); 217 #endif 218 } 219 220 #if !_KERNEL_MODE 221 /*! \brief Returns the thread local storage handle used to store 222 indentation information, allocating the handle first if 223 necessary. 224 */ 225 int32 226 get_tls_handle() 227 { 228 // Init the tls handle if this is the first call. 229 if (!tls_handle_initialized) { 230 if (atomic_or(&tls_spinlock, 1) == 0) { 231 // First one in gets to init 232 tls_handle = tls_allocate(); 233 tls_handle_initialized = true; 234 atomic_and(&tls_spinlock, 0); 235 } else { 236 // All others must wait patiently 237 while (!tls_handle_initialized) { 238 snooze(1); 239 } 240 } 241 } 242 return tls_handle; 243 } 244 #endif 245 246 /*! \brief Helper class for initializing the debugging output 247 file. 248 249 Note that this hummer isn't threadsafe, but it doesn't really 250 matter for our concerns, since the worst it'll result in is 251 a dangling file descriptor, and that would be in the case of 252 two or more volumes being mounted almost simultaneously... 253 not too big of a worry. 254 */ 255 class DebugOutputFile { 256 public: 257 DebugOutputFile(const char *filename = NULL) 258 : fFile(-1) 259 { 260 Init(filename); 261 } 262 263 ~DebugOutputFile() { 264 if (fFile >= 0) 265 close(fFile); 266 } 267 268 void Init(const char *filename) { 269 if (fFile < 0 && filename) 270 fFile = open(filename, O_RDWR | O_CREAT | O_TRUNC); 271 } 272 273 int File() const { return fFile; } 274 private: 275 int fFile; 276 }; 277 278 DebugOutputFile *out = NULL; 279 280 /*! \brief It doesn't appear that the constructor for the global 281 \c out variable is called when built as an R5 filesystem add-on, 282 so this function needs to be called in udf_mount to let the 283 magic happen. 284 */ 285 void initialize_debugger(const char *filename) 286 { 287 #if DEBUG_TO_FILE 288 if (!out) { 289 out = new(nothrow) DebugOutputFile(filename); 290 dbg_printf("out was NULL!\n"); 291 } else { 292 DebugOutputFile *temp = out; 293 out = new(nothrow) DebugOutputFile(filename); 294 dbg_printf("out was %p!\n", temp); 295 } 296 #endif 297 } 298 299 // dbg_printf, stolen from Ingo's ReiserFS::Debug.cpp. 300 void 301 dbg_printf(const char *format,...) 302 { 303 #if DEBUG_TO_FILE 304 if (!out) 305 return; 306 307 char buffer[1024]; 308 va_list args; 309 va_start(args, format); 310 // no vsnprintf() on PPC 311 #if defined(__i386__) && !_KERNEL_MODE 312 vsnprintf(buffer, sizeof(buffer) - 1, format, args); 313 #else 314 vsprintf(buffer, format, args); 315 #endif 316 va_end(args); 317 buffer[sizeof(buffer) - 1] = '\0'; 318 write(out->File(), buffer, strlen(buffer)); 319 #endif 320 } 321 322 //---------------------------------------------------------------------- 323 // DebugHelper 324 //---------------------------------------------------------------------- 325 326 /*! \brief Increases the current indentation level. 327 */ 328 DebugHelper::DebugHelper(const char *className, uint8 tabCount) 329 : fTabCount(tabCount) 330 , fClassName(NULL) 331 { 332 indent(fTabCount); 333 if (className) { 334 fClassName = (char*)malloc(strlen(className)+1); 335 if (fClassName) 336 strcpy(fClassName, className); 337 } 338 } 339 340 /*! \brief Decreases the current indentation level. 341 */ 342 DebugHelper::~DebugHelper() 343 { 344 unindent(fTabCount); 345 free(fClassName); 346 } 347 348