130fdc8d8SChris Lattner //===-- DNBLog.cpp ----------------------------------------------*- C++ -*-===//
230fdc8d8SChris Lattner //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
630fdc8d8SChris Lattner //
730fdc8d8SChris Lattner //===----------------------------------------------------------------------===//
830fdc8d8SChris Lattner //
930fdc8d8SChris Lattner // Created by Greg Clayton on 6/18/07.
1030fdc8d8SChris Lattner //
1130fdc8d8SChris Lattner //===----------------------------------------------------------------------===//
1230fdc8d8SChris Lattner
1330fdc8d8SChris Lattner #include "DNBLog.h"
1430fdc8d8SChris Lattner
1530fdc8d8SChris Lattner static int g_debug = 0;
1630fdc8d8SChris Lattner static int g_verbose = 0;
1730fdc8d8SChris Lattner
1830fdc8d8SChris Lattner #if defined(DNBLOG_ENABLED)
1930fdc8d8SChris Lattner
20b9c1b51eSKate Stone #include "PThreadMutex.h"
21*76e47d48SRaphael Isemann #include <cstdarg>
22*76e47d48SRaphael Isemann #include <cstdio>
23*76e47d48SRaphael Isemann #include <cstdlib>
24b9c1b51eSKate Stone #include <mach/mach.h>
25b9c1b51eSKate Stone #include <pthread.h>
26e5219660SGreg Clayton #include <sys/time.h>
2730fdc8d8SChris Lattner #include <unistd.h>
2830fdc8d8SChris Lattner
2930fdc8d8SChris Lattner uint32_t g_log_bits = 0;
3030fdc8d8SChris Lattner static DNBCallbackLog g_log_callback = NULL;
3130fdc8d8SChris Lattner static void *g_log_baton = NULL;
3230fdc8d8SChris Lattner
DNBLogGetDebug()33b9c1b51eSKate Stone int DNBLogGetDebug() { return g_debug; }
3430fdc8d8SChris Lattner
DNBLogSetDebug(int g)35b9c1b51eSKate Stone void DNBLogSetDebug(int g) { g_debug = g; }
3630fdc8d8SChris Lattner
DNBLogGetVerbose()37b9c1b51eSKate Stone int DNBLogGetVerbose() { return g_verbose; }
3830fdc8d8SChris Lattner
DNBLogSetVerbose(int v)39b9c1b51eSKate Stone void DNBLogSetVerbose(int v) { g_verbose = v; }
4030fdc8d8SChris Lattner
DNBLogCheckLogBit(uint32_t bit)41b9c1b51eSKate Stone bool DNBLogCheckLogBit(uint32_t bit) { return (g_log_bits & bit) != 0; }
4230fdc8d8SChris Lattner
DNBLogSetLogMask(uint32_t mask)43b9c1b51eSKate Stone uint32_t DNBLogSetLogMask(uint32_t mask) {
4430fdc8d8SChris Lattner uint32_t old = g_log_bits;
4530fdc8d8SChris Lattner g_log_bits = mask;
4630fdc8d8SChris Lattner return old;
4730fdc8d8SChris Lattner }
4830fdc8d8SChris Lattner
DNBLogGetLogMask()49b9c1b51eSKate Stone uint32_t DNBLogGetLogMask() { return g_log_bits; }
5030fdc8d8SChris Lattner
DNBLogSetLogCallback(DNBCallbackLog callback,void * baton)51b9c1b51eSKate Stone void DNBLogSetLogCallback(DNBCallbackLog callback, void *baton) {
5230fdc8d8SChris Lattner g_log_callback = callback;
5330fdc8d8SChris Lattner g_log_baton = baton;
5430fdc8d8SChris Lattner }
5530fdc8d8SChris Lattner
DNBLogGetLogCallback()56b9c1b51eSKate Stone DNBCallbackLog DNBLogGetLogCallback() { return g_log_callback; }
574edb7ab8SGreg Clayton
DNBLogEnabled()58b9c1b51eSKate Stone bool DNBLogEnabled() { return g_log_callback != NULL; }
5930fdc8d8SChris Lattner
DNBLogEnabledForAny(uint32_t mask)60b9c1b51eSKate Stone bool DNBLogEnabledForAny(uint32_t mask) {
6132e0a750SGreg Clayton if (g_log_callback)
6232e0a750SGreg Clayton return (g_log_bits & mask) != 0;
6332e0a750SGreg Clayton return false;
6432e0a750SGreg Clayton }
_DNBLogVAPrintf(uint32_t flags,const char * format,va_list args)65b9c1b51eSKate Stone static inline void _DNBLogVAPrintf(uint32_t flags, const char *format,
66b9c1b51eSKate Stone va_list args) {
6771fc2a33SGreg Clayton static PThreadMutex g_LogThreadedMutex(PTHREAD_MUTEX_RECURSIVE);
6871fc2a33SGreg Clayton PTHREAD_MUTEX_LOCKER(locker, g_LogThreadedMutex);
6971fc2a33SGreg Clayton
7030fdc8d8SChris Lattner if (g_log_callback)
7130fdc8d8SChris Lattner g_log_callback(g_log_baton, flags, format, args);
7230fdc8d8SChris Lattner }
7330fdc8d8SChris Lattner
_DNBLog(uint32_t flags,const char * format,...)74b9c1b51eSKate Stone void _DNBLog(uint32_t flags, const char *format, ...) {
7530fdc8d8SChris Lattner va_list args;
7630fdc8d8SChris Lattner va_start(args, format);
7730fdc8d8SChris Lattner _DNBLogVAPrintf(flags, format, args);
7830fdc8d8SChris Lattner va_end(args);
7930fdc8d8SChris Lattner }
8030fdc8d8SChris Lattner
8130fdc8d8SChris Lattner // Print debug strings if and only if the global g_debug is set to
8230fdc8d8SChris Lattner // a non-zero value.
_DNBLogDebug(const char * format,...)83b9c1b51eSKate Stone void _DNBLogDebug(const char *format, ...) {
84b9c1b51eSKate Stone if (DNBLogEnabled() && g_debug) {
8530fdc8d8SChris Lattner va_list args;
8630fdc8d8SChris Lattner va_start(args, format);
8730fdc8d8SChris Lattner _DNBLogVAPrintf(DNBLOG_FLAG_DEBUG, format, args);
8830fdc8d8SChris Lattner va_end(args);
8930fdc8d8SChris Lattner }
9030fdc8d8SChris Lattner }
9130fdc8d8SChris Lattner
9230fdc8d8SChris Lattner // Print debug strings if and only if the global g_debug is set to
9330fdc8d8SChris Lattner // a non-zero value.
_DNBLogDebugVerbose(const char * format,...)94b9c1b51eSKate Stone void _DNBLogDebugVerbose(const char *format, ...) {
95b9c1b51eSKate Stone if (DNBLogEnabled() && g_debug && g_verbose) {
9630fdc8d8SChris Lattner va_list args;
9730fdc8d8SChris Lattner va_start(args, format);
9830fdc8d8SChris Lattner _DNBLogVAPrintf(DNBLOG_FLAG_DEBUG | DNBLOG_FLAG_VERBOSE, format, args);
9930fdc8d8SChris Lattner va_end(args);
10030fdc8d8SChris Lattner }
10130fdc8d8SChris Lattner }
10230fdc8d8SChris Lattner
10330fdc8d8SChris Lattner static uint32_t g_message_id = 0;
10430fdc8d8SChris Lattner
10530fdc8d8SChris Lattner // Prefix the formatted log string with process and thread IDs and
10630fdc8d8SChris Lattner // suffix it with a newline.
_DNBLogThreaded(const char * format,...)107b9c1b51eSKate Stone void _DNBLogThreaded(const char *format, ...) {
108b9c1b51eSKate Stone if (DNBLogEnabled()) {
10971fc2a33SGreg Clayton // PTHREAD_MUTEX_LOCKER(locker, GetLogThreadedMutex());
11030fdc8d8SChris Lattner
11130fdc8d8SChris Lattner char *arg_msg = NULL;
11230fdc8d8SChris Lattner va_list args;
11330fdc8d8SChris Lattner va_start(args, format);
11430fdc8d8SChris Lattner ::vasprintf(&arg_msg, format, args);
11530fdc8d8SChris Lattner va_end(args);
11630fdc8d8SChris Lattner
117b9c1b51eSKate Stone if (arg_msg != NULL) {
118e5219660SGreg Clayton static struct timeval g_timeval = {0, 0};
119e5219660SGreg Clayton static struct timeval tv;
120e5219660SGreg Clayton static struct timeval delta;
121e5219660SGreg Clayton gettimeofday(&tv, NULL);
122b9c1b51eSKate Stone if (g_timeval.tv_sec == 0) {
123e5219660SGreg Clayton delta.tv_sec = 0;
124e5219660SGreg Clayton delta.tv_usec = 0;
125b9c1b51eSKate Stone } else {
126e5219660SGreg Clayton timersub(&tv, &g_timeval, &delta);
127e5219660SGreg Clayton }
128e5219660SGreg Clayton g_timeval = tv;
129813ddfcdSGreg Clayton
130b9c1b51eSKate Stone // Calling "mach_port_deallocate()" bumps the reference count on the
131b9c1b51eSKate Stone // thread
132b9c1b51eSKate Stone // port, so we need to deallocate it. mach_task_self() doesn't bump the
133b9c1b51eSKate Stone // ref
134813ddfcdSGreg Clayton // count.
135813ddfcdSGreg Clayton thread_port_t thread_self = mach_thread_self();
136813ddfcdSGreg Clayton
137490fbbe2SGreg Clayton _DNBLog(DNBLOG_FLAG_THREADED, "%u +%lu.%06u sec [%4.4x/%4.4x]: %s",
138b9c1b51eSKate Stone ++g_message_id, delta.tv_sec, delta.tv_usec, getpid(),
139b9c1b51eSKate Stone thread_self, arg_msg);
140813ddfcdSGreg Clayton
141813ddfcdSGreg Clayton mach_port_deallocate(mach_task_self(), thread_self);
14230fdc8d8SChris Lattner free(arg_msg);
14330fdc8d8SChris Lattner }
14430fdc8d8SChris Lattner }
14530fdc8d8SChris Lattner }
14630fdc8d8SChris Lattner
14730fdc8d8SChris Lattner // Prefix the formatted log string with process and thread IDs and
14830fdc8d8SChris Lattner // suffix it with a newline.
_DNBLogThreadedIf(uint32_t log_bit,const char * format,...)149b9c1b51eSKate Stone void _DNBLogThreadedIf(uint32_t log_bit, const char *format, ...) {
150b9c1b51eSKate Stone if (DNBLogEnabled() && (log_bit & g_log_bits) == log_bit) {
15171fc2a33SGreg Clayton // PTHREAD_MUTEX_LOCKER(locker, GetLogThreadedMutex());
15230fdc8d8SChris Lattner
15330fdc8d8SChris Lattner char *arg_msg = NULL;
15430fdc8d8SChris Lattner va_list args;
15530fdc8d8SChris Lattner va_start(args, format);
15630fdc8d8SChris Lattner ::vasprintf(&arg_msg, format, args);
15730fdc8d8SChris Lattner va_end(args);
15830fdc8d8SChris Lattner
159b9c1b51eSKate Stone if (arg_msg != NULL) {
160e5219660SGreg Clayton static struct timeval g_timeval = {0, 0};
161e5219660SGreg Clayton static struct timeval tv;
162e5219660SGreg Clayton static struct timeval delta;
163e5219660SGreg Clayton gettimeofday(&tv, NULL);
164b9c1b51eSKate Stone if (g_timeval.tv_sec == 0) {
165e5219660SGreg Clayton delta.tv_sec = 0;
166e5219660SGreg Clayton delta.tv_usec = 0;
167b9c1b51eSKate Stone } else {
168e5219660SGreg Clayton timersub(&tv, &g_timeval, &delta);
169e5219660SGreg Clayton }
170e5219660SGreg Clayton g_timeval = tv;
171813ddfcdSGreg Clayton
172b9c1b51eSKate Stone // Calling "mach_port_deallocate()" bumps the reference count on the
173b9c1b51eSKate Stone // thread
174b9c1b51eSKate Stone // port, so we need to deallocate it. mach_task_self() doesn't bump the
175b9c1b51eSKate Stone // ref
176813ddfcdSGreg Clayton // count.
177813ddfcdSGreg Clayton thread_port_t thread_self = mach_thread_self();
178813ddfcdSGreg Clayton
179490fbbe2SGreg Clayton _DNBLog(DNBLOG_FLAG_THREADED, "%u +%lu.%06u sec [%4.4x/%4.4x]: %s",
180b9c1b51eSKate Stone ++g_message_id, delta.tv_sec, delta.tv_usec, getpid(),
181b9c1b51eSKate Stone thread_self, arg_msg);
182813ddfcdSGreg Clayton
183813ddfcdSGreg Clayton mach_port_deallocate(mach_task_self(), thread_self);
184813ddfcdSGreg Clayton
18530fdc8d8SChris Lattner free(arg_msg);
18630fdc8d8SChris Lattner }
18730fdc8d8SChris Lattner }
18830fdc8d8SChris Lattner }
18930fdc8d8SChris Lattner
19030fdc8d8SChris Lattner // Printing of errors that are not fatal.
_DNBLogError(const char * format,...)191b9c1b51eSKate Stone void _DNBLogError(const char *format, ...) {
192b9c1b51eSKate Stone if (DNBLogEnabled()) {
19330fdc8d8SChris Lattner char *arg_msg = NULL;
19430fdc8d8SChris Lattner va_list args;
19530fdc8d8SChris Lattner va_start(args, format);
19630fdc8d8SChris Lattner ::vasprintf(&arg_msg, format, args);
19730fdc8d8SChris Lattner va_end(args);
19830fdc8d8SChris Lattner
199b9c1b51eSKate Stone if (arg_msg != NULL) {
20030fdc8d8SChris Lattner _DNBLog(DNBLOG_FLAG_ERROR, "error: %s", arg_msg);
20130fdc8d8SChris Lattner free(arg_msg);
20230fdc8d8SChris Lattner }
20330fdc8d8SChris Lattner }
20430fdc8d8SChris Lattner }
20530fdc8d8SChris Lattner
20630fdc8d8SChris Lattner // Printing of errors that ARE fatal. Exit with ERR exit code
20730fdc8d8SChris Lattner // immediately.
_DNBLogFatalError(int err,const char * format,...)208b9c1b51eSKate Stone void _DNBLogFatalError(int err, const char *format, ...) {
209b9c1b51eSKate Stone if (DNBLogEnabled()) {
21030fdc8d8SChris Lattner char *arg_msg = NULL;
21130fdc8d8SChris Lattner va_list args;
21230fdc8d8SChris Lattner va_start(args, format);
21330fdc8d8SChris Lattner ::vasprintf(&arg_msg, format, args);
21430fdc8d8SChris Lattner va_end(args);
21530fdc8d8SChris Lattner
216b9c1b51eSKate Stone if (arg_msg != NULL) {
21730fdc8d8SChris Lattner _DNBLog(DNBLOG_FLAG_ERROR | DNBLOG_FLAG_FATAL, "error: %s", arg_msg);
21830fdc8d8SChris Lattner free(arg_msg);
21930fdc8d8SChris Lattner }
22030fdc8d8SChris Lattner ::exit(err);
22130fdc8d8SChris Lattner }
22230fdc8d8SChris Lattner }
22330fdc8d8SChris Lattner
22430fdc8d8SChris Lattner // Printing of warnings that are not fatal only if verbose mode is
22530fdc8d8SChris Lattner // enabled.
_DNBLogVerbose(const char * format,...)226b9c1b51eSKate Stone void _DNBLogVerbose(const char *format, ...) {
227b9c1b51eSKate Stone if (DNBLogEnabled() && g_verbose) {
22830fdc8d8SChris Lattner va_list args;
22930fdc8d8SChris Lattner va_start(args, format);
23030fdc8d8SChris Lattner _DNBLogVAPrintf(DNBLOG_FLAG_VERBOSE, format, args);
23130fdc8d8SChris Lattner va_end(args);
23230fdc8d8SChris Lattner }
23330fdc8d8SChris Lattner }
23430fdc8d8SChris Lattner
23530fdc8d8SChris Lattner // Printing of warnings that are not fatal only if verbose mode is
23630fdc8d8SChris Lattner // enabled.
_DNBLogWarningVerbose(const char * format,...)237b9c1b51eSKate Stone void _DNBLogWarningVerbose(const char *format, ...) {
238b9c1b51eSKate Stone if (DNBLogEnabled() && g_verbose) {
23930fdc8d8SChris Lattner char *arg_msg = NULL;
24030fdc8d8SChris Lattner va_list args;
24130fdc8d8SChris Lattner va_start(args, format);
24230fdc8d8SChris Lattner ::vasprintf(&arg_msg, format, args);
24330fdc8d8SChris Lattner va_end(args);
24430fdc8d8SChris Lattner
245b9c1b51eSKate Stone if (arg_msg != NULL) {
246b9c1b51eSKate Stone _DNBLog(DNBLOG_FLAG_WARNING | DNBLOG_FLAG_VERBOSE, "warning: %s",
247b9c1b51eSKate Stone arg_msg);
24830fdc8d8SChris Lattner free(arg_msg);
24930fdc8d8SChris Lattner }
25030fdc8d8SChris Lattner }
25130fdc8d8SChris Lattner }
25230fdc8d8SChris Lattner // Printing of warnings that are not fatal.
_DNBLogWarning(const char * format,...)253b9c1b51eSKate Stone void _DNBLogWarning(const char *format, ...) {
254b9c1b51eSKate Stone if (DNBLogEnabled()) {
25530fdc8d8SChris Lattner char *arg_msg = NULL;
25630fdc8d8SChris Lattner va_list args;
25730fdc8d8SChris Lattner va_start(args, format);
25830fdc8d8SChris Lattner ::vasprintf(&arg_msg, format, args);
25930fdc8d8SChris Lattner va_end(args);
26030fdc8d8SChris Lattner
261b9c1b51eSKate Stone if (arg_msg != NULL) {
26230fdc8d8SChris Lattner _DNBLog(DNBLOG_FLAG_WARNING, "warning: %s", arg_msg);
26330fdc8d8SChris Lattner free(arg_msg);
26430fdc8d8SChris Lattner }
26530fdc8d8SChris Lattner }
26630fdc8d8SChris Lattner }
26730fdc8d8SChris Lattner
26830fdc8d8SChris Lattner #endif
269