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