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 static 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 100 void 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 //---------------------------------------------------------------------- 113 void 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 //---------------------------------------------------------------------- 130 void 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 143 static pthread_mutex_t * 144 GetLogThreadedMutex() 145 { 146 static PThreadMutex g_LogThreadedMutex(PTHREAD_MUTEX_RECURSIVE); 147 return g_LogThreadedMutex.Mutex(); 148 } 149 static 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 //---------------------------------------------------------------------- 155 void 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 //---------------------------------------------------------------------- 200 void 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 //---------------------------------------------------------------------- 246 void 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 //---------------------------------------------------------------------- 269 void 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 //---------------------------------------------------------------------- 294 void 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 //---------------------------------------------------------------------- 310 void 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 //---------------------------------------------------------------------- 331 void 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