brintos

brintos / llvm-project-archived public Read only

0
0
Text · 7.1 KiB · f7d7016 Raw
269 lines · cpp
1//===-- DNBLog.cpp ----------------------------------------------*- C++ -*-===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9//  Created by Greg Clayton on 6/18/07.10//11//===----------------------------------------------------------------------===//12 13#include "DNBLog.h"14 15static int g_debug = 0;16static int g_verbose = 0;17 18#if defined(DNBLOG_ENABLED)19 20#include <cstdarg>21#include <cstdio>22#include <cstdlib>23#include <mach/mach.h>24#include <mutex>25#include <pthread.h>26#include <sys/time.h>27#include <unistd.h>28 29uint32_t g_log_bits = 0;30static DNBCallbackLog g_log_callback = NULL;31static void *g_log_baton = NULL;32 33int DNBLogGetDebug() { return g_debug; }34 35void DNBLogSetDebug(int g) { g_debug = g; }36 37int DNBLogGetVerbose() { return g_verbose; }38 39void DNBLogSetVerbose(int v) { g_verbose = v; }40 41bool DNBLogCheckLogBit(uint32_t bit) { return (g_log_bits & bit) != 0; }42 43uint32_t DNBLogSetLogMask(uint32_t mask) {44  uint32_t old = g_log_bits;45  g_log_bits = mask;46  return old;47}48 49uint32_t DNBLogGetLogMask() { return g_log_bits; }50 51void DNBLogSetLogCallback(DNBCallbackLog callback, void *baton) {52  g_log_callback = callback;53  g_log_baton = baton;54}55 56DNBCallbackLog DNBLogGetLogCallback() { return g_log_callback; }57 58bool DNBLogEnabled() { return g_log_callback != NULL; }59 60bool DNBLogEnabledForAny(uint32_t mask) {61  if (g_log_callback)62    return (g_log_bits & mask) != 0;63  return false;64}65static inline void _DNBLogVAPrintf(uint32_t flags, const char *format,66                                   va_list args) {67  static std::recursive_mutex g_LogThreadedMutex;68  std::lock_guard<std::recursive_mutex> guard(g_LogThreadedMutex);69 70  if (g_log_callback)71    g_log_callback(g_log_baton, flags, format, args);72}73 74void _DNBLog(uint32_t flags, const char *format, ...) {75  va_list args;76  va_start(args, format);77  _DNBLogVAPrintf(flags, format, args);78  va_end(args);79}80 81// Print debug strings if and only if the global g_debug is set to82// a non-zero value.83void _DNBLogDebug(const char *format, ...) {84  if (DNBLogEnabled() && g_debug) {85    va_list args;86    va_start(args, format);87    _DNBLogVAPrintf(DNBLOG_FLAG_DEBUG, format, args);88    va_end(args);89  }90}91 92// Print debug strings if and only if the global g_debug is set to93// a non-zero value.94void _DNBLogDebugVerbose(const char *format, ...) {95  if (DNBLogEnabled() && g_debug && g_verbose) {96    va_list args;97    va_start(args, format);98    _DNBLogVAPrintf(DNBLOG_FLAG_DEBUG | DNBLOG_FLAG_VERBOSE, format, args);99    va_end(args);100  }101}102 103static uint32_t g_message_id = 0;104 105// Prefix the formatted log string with process and thread IDs and106// suffix it with a newline.107void _DNBLogThreaded(const char *format, ...) {108  if (DNBLogEnabled()) {109    // PTHREAD_MUTEX_LOCKER(locker, GetLogThreadedMutex());110 111    char *arg_msg = NULL;112    va_list args;113    va_start(args, format);114    ::vasprintf(&arg_msg, format, args);115    va_end(args);116 117    if (arg_msg != NULL) {118      static struct timeval g_timeval = {0, 0};119      static struct timeval tv;120      static struct timeval delta;121      gettimeofday(&tv, NULL);122      if (g_timeval.tv_sec == 0) {123        delta.tv_sec = 0;124        delta.tv_usec = 0;125      } else {126        timersub(&tv, &g_timeval, &delta);127      }128      g_timeval = tv;129 130      // Calling "mach_port_deallocate()" bumps the reference count on the131      // thread132      // port, so we need to deallocate it. mach_task_self() doesn't bump the133      // ref134      // count.135      thread_port_t thread_self = mach_thread_self();136 137      _DNBLog(DNBLOG_FLAG_THREADED, "%u +%lu.%06u sec [%4.4x/%4.4x]: %s",138              ++g_message_id, delta.tv_sec, delta.tv_usec, getpid(),139              thread_self, arg_msg);140 141      mach_port_deallocate(mach_task_self(), thread_self);142      free(arg_msg);143    }144  }145}146 147// Prefix the formatted log string with process and thread IDs and148// suffix it with a newline.149void _DNBLogThreadedIf(uint32_t log_bit, const char *format, ...) {150  if (DNBLogEnabled() && (log_bit & g_log_bits) == log_bit) {151    // PTHREAD_MUTEX_LOCKER(locker, GetLogThreadedMutex());152 153    char *arg_msg = NULL;154    va_list args;155    va_start(args, format);156    ::vasprintf(&arg_msg, format, args);157    va_end(args);158 159    if (arg_msg != NULL) {160      static struct timeval g_timeval = {0, 0};161      static struct timeval tv;162      static struct timeval delta;163      gettimeofday(&tv, NULL);164      if (g_timeval.tv_sec == 0) {165        delta.tv_sec = 0;166        delta.tv_usec = 0;167      } else {168        timersub(&tv, &g_timeval, &delta);169      }170      g_timeval = tv;171 172      // Calling "mach_port_deallocate()" bumps the reference count on the173      // thread174      // port, so we need to deallocate it. mach_task_self() doesn't bump the175      // ref176      // count.177      thread_port_t thread_self = mach_thread_self();178 179      _DNBLog(DNBLOG_FLAG_THREADED, "%u +%lu.%06u sec [%4.4x/%4.4x]: %s",180              ++g_message_id, delta.tv_sec, delta.tv_usec, getpid(),181              thread_self, arg_msg);182 183      mach_port_deallocate(mach_task_self(), thread_self);184 185      free(arg_msg);186    }187  }188}189 190// Printing of errors that are not fatal.191void _DNBLogError(const char *format, ...) {192  if (DNBLogEnabled()) {193    char *arg_msg = NULL;194    va_list args;195    va_start(args, format);196    ::vasprintf(&arg_msg, format, args);197    va_end(args);198 199    if (arg_msg != NULL) {200      _DNBLog(DNBLOG_FLAG_ERROR, "error: %s", arg_msg);201      free(arg_msg);202    }203  }204}205 206// Printing of errors that ARE fatal. Exit with ERR exit code207// immediately.208void _DNBLogFatalError(int err, const char *format, ...) {209  if (DNBLogEnabled()) {210    char *arg_msg = NULL;211    va_list args;212    va_start(args, format);213    ::vasprintf(&arg_msg, format, args);214    va_end(args);215 216    if (arg_msg != NULL) {217      _DNBLog(DNBLOG_FLAG_ERROR | DNBLOG_FLAG_FATAL, "error: %s", arg_msg);218      free(arg_msg);219    }220    ::exit(err);221  }222}223 224// Printing of warnings that are not fatal only if verbose mode is225// enabled.226void _DNBLogVerbose(const char *format, ...) {227  if (DNBLogEnabled() && g_verbose) {228    va_list args;229    va_start(args, format);230    _DNBLogVAPrintf(DNBLOG_FLAG_VERBOSE, format, args);231    va_end(args);232  }233}234 235// Printing of warnings that are not fatal only if verbose mode is236// enabled.237void _DNBLogWarningVerbose(const char *format, ...) {238  if (DNBLogEnabled() && g_verbose) {239    char *arg_msg = NULL;240    va_list args;241    va_start(args, format);242    ::vasprintf(&arg_msg, format, args);243    va_end(args);244 245    if (arg_msg != NULL) {246      _DNBLog(DNBLOG_FLAG_WARNING | DNBLOG_FLAG_VERBOSE, "warning: %s",247              arg_msg);248      free(arg_msg);249    }250  }251}252// Printing of warnings that are not fatal.253void _DNBLogWarning(const char *format, ...) {254  if (DNBLogEnabled()) {255    char *arg_msg = NULL;256    va_list args;257    va_start(args, format);258    ::vasprintf(&arg_msg, format, args);259    va_end(args);260 261    if (arg_msg != NULL) {262      _DNBLog(DNBLOG_FLAG_WARNING, "warning: %s", arg_msg);263      free(arg_msg);264    }265  }266}267 268#endif269