1 //===-- DNBLog.cpp ----------------------------------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // Created by Greg Clayton on 6/18/07. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "DNBLog.h" 15 16 static int g_debug = 0; 17 static int g_verbose = 0; 18 19 #if defined (DNBLOG_ENABLED) 20 21 #include <stdio.h> 22 #include <stdarg.h> 23 #include <stdlib.h> 24 #include <sys/time.h> 25 #include <unistd.h> 26 #include <mach/mach.h> 27 #include <pthread.h> 28 #include "PThreadMutex.h" 29 30 uint32_t g_log_bits = 0; 31 static DNBCallbackLog g_log_callback = NULL; 32 static void *g_log_baton = NULL; 33 34 35 int 36 DNBLogGetDebug () 37 { 38 return g_debug; 39 } 40 41 42 void 43 DNBLogSetDebug (int g) 44 { 45 g_debug = g; 46 } 47 48 int 49 DNBLogGetVerbose () 50 { 51 return g_verbose; 52 } 53 54 void 55 DNBLogSetVerbose (int v) 56 { 57 g_verbose = v; 58 } 59 60 bool 61 DNBLogCheckLogBit (uint32_t bit) 62 { 63 return (g_log_bits & bit) != 0; 64 } 65 66 uint32_t 67 DNBLogSetLogMask (uint32_t mask) 68 { 69 uint32_t old = g_log_bits; 70 g_log_bits = mask; 71 return old; 72 } 73 74 uint32_t 75 DNBLogGetLogMask () 76 { 77 return g_log_bits; 78 } 79 80 void 81 DNBLogSetLogCallback (DNBCallbackLog callback, void *baton) 82 { 83 g_log_callback = callback; 84 g_log_baton = baton; 85 } 86 87 DNBCallbackLog 88 DNBLogGetLogCallback () 89 { 90 return g_log_callback; 91 } 92 93 bool 94 DNBLogEnabled () 95 { 96 return g_log_callback != NULL; 97 } 98 99 bool 100 DNBLogEnabledForAny (uint32_t mask) 101 { 102 if (g_log_callback) 103 return (g_log_bits & mask) != 0; 104 return false; 105 } 106 static inline void 107 _DNBLogVAPrintf(uint32_t flags, const char *format, va_list args) 108 { 109 static PThreadMutex g_LogThreadedMutex(PTHREAD_MUTEX_RECURSIVE); 110 PTHREAD_MUTEX_LOCKER(locker, g_LogThreadedMutex); 111 112 if (g_log_callback) 113 g_log_callback(g_log_baton, flags, format, args); 114 } 115 116 void 117 _DNBLog(uint32_t flags, const char *format, ...) 118 { 119 va_list args; 120 va_start (args, format); 121 _DNBLogVAPrintf(flags, format, args); 122 va_end (args); 123 } 124 125 //---------------------------------------------------------------------- 126 // Print debug strings if and only if the global g_debug is set to 127 // a non-zero value. 128 //---------------------------------------------------------------------- 129 void 130 _DNBLogDebug (const char *format, ...) 131 { 132 if (DNBLogEnabled () && g_debug) 133 { 134 va_list args; 135 va_start (args, format); 136 _DNBLogVAPrintf(DNBLOG_FLAG_DEBUG, format, args); 137 va_end (args); 138 } 139 } 140 141 142 //---------------------------------------------------------------------- 143 // Print debug strings if and only if the global g_debug is set to 144 // a non-zero value. 145 //---------------------------------------------------------------------- 146 void 147 _DNBLogDebugVerbose (const char *format, ...) 148 { 149 if (DNBLogEnabled () && g_debug && g_verbose) 150 { 151 va_list args; 152 va_start (args, format); 153 _DNBLogVAPrintf(DNBLOG_FLAG_DEBUG | DNBLOG_FLAG_VERBOSE, format, args); 154 va_end (args); 155 } 156 } 157 158 159 static uint32_t g_message_id = 0; 160 161 //---------------------------------------------------------------------- 162 // Prefix the formatted log string with process and thread IDs and 163 // suffix it with a newline. 164 //---------------------------------------------------------------------- 165 void 166 _DNBLogThreaded (const char *format, ...) 167 { 168 if (DNBLogEnabled ()) 169 { 170 //PTHREAD_MUTEX_LOCKER(locker, GetLogThreadedMutex()); 171 172 char *arg_msg = NULL; 173 va_list args; 174 va_start (args, format); 175 ::vasprintf (&arg_msg, format, args); 176 va_end (args); 177 178 if (arg_msg != NULL) 179 { 180 static struct timeval g_timeval = { 0 , 0 }; 181 static struct timeval tv; 182 static struct timeval delta; 183 gettimeofday(&tv, NULL); 184 if (g_timeval.tv_sec == 0) 185 { 186 delta.tv_sec = 0; 187 delta.tv_usec = 0; 188 } 189 else 190 { 191 timersub (&tv, &g_timeval, &delta); 192 } 193 g_timeval = tv; 194 195 // Calling "mach_port_deallocate()" bumps the reference count on the thread 196 // port, so we need to deallocate it. mach_task_self() doesn't bump the ref 197 // count. 198 thread_port_t thread_self = mach_thread_self(); 199 200 _DNBLog (DNBLOG_FLAG_THREADED, "%u +%lu.%06u sec [%4.4x/%4.4x]: %s", 201 ++g_message_id, 202 delta.tv_sec, 203 delta.tv_usec, 204 getpid(), 205 thread_self, 206 arg_msg); 207 208 mach_port_deallocate(mach_task_self(), thread_self); 209 free (arg_msg); 210 } 211 } 212 } 213 214 //---------------------------------------------------------------------- 215 // Prefix the formatted log string with process and thread IDs and 216 // suffix it with a newline. 217 //---------------------------------------------------------------------- 218 void 219 _DNBLogThreadedIf (uint32_t log_bit, const char *format, ...) 220 { 221 if (DNBLogEnabled () && (log_bit & g_log_bits) == log_bit) 222 { 223 //PTHREAD_MUTEX_LOCKER(locker, GetLogThreadedMutex()); 224 225 char *arg_msg = NULL; 226 va_list args; 227 va_start (args, format); 228 ::vasprintf (&arg_msg, format, args); 229 va_end (args); 230 231 if (arg_msg != NULL) 232 { 233 static struct timeval g_timeval = { 0 , 0 }; 234 static struct timeval tv; 235 static struct timeval delta; 236 gettimeofday(&tv, NULL); 237 if (g_timeval.tv_sec == 0) 238 { 239 delta.tv_sec = 0; 240 delta.tv_usec = 0; 241 } 242 else 243 { 244 timersub (&tv, &g_timeval, &delta); 245 } 246 g_timeval = tv; 247 248 // Calling "mach_port_deallocate()" bumps the reference count on the thread 249 // port, so we need to deallocate it. mach_task_self() doesn't bump the ref 250 // count. 251 thread_port_t thread_self = mach_thread_self(); 252 253 _DNBLog (DNBLOG_FLAG_THREADED, "%u +%lu.%06u sec [%4.4x/%4.4x]: %s", 254 ++g_message_id, 255 delta.tv_sec, 256 delta.tv_usec, 257 getpid(), 258 thread_self, 259 arg_msg); 260 261 mach_port_deallocate(mach_task_self(), thread_self); 262 263 free (arg_msg); 264 } 265 } 266 } 267 268 269 270 //---------------------------------------------------------------------- 271 // Printing of errors that are not fatal. 272 //---------------------------------------------------------------------- 273 void 274 _DNBLogError (const char *format, ...) 275 { 276 if (DNBLogEnabled ()) 277 { 278 char *arg_msg = NULL; 279 va_list args; 280 va_start (args, format); 281 ::vasprintf (&arg_msg, format, args); 282 va_end (args); 283 284 if (arg_msg != NULL) 285 { 286 _DNBLog (DNBLOG_FLAG_ERROR, "error: %s", arg_msg); 287 free (arg_msg); 288 } 289 } 290 } 291 292 //---------------------------------------------------------------------- 293 // Printing of errors that ARE fatal. Exit with ERR exit code 294 // immediately. 295 //---------------------------------------------------------------------- 296 void 297 _DNBLogFatalError (int err, const char *format, ...) 298 { 299 if (DNBLogEnabled ()) 300 { 301 char *arg_msg = NULL; 302 va_list args; 303 va_start (args, format); 304 ::vasprintf (&arg_msg, format, args); 305 va_end (args); 306 307 if (arg_msg != NULL) 308 { 309 _DNBLog (DNBLOG_FLAG_ERROR | DNBLOG_FLAG_FATAL, "error: %s", arg_msg); 310 free (arg_msg); 311 } 312 ::exit (err); 313 } 314 } 315 316 317 //---------------------------------------------------------------------- 318 // Printing of warnings that are not fatal only if verbose mode is 319 // enabled. 320 //---------------------------------------------------------------------- 321 void 322 _DNBLogVerbose (const char *format, ...) 323 { 324 if (DNBLogEnabled () && g_verbose) 325 { 326 va_list args; 327 va_start (args, format); 328 _DNBLogVAPrintf(DNBLOG_FLAG_VERBOSE, format, args); 329 va_end (args); 330 } 331 } 332 333 //---------------------------------------------------------------------- 334 // Printing of warnings that are not fatal only if verbose mode is 335 // enabled. 336 //---------------------------------------------------------------------- 337 void 338 _DNBLogWarningVerbose (const char *format, ...) 339 { 340 if (DNBLogEnabled () && g_verbose) 341 { 342 char *arg_msg = NULL; 343 va_list args; 344 va_start (args, format); 345 ::vasprintf (&arg_msg, format, args); 346 va_end (args); 347 348 if (arg_msg != NULL) 349 { 350 _DNBLog (DNBLOG_FLAG_WARNING | DNBLOG_FLAG_VERBOSE, "warning: %s", arg_msg); 351 free (arg_msg); 352 } 353 } 354 } 355 //---------------------------------------------------------------------- 356 // Printing of warnings that are not fatal. 357 //---------------------------------------------------------------------- 358 void 359 _DNBLogWarning (const char *format, ...) 360 { 361 if (DNBLogEnabled ()) 362 { 363 char *arg_msg = NULL; 364 va_list args; 365 va_start (args, format); 366 ::vasprintf (&arg_msg, format, args); 367 va_end (args); 368 369 if (arg_msg != NULL) 370 { 371 _DNBLog (DNBLOG_FLAG_WARNING, "warning: %s", arg_msg); 372 free (arg_msg); 373 } 374 } 375 } 376 377 #endif 378