|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356 |
- /**
- * \file src/core/impl/common.cpp
- * MegEngine is Licensed under the Apache License, Version 2.0 (the "License")
- *
- * Copyright (c) 2014-2021 Megvii Inc. All rights reserved.
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT ARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- */
-
- #include "megbrain/common.h"
- #include "megbrain/exception.h"
- #include "megbrain/system.h"
- #include "megbrain/utils/thread.h"
-
- #include "megdnn/basic_types.h"
-
- #include <cstdio>
- #include <cstdlib>
- #include <ctime>
- #include <cstring>
-
- #ifdef __ANDROID__
- #include <android/log.h>
- #include <sys/system_properties.h>
- #endif
-
- using namespace mgb;
-
- namespace {
- LogLevel config_default_log_level() {
- auto default_level = LogLevel::ERROR;
- //! env to config LogLevel
- //! DEBUG = 0, INFO = 1, WARN = 2, ERROR = 3, NO_LOG = 4
- //! for example , export RUNTIME_OVERRIDE_LOG_LEVEL=0, means set LogLevel to
- //! DEBUG
- if (auto env = ::std::getenv("RUNTIME_OVERRIDE_LOG_LEVEL"))
- default_level = static_cast<LogLevel>(std::stoi(env));
-
- #ifdef __ANDROID__
- //! special for Android prop, attention: getprop may need permission
- char buf[PROP_VALUE_MAX];
- if (__system_property_get("RUNTIME_OVERRIDE_LOG_LEVEL", buf) > 0) {
- default_level = static_cast<LogLevel>(atoi(buf));
- }
- #endif
-
- return default_level;
- }
-
- LogLevel min_log_level = config_default_log_level();
- } // namespace
-
- #if MGB_ENABLE_LOGGING
-
- #if MGB_EXTERN_API_TIME
- extern "C" {
- void mgb_extern_api_get_time(int64_t *sec, int64_t *nsec);
- }
- #endif
-
- namespace {
- void default_log_handler(LogLevel level,
- const char *file, const char *func, int line, const char *fmt,
- va_list ap) {
- if (level < min_log_level)
- return;
-
- #define HDR_FMT "[%s %s@%s:%d]%s"
- fmt = convert_fmt_str(fmt);
-
- // we have to use a Spinlock here, since log handler might be called during
- // global finalization when mtx has been destructed
- static Spinlock mtx;
-
- static const char *hdr_fmt = nullptr;
- if (!hdr_fmt) {
- if (sys::stderr_ansi_color())
- hdr_fmt = "\x1b[32m" HDR_FMT "\x1b[0m ";
- else
- hdr_fmt = HDR_FMT " ";
- }
- const char *warn_reminder = "";
- switch (level) {
- case LogLevel::ERROR:
- if (sys::stderr_ansi_color())
- warn_reminder = "\x1b[1;4;31m[ERR]\x1b[0m";
- else
- warn_reminder = "[ERR]";
- break;
- case LogLevel::WARN:
- if (sys::stderr_ansi_color())
- warn_reminder = "\x1b[1;31m[WARN]\x1b[0m";
- else
- warn_reminder = "[WARN]";
- break;
- case LogLevel::INFO:
- break;
- case LogLevel::DEBUG:
- if (sys::stderr_ansi_color())
- warn_reminder = "\x1b[36m[DEBUG]\x1b[0m";
- else
- warn_reminder = "[DEBUG]";
- break;
- default:
- mgb_throw(MegBrainError, "bad log level");
- }
- char timestr[64];
- #if MGB_EXTERN_API_TIME
- {
- static int64_t sec_start, nsec_start;
- int64_t sec, nsec;
- mgb_extern_api_get_time(&sec, &nsec);
- if (!sec_start) {
- sec_start = sec;
- nsec_start = nsec;
- }
- sec -= sec_start;
- nsec -= nsec_start;
- if (nsec < 0) {
- -- sec;
- nsec += 1000000000;
- }
- snprintf(timestr, sizeof(timestr), "%.3f",
- static_cast<int>(sec) + static_cast<int>(nsec) * 1e-9);
- }
- #else
- {
- time_t cur_time;
- MGB_LOCK_GUARD(mtx);
- time(&cur_time);
- strftime(timestr, sizeof(timestr), "%d %H:%M:%S", localtime(&cur_time));
- }
- #endif
-
- {
- // find file basename part
- auto f0 = file;
- file = f0 + strlen(f0) - 1;
- while (file >= f0 && *file != '/' && *file != '\\')
- -- file;
- ++ file;
- }
- {
- MGB_LOCK_GUARD(mtx);
- fprintf(stderr, hdr_fmt, timestr, func, file, line, warn_reminder);
- vfprintf(stderr, fmt, ap);
- fputc('\n', stderr);
- }
-
- #ifdef __ANDROID__
- android_LogPriority android_level;
- switch (level) {
- case LogLevel::WARN:
- android_level = ANDROID_LOG_WARN;
- break;
- case LogLevel::INFO:
- android_level = ANDROID_LOG_INFO;
- break;
- case LogLevel::DEBUG:
- android_level = ANDROID_LOG_DEBUG;
- break;
- default:
- android_level = ANDROID_LOG_ERROR;
- }
- __android_log_vprint(android_level, "runtime", fmt, ap);
- #endif
-
- #undef HDR_FMT
- }
-
- LogHandler log_handler = default_log_handler;
-
- class MegDNNLogHandler {
- static void dnn_log_handler(megdnn::LogLevel dnn_level, const char* file,
- const char* func, int line, const char* fmt,
- va_list ap) {
- mgb::LogLevel mgb_level;
- switch (dnn_level) {
- case megdnn::LogLevel::DEBUG:
- mgb_level = LogLevel::DEBUG;
- break;
- case megdnn::LogLevel::INFO:
- mgb_level = LogLevel::INFO;
- break;
- case megdnn::LogLevel::WARN:
- mgb_level = LogLevel::WARN;
- break;
- default:
- mgb_level = LogLevel::ERROR;
- }
- if (mgb_level < min_log_level) {
- return;
- }
-
- std::string new_fmt{"[dnn] "};
- new_fmt.append(fmt);
- log_handler(mgb_level, file, func, line, new_fmt.c_str(), ap);
- }
-
- public:
- MegDNNLogHandler() { megdnn::set_log_handler(dnn_log_handler); }
- };
- MegDNNLogHandler g_megdnn_log_handler_init;
- } // anonymous namespace
-
- void mgb::__log__(LogLevel level,
- const char *file, const char *func, int line, const char *fmt, ...) {
- if (level < min_log_level)
- return;
-
- va_list ap;
- va_start(ap, fmt);
- log_handler(level, file, func, line, fmt, ap);
- va_end(ap);
- }
-
- /* ===================== forward log in MegWave ===================== */
- // common::Log is a weak symbol in megwave
- namespace common {
- enum class LogLevel { kInfo, kWarn, kDebug, kFatal };
- void Log(LogLevel level, char const* file, int line, char const* func,
- char const *fmt, ...) {
-
- std::string new_fmt("[wave] ");
- new_fmt.append(fmt);
- va_list ap;
- va_start(ap, fmt);
- log_handler(level == LogLevel::kWarn ? mgb::LogLevel::WARN :
- mgb::LogLevel::DEBUG,
- file, func, line, new_fmt.c_str(), ap);
- va_end(ap);
- }
- }
-
- #else // MGB_ENABLE_LOGGING
-
- namespace {
- void default_log_handler(LogLevel ,
- const char *, const char *, int , const char *,
- va_list ) {
- }
- LogHandler log_handler = default_log_handler;
- }
-
- #endif // MGB_ENABLE_LOGGING
-
- LogLevel mgb::set_log_level(LogLevel level) {
- if (auto env = ::std::getenv("RUNTIME_OVERRIDE_LOG_LEVEL"))
- level = static_cast<LogLevel>(std::stoi(env));
-
- #ifdef __ANDROID__
- //! special for Android prop, attention: getprop may need permission
- char buf[PROP_VALUE_MAX];
- if (__system_property_get("RUNTIME_OVERRIDE_LOG_LEVEL", buf) > 0) {
- level = static_cast<LogLevel>(atoi(buf));
- }
- #endif
-
- auto ret = min_log_level;
- min_log_level = level;
- return ret;
- }
-
- LogLevel mgb::get_log_level() {
- return min_log_level;
- }
-
- LogHandler mgb::set_log_handler(LogHandler handler) {
- auto ret = log_handler;
- log_handler = handler;
- return ret;
- }
-
- void mgb::__assert_fail__(
- const char *file, int line, const char *func,
- const char *expr, const char *msg_fmt, ...) {
-
- std::string msg = ssprintf("assertion `%s' failed at %s:%d: %s",
- expr, file, line, func);
- if (msg_fmt) {
- msg_fmt = convert_fmt_str(msg_fmt);
- va_list ap;
- va_start(ap, msg_fmt);
- msg.append("\nextra message: ");
- msg.append(svsprintf(msg_fmt, ap));
- va_end(ap);
- }
- mgb_throw_raw(AssertionError{msg});
- }
-
- #if MGB_ENABLE_LOGGING && !MGB_ENABLE_EXCEPTION
- void mgb::__on_exception_throw__(const std::exception &exc) {
- mgb_log_error("exception thrown: %s", exc.what());
- mgb_log_error("abort now due to previous error");
- mgb_trap();
- }
- #endif
-
- std::string mgb::svsprintf(const char *fmt, va_list ap_orig) {
- fmt = convert_fmt_str(fmt);
- int size = 100; /* Guess we need no more than 100 bytes */
- char *p;
-
- if ((p = (char*)malloc(size)) == nullptr)
- goto err;
-
- for (; ;) {
- va_list ap;
- va_copy(ap, ap_orig);
- int n = vsnprintf(p, size, fmt, ap);
- va_end(ap);
-
- #ifdef WIN32
- if (n == -1) {
- n = _vscprintf(fmt, ap_orig);
- mgb_assert(n >= size);
- }
- #endif
-
- if (n < 0)
- goto err;
-
- if (n < size) {
- std::string rst(p);
- free(p);
- return rst;
- }
-
- size = n + 1;
-
- char *np = (char*)realloc(p, size);
- if (!np) {
- free(p);
- goto err;
- } else
- p = np;
- }
-
- err:
- fprintf(stderr, "could not allocate memory for svsprintf; fmt=%s\n",
- fmt);
- mgb_trap();
- }
-
- std::string mgb::ssprintf(const char *fmt, ...) {
- va_list ap;
- va_start(ap, fmt);
- auto rst = svsprintf(fmt, ap);
- va_end(ap);
- return rst;
- }
-
-
- // vim: syntax=cpp.doxygen foldmethod=marker foldmarker=f{{{,f}}}
|