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
DNBLogGetDebug()36 DNBLogGetDebug ()
37 {
38     return g_debug;
39 }
40 
41 
42 void
DNBLogSetDebug(int g)43 DNBLogSetDebug (int g)
44 {
45     g_debug = g;
46 }
47 
48 int
DNBLogGetVerbose()49 DNBLogGetVerbose ()
50 {
51     return g_verbose;
52 }
53 
54 void
DNBLogSetVerbose(int v)55 DNBLogSetVerbose (int v)
56 {
57     g_verbose = v;
58 }
59 
60 bool
DNBLogCheckLogBit(uint32_t bit)61 DNBLogCheckLogBit (uint32_t bit)
62 {
63     return (g_log_bits & bit) != 0;
64 }
65 
66 uint32_t
DNBLogSetLogMask(uint32_t mask)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
DNBLogGetLogMask()75 DNBLogGetLogMask ()
76 {
77     return g_log_bits;
78 }
79 
80 void
DNBLogSetLogCallback(DNBCallbackLog callback,void * baton)81 DNBLogSetLogCallback (DNBCallbackLog callback, void *baton)
82 {
83     g_log_callback = callback;
84     g_log_baton = baton;
85 }
86 
87 DNBCallbackLog
DNBLogGetLogCallback()88 DNBLogGetLogCallback ()
89 {
90     return g_log_callback;
91 }
92 
93 bool
DNBLogEnabled()94 DNBLogEnabled ()
95 {
96     return g_log_callback != NULL;
97 }
98 
99 bool
DNBLogEnabledForAny(uint32_t mask)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
_DNBLogVAPrintf(uint32_t flags,const char * format,va_list args)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
_DNBLog(uint32_t flags,const char * format,...)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
_DNBLogDebug(const char * format,...)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
_DNBLogDebugVerbose(const char * format,...)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
_DNBLogThreaded(const char * format,...)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
_DNBLogThreadedIf(uint32_t log_bit,const char * format,...)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
_DNBLogError(const char * format,...)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
_DNBLogFatalError(int err,const char * format,...)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
_DNBLogVerbose(const char * format,...)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
_DNBLogWarningVerbose(const char * format,...)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
_DNBLogWarning(const char * format,...)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