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