DNBLog.cpp revision 9c81c3322b68e49530b5c2180f8a0db8c6a494fb
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 16static int g_debug = 0; 17static 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 30uint32_t g_log_bits = 0; 31static DNBCallbackLog g_log_callback = NULL; 32static void *g_log_baton = NULL; 33 34 35int 36DNBLogGetDebug () 37{ 38 return g_debug; 39} 40 41 42void 43DNBLogSetDebug (int g) 44{ 45 g_debug = g; 46} 47 48int 49DNBLogGetVerbose () 50{ 51 return g_verbose; 52} 53 54void 55DNBLogSetVerbose (int v) 56{ 57 g_verbose = v; 58} 59 60bool 61DNBLogCheckLogBit (uint32_t bit) 62{ 63 return (g_log_bits & bit) != 0; 64} 65 66uint32_t 67DNBLogSetLogMask (uint32_t mask) 68{ 69 uint32_t old = g_log_bits; 70 g_log_bits = mask; 71 return old; 72} 73 74uint32_t 75DNBLogGetLogMask () 76{ 77 return g_log_bits; 78} 79 80void 81DNBLogSetLogCallback (DNBCallbackLog callback, void *baton) 82{ 83 g_log_callback = callback; 84 g_log_baton = baton; 85} 86 87DNBCallbackLog 88DNBLogGetLogCallback () 89{ 90 return g_log_callback; 91} 92 93bool 94DNBLogEnabled () 95{ 96 return g_log_callback != NULL; 97} 98 99bool 100DNBLogEnabledForAny (uint32_t mask) 101{ 102 if (g_log_callback) 103 return (g_log_bits & mask) != 0; 104 return false; 105} 106static 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 116void 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//---------------------------------------------------------------------- 129void 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//---------------------------------------------------------------------- 146void 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 159static 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//---------------------------------------------------------------------- 165void 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//---------------------------------------------------------------------- 218void 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//---------------------------------------------------------------------- 273void 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//---------------------------------------------------------------------- 296void 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//---------------------------------------------------------------------- 321void 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//---------------------------------------------------------------------- 337void 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//---------------------------------------------------------------------- 358void 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