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 "PThreadMutex.h" 22 #include <mach/mach.h> 23 #include <pthread.h> 24 #include <stdarg.h> 25 #include <stdio.h> 26 #include <stdlib.h> 27 #include <sys/time.h> 28 #include <unistd.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 int DNBLogGetDebug() { return g_debug; } 35 36 void DNBLogSetDebug(int g) { g_debug = g; } 37 38 int DNBLogGetVerbose() { return g_verbose; } 39 40 void DNBLogSetVerbose(int v) { g_verbose = v; } 41 42 bool DNBLogCheckLogBit(uint32_t bit) { return (g_log_bits & bit) != 0; } 43 44 uint32_t DNBLogSetLogMask(uint32_t mask) { 45 uint32_t old = g_log_bits; 46 g_log_bits = mask; 47 return old; 48 } 49 50 uint32_t DNBLogGetLogMask() { return g_log_bits; } 51 52 void DNBLogSetLogCallback(DNBCallbackLog callback, void *baton) { 53 g_log_callback = callback; 54 g_log_baton = baton; 55 } 56 57 DNBCallbackLog DNBLogGetLogCallback() { return g_log_callback; } 58 59 bool DNBLogEnabled() { return g_log_callback != NULL; } 60 61 bool DNBLogEnabledForAny(uint32_t mask) { 62 if (g_log_callback) 63 return (g_log_bits & mask) != 0; 64 return false; 65 } 66 static inline void _DNBLogVAPrintf(uint32_t flags, const char *format, 67 va_list args) { 68 static PThreadMutex g_LogThreadedMutex(PTHREAD_MUTEX_RECURSIVE); 69 PTHREAD_MUTEX_LOCKER(locker, g_LogThreadedMutex); 70 71 if (g_log_callback) 72 g_log_callback(g_log_baton, flags, format, args); 73 } 74 75 void _DNBLog(uint32_t flags, const char *format, ...) { 76 va_list args; 77 va_start(args, format); 78 _DNBLogVAPrintf(flags, format, args); 79 va_end(args); 80 } 81 82 //---------------------------------------------------------------------- 83 // Print debug strings if and only if the global g_debug is set to 84 // a non-zero value. 85 //---------------------------------------------------------------------- 86 void _DNBLogDebug(const char *format, ...) { 87 if (DNBLogEnabled() && g_debug) { 88 va_list args; 89 va_start(args, format); 90 _DNBLogVAPrintf(DNBLOG_FLAG_DEBUG, format, args); 91 va_end(args); 92 } 93 } 94 95 //---------------------------------------------------------------------- 96 // Print debug strings if and only if the global g_debug is set to 97 // a non-zero value. 98 //---------------------------------------------------------------------- 99 void _DNBLogDebugVerbose(const char *format, ...) { 100 if (DNBLogEnabled() && g_debug && g_verbose) { 101 va_list args; 102 va_start(args, format); 103 _DNBLogVAPrintf(DNBLOG_FLAG_DEBUG | DNBLOG_FLAG_VERBOSE, format, args); 104 va_end(args); 105 } 106 } 107 108 static uint32_t g_message_id = 0; 109 110 //---------------------------------------------------------------------- 111 // Prefix the formatted log string with process and thread IDs and 112 // suffix it with a newline. 113 //---------------------------------------------------------------------- 114 void _DNBLogThreaded(const char *format, ...) { 115 if (DNBLogEnabled()) { 116 // PTHREAD_MUTEX_LOCKER(locker, GetLogThreadedMutex()); 117 118 char *arg_msg = NULL; 119 va_list args; 120 va_start(args, format); 121 ::vasprintf(&arg_msg, format, args); 122 va_end(args); 123 124 if (arg_msg != NULL) { 125 static struct timeval g_timeval = {0, 0}; 126 static struct timeval tv; 127 static struct timeval delta; 128 gettimeofday(&tv, NULL); 129 if (g_timeval.tv_sec == 0) { 130 delta.tv_sec = 0; 131 delta.tv_usec = 0; 132 } else { 133 timersub(&tv, &g_timeval, &delta); 134 } 135 g_timeval = tv; 136 137 // Calling "mach_port_deallocate()" bumps the reference count on the 138 // thread 139 // port, so we need to deallocate it. mach_task_self() doesn't bump the 140 // ref 141 // count. 142 thread_port_t thread_self = mach_thread_self(); 143 144 _DNBLog(DNBLOG_FLAG_THREADED, "%u +%lu.%06u sec [%4.4x/%4.4x]: %s", 145 ++g_message_id, delta.tv_sec, delta.tv_usec, getpid(), 146 thread_self, arg_msg); 147 148 mach_port_deallocate(mach_task_self(), thread_self); 149 free(arg_msg); 150 } 151 } 152 } 153 154 //---------------------------------------------------------------------- 155 // Prefix the formatted log string with process and thread IDs and 156 // suffix it with a newline. 157 //---------------------------------------------------------------------- 158 void _DNBLogThreadedIf(uint32_t log_bit, const char *format, ...) { 159 if (DNBLogEnabled() && (log_bit & g_log_bits) == log_bit) { 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 static struct timeval g_timeval = {0, 0}; 170 static struct timeval tv; 171 static struct timeval delta; 172 gettimeofday(&tv, NULL); 173 if (g_timeval.tv_sec == 0) { 174 delta.tv_sec = 0; 175 delta.tv_usec = 0; 176 } else { 177 timersub(&tv, &g_timeval, &delta); 178 } 179 g_timeval = tv; 180 181 // Calling "mach_port_deallocate()" bumps the reference count on the 182 // thread 183 // port, so we need to deallocate it. mach_task_self() doesn't bump the 184 // ref 185 // count. 186 thread_port_t thread_self = mach_thread_self(); 187 188 _DNBLog(DNBLOG_FLAG_THREADED, "%u +%lu.%06u sec [%4.4x/%4.4x]: %s", 189 ++g_message_id, delta.tv_sec, delta.tv_usec, getpid(), 190 thread_self, arg_msg); 191 192 mach_port_deallocate(mach_task_self(), thread_self); 193 194 free(arg_msg); 195 } 196 } 197 } 198 199 //---------------------------------------------------------------------- 200 // Printing of errors that are not fatal. 201 //---------------------------------------------------------------------- 202 void _DNBLogError(const char *format, ...) { 203 if (DNBLogEnabled()) { 204 char *arg_msg = NULL; 205 va_list args; 206 va_start(args, format); 207 ::vasprintf(&arg_msg, format, args); 208 va_end(args); 209 210 if (arg_msg != NULL) { 211 _DNBLog(DNBLOG_FLAG_ERROR, "error: %s", arg_msg); 212 free(arg_msg); 213 } 214 } 215 } 216 217 //---------------------------------------------------------------------- 218 // Printing of errors that ARE fatal. Exit with ERR exit code 219 // immediately. 220 //---------------------------------------------------------------------- 221 void _DNBLogFatalError(int err, const char *format, ...) { 222 if (DNBLogEnabled()) { 223 char *arg_msg = NULL; 224 va_list args; 225 va_start(args, format); 226 ::vasprintf(&arg_msg, format, args); 227 va_end(args); 228 229 if (arg_msg != NULL) { 230 _DNBLog(DNBLOG_FLAG_ERROR | DNBLOG_FLAG_FATAL, "error: %s", arg_msg); 231 free(arg_msg); 232 } 233 ::exit(err); 234 } 235 } 236 237 //---------------------------------------------------------------------- 238 // Printing of warnings that are not fatal only if verbose mode is 239 // enabled. 240 //---------------------------------------------------------------------- 241 void _DNBLogVerbose(const char *format, ...) { 242 if (DNBLogEnabled() && g_verbose) { 243 va_list args; 244 va_start(args, format); 245 _DNBLogVAPrintf(DNBLOG_FLAG_VERBOSE, format, args); 246 va_end(args); 247 } 248 } 249 250 //---------------------------------------------------------------------- 251 // Printing of warnings that are not fatal only if verbose mode is 252 // enabled. 253 //---------------------------------------------------------------------- 254 void _DNBLogWarningVerbose(const char *format, ...) { 255 if (DNBLogEnabled() && g_verbose) { 256 char *arg_msg = NULL; 257 va_list args; 258 va_start(args, format); 259 ::vasprintf(&arg_msg, format, args); 260 va_end(args); 261 262 if (arg_msg != NULL) { 263 _DNBLog(DNBLOG_FLAG_WARNING | DNBLOG_FLAG_VERBOSE, "warning: %s", 264 arg_msg); 265 free(arg_msg); 266 } 267 } 268 } 269 //---------------------------------------------------------------------- 270 // Printing of warnings that are not fatal. 271 //---------------------------------------------------------------------- 272 void _DNBLogWarning(const char *format, ...) { 273 if (DNBLogEnabled()) { 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 _DNBLog(DNBLOG_FLAG_WARNING, "warning: %s", arg_msg); 282 free(arg_msg); 283 } 284 } 285 } 286 287 #endif 288