Home | History | Annotate | Download | only in source
      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 DNBCallbackLog
     88 DNBLogGetLogCallback ()
     89 {
     90     return g_log_callback;
     91 }
     92 
     93 bool
     94 DNBLogEnabled ()
     95 {
     96     return g_log_callback != NULL;
     97 }
     98 
     99 bool
    100 DNBLogEnabledForAny (uint32_t mask)
    101 {
    102     if (g_log_callback)
    103         return (g_log_bits & mask) != 0;
    104     return false;
    105 }
    106 static 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 
    116 void
    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 //----------------------------------------------------------------------
    129 void
    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 //----------------------------------------------------------------------
    146 void
    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 
    159 static 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 //----------------------------------------------------------------------
    165 void
    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 //----------------------------------------------------------------------
    218 void
    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 //----------------------------------------------------------------------
    273 void
    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 //----------------------------------------------------------------------
    296 void
    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 //----------------------------------------------------------------------
    321 void
    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 //----------------------------------------------------------------------
    337 void
    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 //----------------------------------------------------------------------
    358 void
    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