e3cb659541a3cc0755b083e7b2015ded5f044f45
[platform/adaptation/npu/trix-engine.git] / src / core / utils / ne-utils.cc
1 /**
2  * Proprietary
3  * Copyright (C) 2019 Samsung Electronics
4  * Copyright (C) 2019 Dongju Chae <dongju.chae@samsung.com>
5  */
6 /**
7  * @file NE-utils.cc
8  * @date 13 June 2019
9  * @brief Utility libraries for NPU Engine and other related components.
10  * @author Dongju Chae <dongju.chae@samsung.com>
11  * @bug No known bugs except for NYI items
12  */
13
14 #include <sys/timeb.h>
15 #include <assert.h>
16 #include <stdarg.h>
17
18 #include "ne-utils.h"
19 #include "ne-conf.h"
20
21 /********************************************************************
22  * Logging utilities                                                *
23  ********************************************************************/
24 #define LOG_FILENAME "npu-engine.log"
25 #define MAX_LOG_MSG 512
26
27 /**
28  * @brief Log Level String in 5 characters
29  */
30 static const char *loglevelstr[NPU_LOG_END] = {
31     [NPU_LOG_NONE] = "NONE",
32     [NPU_LOG_ERROR] = "ERROR",
33     [NPU_LOG_WARN] = "WARN ",
34     [NPU_LOG_INFO] = "INFO ",
35 };
36
37 /**
38  * @brief Module Name String in 8 characters
39  */
40 static const char *modulestr[_NEND] = {
41     [_N1] = "N1/CommPl",  [_N11] = "N11/IP   ", [_N2] = "N2/Handlr",  [_N21] = "N21/Host ",
42     [_N3] = "N3/Sched ",  [_N4] = "N4/InputC",  [_N41] = "N41/HWrec", [_N42] = "N42/Host ",
43     [_N5] = "N5/ThPool",  [_N6] = "N6/Mem   ",  [_N61] = "N61/MemDe", [_N62] = "N62/MemPl",
44     [_N7] = "N7/HWmem ",  [_N71] = "N71/Model", [_N72] = "N72/Buff ", [_N73] = "N72/Segt ",
45     [_N8] = "N8/HWmemI",  [_N9] = "N9/NPUdrv",  [_N91] = "N91/TRIV ", [_N92] = "N92/TRIV2",
46     [_N93] = "N93/TRIA ", [_N94] = "N94/Emul ",
47 };
48
49 /** @brief singleton instance */
50 std::unique_ptr<Logger> Logger::instance_;
51 std::once_flag Logger::once_flag_;
52
53 /** @brief logger destructor. close the file pointer if opened before */
54 Logger::~Logger () {
55   std::unique_lock<std::mutex> lock (m_);
56   if (fp_ != nullptr)
57     fclose (fp_);
58 }
59
60 Logger &
61 Logger::getInstance () {
62   call_once (once_flag_, []() { instance_.reset (new Logger); });
63   return *(instance_.get ());
64 }
65
66 /**
67  * @brief Write a log, to a logfile designated by conf
68  * @param[in] l Loglevel
69  * @param[in] m Module designation
70  *
71  * @return The number of characters that would be consumed. If there is an error,
72  *        a negative value is returned. Note that 0 is not regarded as an error.
73  */
74 int
75 Logger::logwrite (npu_loglevel l, module m, const char *format, ...) {
76   va_list args;
77   int ret;
78
79   if (l <= NPU_LOG_NONE || l >= NPU_LOG_END)
80     return -EINVAL;
81
82   if (format == nullptr)
83     return -EINVAL;
84
85   if (m < _N1 || m >= _NEND)
86     return -EINVAL;
87
88   va_start (args, format);
89   ret = logwrite_args (l, modulestr[m], format, args);
90   va_end (args);
91
92   return ret;
93 }
94
95 int
96 Logger::logwrite_args (npu_loglevel l, const char *tag, const char *format, va_list args) {
97   std::unique_lock<std::mutex> lock (m_);
98
99   time_t ltime = time (nullptr);
100   char *time_str;
101
102   /**
103    * localtime() and asctime() are not MT-safe. There are alternatives,
104    * localtime_r() and asctime_r(), when __USE_POSIX is set. Without them, we
105    * need critical section here.
106    */
107   time_str = asctime (localtime (&ltime));
108   time_str[strcspn (time_str, "\n")] = '\x00';
109
110   char log_msg[MAX_LOG_MSG];
111   int log_len = snprintf (log_msg, MAX_LOG_MSG, "[%s][%s][%s] ", loglevelstr[l], tag, time_str);
112
113   log_len += vsnprintf (log_msg + log_len, MAX_LOG_MSG - log_len, format, args);
114
115   if (Conf::getInstance ().getLogLevel () >= l) {
116     fprintf (stderr, "%s\n", log_msg);
117     fflush (stderr);
118   }
119
120 #ifdef __TIZEN__
121   if (l == NPU_LOG_ERROR)
122     ml_loge ("%s", log_msg);
123   else if (l == NPU_LOG_WARN)
124     ml_logw ("%s", log_msg);
125   else if (l == NPU_LOG_INFO)
126     ml_logi ("%s", log_msg);
127 #endif
128
129   if (fp_ == nullptr) {
130     char filename[FILENAME_MAX];
131
132     snprintf (filename, FILENAME_MAX, "%s/%s", Conf::getInstance ().getLogDir (), LOG_FILENAME);
133     fp_ = fopen (filename, "a");
134     if (fp_ == nullptr)
135       return -errno;
136   }
137
138   fprintf (fp_, "%s\n", log_msg);
139   fflush (fp_);
140
141   return 0;
142 }