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 bool 88 DNBLogEnabled () 89 { 90 return g_log_callback != NULL; 91 } 92 93 bool 94 DNBLogEnabledForAny (uint32_t mask) 95 { 96 if (g_log_callback) 97 return (g_log_bits & mask) != 0; 98 return false; 99 } 100 static inline void 101 _DNBLogVAPrintf(uint32_t flags, const char *format, va_list args) 102 { 103 static PThreadMutex g_LogThreadedMutex(PTHREAD_MUTEX_RECURSIVE); 104 PTHREAD_MUTEX_LOCKER(locker, g_LogThreadedMutex); 105 106 if (g_log_callback) 107 g_log_callback(g_log_baton, flags, format, args); 108 } 109 110 void 111 _DNBLog(uint32_t flags, const char *format, ...) 112 { 113 va_list args; 114 va_start (args, format); 115 _DNBLogVAPrintf(flags, format, args); 116 va_end (args); 117 } 118 119 //---------------------------------------------------------------------- 120 // Print debug strings if and only if the global g_debug is set to 121 // a non-zero value. 122 //---------------------------------------------------------------------- 123 void 124 _DNBLogDebug (const char *format, ...) 125 { 126 if (DNBLogEnabled () && g_debug) 127 { 128 va_list args; 129 va_start (args, format); 130 _DNBLogVAPrintf(DNBLOG_FLAG_DEBUG, format, args); 131 va_end (args); 132 } 133 } 134 135 136 //---------------------------------------------------------------------- 137 // Print debug strings if and only if the global g_debug is set to 138 // a non-zero value. 139 //---------------------------------------------------------------------- 140 void 141 _DNBLogDebugVerbose (const char *format, ...) 142 { 143 if (DNBLogEnabled () && g_debug && g_verbose) 144 { 145 va_list args; 146 va_start (args, format); 147 _DNBLogVAPrintf(DNBLOG_FLAG_DEBUG | DNBLOG_FLAG_VERBOSE, format, args); 148 va_end (args); 149 } 150 } 151 152 153 static uint32_t g_message_id = 0; 154 155 //---------------------------------------------------------------------- 156 // Prefix the formatted log string with process and thread IDs and 157 // suffix it with a newline. 158 //---------------------------------------------------------------------- 159 void 160 _DNBLogThreaded (const char *format, ...) 161 { 162 if (DNBLogEnabled ()) 163 { 164 //PTHREAD_MUTEX_LOCKER(locker, GetLogThreadedMutex()); 165 166 char *arg_msg = NULL; 167 va_list args; 168 va_start (args, format); 169 ::vasprintf (&arg_msg, format, args); 170 va_end (args); 171 172 if (arg_msg != NULL) 173 { 174 static struct timeval g_timeval = { 0 , 0 }; 175 static struct timeval tv; 176 static struct timeval delta; 177 gettimeofday(&tv, NULL); 178 if (g_timeval.tv_sec == 0) 179 { 180 delta.tv_sec = 0; 181 delta.tv_usec = 0; 182 } 183 else 184 { 185 timersub (&tv, &g_timeval, &delta); 186 } 187 g_timeval = tv; 188 189 // Calling "mach_port_deallocate()" bumps the reference count on the thread 190 // port, so we need to deallocate it. mach_task_self() doesn't bump the ref 191 // count. 192 thread_port_t thread_self = mach_thread_self(); 193 194 _DNBLog (DNBLOG_FLAG_THREADED, "%u +%lu.%06u sec [%4.4x/%4.4x]: %s", 195 ++g_message_id, 196 delta.tv_sec, 197 delta.tv_usec, 198 getpid(), 199 thread_self, 200 arg_msg); 201 202 mach_port_deallocate(mach_task_self(), thread_self); 203 free (arg_msg); 204 } 205 } 206 } 207 208 //---------------------------------------------------------------------- 209 // Prefix the formatted log string with process and thread IDs and 210 // suffix it with a newline. 211 //---------------------------------------------------------------------- 212 void 213 _DNBLogThreadedIf (uint32_t log_bit, const char *format, ...) 214 { 215 if (DNBLogEnabled () && (log_bit & g_log_bits) == log_bit) 216 { 217 //PTHREAD_MUTEX_LOCKER(locker, GetLogThreadedMutex()); 218 219 char *arg_msg = NULL; 220 va_list args; 221 va_start (args, format); 222 ::vasprintf (&arg_msg, format, args); 223 va_end (args); 224 225 if (arg_msg != NULL) 226 { 227 static struct timeval g_timeval = { 0 , 0 }; 228 static struct timeval tv; 229 static struct timeval delta; 230 gettimeofday(&tv, NULL); 231 if (g_timeval.tv_sec == 0) 232 { 233 delta.tv_sec = 0; 234 delta.tv_usec = 0; 235 } 236 else 237 { 238 timersub (&tv, &g_timeval, &delta); 239 } 240 g_timeval = tv; 241 242 // Calling "mach_port_deallocate()" bumps the reference count on the thread 243 // port, so we need to deallocate it. mach_task_self() doesn't bump the ref 244 // count. 245 thread_port_t thread_self = mach_thread_self(); 246 247 _DNBLog (DNBLOG_FLAG_THREADED, "%u +%lu.%06u sec [%4.4x/%4.4x]: %s", 248 ++g_message_id, 249 delta.tv_sec, 250 delta.tv_usec, 251 getpid(), 252 thread_self, 253 arg_msg); 254 255 mach_port_deallocate(mach_task_self(), thread_self); 256 257 free (arg_msg); 258 } 259 } 260 } 261 262 263 264 //---------------------------------------------------------------------- 265 // Printing of errors that are not fatal. 266 //---------------------------------------------------------------------- 267 void 268 _DNBLogError (const char *format, ...) 269 { 270 if (DNBLogEnabled ()) 271 { 272 char *arg_msg = NULL; 273 va_list args; 274 va_start (args, format); 275 ::vasprintf (&arg_msg, format, args); 276 va_end (args); 277 278 if (arg_msg != NULL) 279 { 280 _DNBLog (DNBLOG_FLAG_ERROR, "error: %s", arg_msg); 281 free (arg_msg); 282 } 283 } 284 } 285 286 //---------------------------------------------------------------------- 287 // Printing of errors that ARE fatal. Exit with ERR exit code 288 // immediately. 289 //---------------------------------------------------------------------- 290 void 291 _DNBLogFatalError (int err, const char *format, ...) 292 { 293 if (DNBLogEnabled ()) 294 { 295 char *arg_msg = NULL; 296 va_list args; 297 va_start (args, format); 298 ::vasprintf (&arg_msg, format, args); 299 va_end (args); 300 301 if (arg_msg != NULL) 302 { 303 _DNBLog (DNBLOG_FLAG_ERROR | DNBLOG_FLAG_FATAL, "error: %s", arg_msg); 304 free (arg_msg); 305 } 306 ::exit (err); 307 } 308 } 309 310 311 //---------------------------------------------------------------------- 312 // Printing of warnings that are not fatal only if verbose mode is 313 // enabled. 314 //---------------------------------------------------------------------- 315 void 316 _DNBLogVerbose (const char *format, ...) 317 { 318 if (DNBLogEnabled () && g_verbose) 319 { 320 va_list args; 321 va_start (args, format); 322 _DNBLogVAPrintf(DNBLOG_FLAG_VERBOSE, format, args); 323 va_end (args); 324 } 325 } 326 327 //---------------------------------------------------------------------- 328 // Printing of warnings that are not fatal only if verbose mode is 329 // enabled. 330 //---------------------------------------------------------------------- 331 void 332 _DNBLogWarningVerbose (const char *format, ...) 333 { 334 if (DNBLogEnabled () && g_verbose) 335 { 336 char *arg_msg = NULL; 337 va_list args; 338 va_start (args, format); 339 ::vasprintf (&arg_msg, format, args); 340 va_end (args); 341 342 if (arg_msg != NULL) 343 { 344 _DNBLog (DNBLOG_FLAG_WARNING | DNBLOG_FLAG_VERBOSE, "warning: %s", arg_msg); 345 free (arg_msg); 346 } 347 } 348 } 349 //---------------------------------------------------------------------- 350 // Printing of warnings that are not fatal. 351 //---------------------------------------------------------------------- 352 void 353 _DNBLogWarning (const char *format, ...) 354 { 355 if (DNBLogEnabled ()) 356 { 357 char *arg_msg = NULL; 358 va_list args; 359 va_start (args, format); 360 ::vasprintf (&arg_msg, format, args); 361 va_end (args); 362 363 if (arg_msg != NULL) 364 { 365 _DNBLog (DNBLOG_FLAG_WARNING, "warning: %s", arg_msg); 366 free (arg_msg); 367 } 368 } 369 } 370 371 #endif 372