1*61046927SAndroid Build Coastguard Worker /*
2*61046927SAndroid Build Coastguard Worker * Copyright © 2017 Google, Inc.
3*61046927SAndroid Build Coastguard Worker *
4*61046927SAndroid Build Coastguard Worker * Permission is hereby granted, free of charge, to any person obtaining a
5*61046927SAndroid Build Coastguard Worker * copy of this software and associated documentation files (the "Software"),
6*61046927SAndroid Build Coastguard Worker * to deal in the Software without restriction, including without limitation
7*61046927SAndroid Build Coastguard Worker * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8*61046927SAndroid Build Coastguard Worker * and/or sell copies of the Software, and to permit persons to whom the
9*61046927SAndroid Build Coastguard Worker * Software is furnished to do so, subject to the following conditions:
10*61046927SAndroid Build Coastguard Worker *
11*61046927SAndroid Build Coastguard Worker * The above copyright notice and this permission notice (including the next
12*61046927SAndroid Build Coastguard Worker * paragraph) shall be included in all copies or substantial portions of the
13*61046927SAndroid Build Coastguard Worker * Software.
14*61046927SAndroid Build Coastguard Worker *
15*61046927SAndroid Build Coastguard Worker * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16*61046927SAndroid Build Coastguard Worker * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17*61046927SAndroid Build Coastguard Worker * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18*61046927SAndroid Build Coastguard Worker * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19*61046927SAndroid Build Coastguard Worker * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20*61046927SAndroid Build Coastguard Worker * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21*61046927SAndroid Build Coastguard Worker * IN THE SOFTWARE.
22*61046927SAndroid Build Coastguard Worker */
23*61046927SAndroid Build Coastguard Worker
24*61046927SAndroid Build Coastguard Worker #include <stdarg.h>
25*61046927SAndroid Build Coastguard Worker #include <stdio.h>
26*61046927SAndroid Build Coastguard Worker #include <stdlib.h>
27*61046927SAndroid Build Coastguard Worker #include <string.h>
28*61046927SAndroid Build Coastguard Worker #include "c11/threads.h"
29*61046927SAndroid Build Coastguard Worker #include "util/detect_os.h"
30*61046927SAndroid Build Coastguard Worker #include "util/log.h"
31*61046927SAndroid Build Coastguard Worker #include "util/ralloc.h"
32*61046927SAndroid Build Coastguard Worker #include "util/u_debug.h"
33*61046927SAndroid Build Coastguard Worker
34*61046927SAndroid Build Coastguard Worker #if DETECT_OS_POSIX
35*61046927SAndroid Build Coastguard Worker #include <syslog.h>
36*61046927SAndroid Build Coastguard Worker #include "util/u_process.h"
37*61046927SAndroid Build Coastguard Worker #endif
38*61046927SAndroid Build Coastguard Worker
39*61046927SAndroid Build Coastguard Worker #if DETECT_OS_ANDROID
40*61046927SAndroid Build Coastguard Worker #include <android/log.h>
41*61046927SAndroid Build Coastguard Worker #endif
42*61046927SAndroid Build Coastguard Worker
43*61046927SAndroid Build Coastguard Worker #if DETECT_OS_WINDOWS
44*61046927SAndroid Build Coastguard Worker #include <windows.h>
45*61046927SAndroid Build Coastguard Worker #endif
46*61046927SAndroid Build Coastguard Worker
47*61046927SAndroid Build Coastguard Worker enum mesa_log_control {
48*61046927SAndroid Build Coastguard Worker MESA_LOG_CONTROL_NULL = 1 << 0,
49*61046927SAndroid Build Coastguard Worker MESA_LOG_CONTROL_FILE = 1 << 1,
50*61046927SAndroid Build Coastguard Worker MESA_LOG_CONTROL_SYSLOG = 1 << 2,
51*61046927SAndroid Build Coastguard Worker MESA_LOG_CONTROL_ANDROID = 1 << 3,
52*61046927SAndroid Build Coastguard Worker MESA_LOG_CONTROL_WINDBG = 1 << 4,
53*61046927SAndroid Build Coastguard Worker MESA_LOG_CONTROL_LOGGER_MASK = 0xff,
54*61046927SAndroid Build Coastguard Worker
55*61046927SAndroid Build Coastguard Worker MESA_LOG_CONTROL_WAIT = 1 << 8,
56*61046927SAndroid Build Coastguard Worker };
57*61046927SAndroid Build Coastguard Worker
58*61046927SAndroid Build Coastguard Worker static const struct debug_control mesa_log_control_options[] = {
59*61046927SAndroid Build Coastguard Worker /* loggers */
60*61046927SAndroid Build Coastguard Worker { "null", MESA_LOG_CONTROL_NULL },
61*61046927SAndroid Build Coastguard Worker { "file", MESA_LOG_CONTROL_FILE },
62*61046927SAndroid Build Coastguard Worker { "syslog", MESA_LOG_CONTROL_SYSLOG },
63*61046927SAndroid Build Coastguard Worker { "android", MESA_LOG_CONTROL_ANDROID },
64*61046927SAndroid Build Coastguard Worker { "windbg", MESA_LOG_CONTROL_WINDBG },
65*61046927SAndroid Build Coastguard Worker /* flags */
66*61046927SAndroid Build Coastguard Worker { "wait", MESA_LOG_CONTROL_WAIT },
67*61046927SAndroid Build Coastguard Worker { NULL, 0 },
68*61046927SAndroid Build Coastguard Worker };
69*61046927SAndroid Build Coastguard Worker
70*61046927SAndroid Build Coastguard Worker static uint32_t mesa_log_control;
71*61046927SAndroid Build Coastguard Worker static FILE *mesa_log_file;
72*61046927SAndroid Build Coastguard Worker
73*61046927SAndroid Build Coastguard Worker static void
mesa_log_init_once(void)74*61046927SAndroid Build Coastguard Worker mesa_log_init_once(void)
75*61046927SAndroid Build Coastguard Worker {
76*61046927SAndroid Build Coastguard Worker mesa_log_control = parse_debug_string(os_get_option("MESA_LOG"),
77*61046927SAndroid Build Coastguard Worker mesa_log_control_options);
78*61046927SAndroid Build Coastguard Worker
79*61046927SAndroid Build Coastguard Worker if (!(mesa_log_control & MESA_LOG_CONTROL_LOGGER_MASK)) {
80*61046927SAndroid Build Coastguard Worker /* pick the default loggers */
81*61046927SAndroid Build Coastguard Worker #if DETECT_OS_ANDROID
82*61046927SAndroid Build Coastguard Worker mesa_log_control |= MESA_LOG_CONTROL_ANDROID;
83*61046927SAndroid Build Coastguard Worker #else
84*61046927SAndroid Build Coastguard Worker mesa_log_control |= MESA_LOG_CONTROL_FILE;
85*61046927SAndroid Build Coastguard Worker #endif
86*61046927SAndroid Build Coastguard Worker
87*61046927SAndroid Build Coastguard Worker #if DETECT_OS_WINDOWS
88*61046927SAndroid Build Coastguard Worker /* stderr from windows applications without console is not usually
89*61046927SAndroid Build Coastguard Worker * visible, so communicate with the debugger instead */
90*61046927SAndroid Build Coastguard Worker mesa_log_control |= MESA_LOG_CONTROL_WINDBG;
91*61046927SAndroid Build Coastguard Worker #endif
92*61046927SAndroid Build Coastguard Worker }
93*61046927SAndroid Build Coastguard Worker
94*61046927SAndroid Build Coastguard Worker mesa_log_file = stderr;
95*61046927SAndroid Build Coastguard Worker
96*61046927SAndroid Build Coastguard Worker #if !DETECT_OS_WINDOWS
97*61046927SAndroid Build Coastguard Worker if (__normal_user()) {
98*61046927SAndroid Build Coastguard Worker const char *log_file = os_get_option("MESA_LOG_FILE");
99*61046927SAndroid Build Coastguard Worker if (log_file) {
100*61046927SAndroid Build Coastguard Worker FILE *fp = fopen(log_file, "w");
101*61046927SAndroid Build Coastguard Worker if (fp) {
102*61046927SAndroid Build Coastguard Worker mesa_log_file = fp;
103*61046927SAndroid Build Coastguard Worker mesa_log_control |= MESA_LOG_CONTROL_FILE;
104*61046927SAndroid Build Coastguard Worker }
105*61046927SAndroid Build Coastguard Worker }
106*61046927SAndroid Build Coastguard Worker }
107*61046927SAndroid Build Coastguard Worker #endif
108*61046927SAndroid Build Coastguard Worker
109*61046927SAndroid Build Coastguard Worker #if DETECT_OS_POSIX
110*61046927SAndroid Build Coastguard Worker if (mesa_log_control & MESA_LOG_CONTROL_SYSLOG)
111*61046927SAndroid Build Coastguard Worker openlog(util_get_process_name(), LOG_NDELAY | LOG_PID, LOG_USER);
112*61046927SAndroid Build Coastguard Worker #endif
113*61046927SAndroid Build Coastguard Worker }
114*61046927SAndroid Build Coastguard Worker
115*61046927SAndroid Build Coastguard Worker static void
mesa_log_init(void)116*61046927SAndroid Build Coastguard Worker mesa_log_init(void)
117*61046927SAndroid Build Coastguard Worker {
118*61046927SAndroid Build Coastguard Worker static once_flag once = ONCE_FLAG_INIT;
119*61046927SAndroid Build Coastguard Worker call_once(&once, mesa_log_init_once);
120*61046927SAndroid Build Coastguard Worker }
121*61046927SAndroid Build Coastguard Worker
122*61046927SAndroid Build Coastguard Worker void
mesa_log_if_debug(enum mesa_log_level level,const char * outputString)123*61046927SAndroid Build Coastguard Worker mesa_log_if_debug(enum mesa_log_level level, const char *outputString)
124*61046927SAndroid Build Coastguard Worker {
125*61046927SAndroid Build Coastguard Worker static int debug = -1;
126*61046927SAndroid Build Coastguard Worker
127*61046927SAndroid Build Coastguard Worker /* Init the local 'debug' var once. */
128*61046927SAndroid Build Coastguard Worker if (debug == -1) {
129*61046927SAndroid Build Coastguard Worker const char *env = getenv("MESA_DEBUG");
130*61046927SAndroid Build Coastguard Worker bool silent = env && strstr(env, "silent") != NULL;
131*61046927SAndroid Build Coastguard Worker #ifndef NDEBUG
132*61046927SAndroid Build Coastguard Worker /* in debug builds, print messages unless MESA_DEBUG="silent" */
133*61046927SAndroid Build Coastguard Worker if (silent)
134*61046927SAndroid Build Coastguard Worker debug = 0;
135*61046927SAndroid Build Coastguard Worker else
136*61046927SAndroid Build Coastguard Worker debug = 1;
137*61046927SAndroid Build Coastguard Worker #else
138*61046927SAndroid Build Coastguard Worker /* in release builds, print messages if any MESA_DEBUG value other than
139*61046927SAndroid Build Coastguard Worker * MESA_DEBUG="silent" is set
140*61046927SAndroid Build Coastguard Worker */
141*61046927SAndroid Build Coastguard Worker debug = env && !silent;
142*61046927SAndroid Build Coastguard Worker #endif
143*61046927SAndroid Build Coastguard Worker }
144*61046927SAndroid Build Coastguard Worker
145*61046927SAndroid Build Coastguard Worker /* Now only print the string if we're required to do so. */
146*61046927SAndroid Build Coastguard Worker if (debug)
147*61046927SAndroid Build Coastguard Worker mesa_log(level, "Mesa", "%s", outputString);
148*61046927SAndroid Build Coastguard Worker }
149*61046927SAndroid Build Coastguard Worker
150*61046927SAndroid Build Coastguard Worker static inline const char *
level_to_str(enum mesa_log_level l)151*61046927SAndroid Build Coastguard Worker level_to_str(enum mesa_log_level l)
152*61046927SAndroid Build Coastguard Worker {
153*61046927SAndroid Build Coastguard Worker switch (l) {
154*61046927SAndroid Build Coastguard Worker case MESA_LOG_ERROR: return "error";
155*61046927SAndroid Build Coastguard Worker case MESA_LOG_WARN: return "warning";
156*61046927SAndroid Build Coastguard Worker case MESA_LOG_INFO: return "info";
157*61046927SAndroid Build Coastguard Worker case MESA_LOG_DEBUG: return "debug";
158*61046927SAndroid Build Coastguard Worker }
159*61046927SAndroid Build Coastguard Worker
160*61046927SAndroid Build Coastguard Worker unreachable("bad mesa_log_level");
161*61046927SAndroid Build Coastguard Worker }
162*61046927SAndroid Build Coastguard Worker
163*61046927SAndroid Build Coastguard Worker enum logger_vasnprintf_affix {
164*61046927SAndroid Build Coastguard Worker LOGGER_VASNPRINTF_AFFIX_TAG = 1 << 0,
165*61046927SAndroid Build Coastguard Worker LOGGER_VASNPRINTF_AFFIX_LEVEL = 1 << 1,
166*61046927SAndroid Build Coastguard Worker LOGGER_VASNPRINTF_AFFIX_NEWLINE = 1 << 2,
167*61046927SAndroid Build Coastguard Worker };
168*61046927SAndroid Build Coastguard Worker
169*61046927SAndroid Build Coastguard Worker /* Try vsnprintf first and fall back to vasprintf if buf is too small. This
170*61046927SAndroid Build Coastguard Worker * function handles all errors and never fails.
171*61046927SAndroid Build Coastguard Worker */
172*61046927SAndroid Build Coastguard Worker static char *
logger_vasnprintf(char * buf,int size,int affixes,enum mesa_log_level level,const char * tag,const char * format,va_list in_va)173*61046927SAndroid Build Coastguard Worker logger_vasnprintf(char *buf,
174*61046927SAndroid Build Coastguard Worker int size,
175*61046927SAndroid Build Coastguard Worker int affixes,
176*61046927SAndroid Build Coastguard Worker enum mesa_log_level level,
177*61046927SAndroid Build Coastguard Worker const char *tag,
178*61046927SAndroid Build Coastguard Worker const char *format,
179*61046927SAndroid Build Coastguard Worker va_list in_va)
180*61046927SAndroid Build Coastguard Worker {
181*61046927SAndroid Build Coastguard Worker struct {
182*61046927SAndroid Build Coastguard Worker char *cur;
183*61046927SAndroid Build Coastguard Worker int rem;
184*61046927SAndroid Build Coastguard Worker int total;
185*61046927SAndroid Build Coastguard Worker bool invalid;
186*61046927SAndroid Build Coastguard Worker } state = {
187*61046927SAndroid Build Coastguard Worker .cur = buf,
188*61046927SAndroid Build Coastguard Worker .rem = size,
189*61046927SAndroid Build Coastguard Worker };
190*61046927SAndroid Build Coastguard Worker
191*61046927SAndroid Build Coastguard Worker va_list va;
192*61046927SAndroid Build Coastguard Worker va_copy(va, in_va);
193*61046927SAndroid Build Coastguard Worker
194*61046927SAndroid Build Coastguard Worker #define APPEND(state, func, ...) \
195*61046927SAndroid Build Coastguard Worker do { \
196*61046927SAndroid Build Coastguard Worker int ret = func(state.cur, state.rem, __VA_ARGS__); \
197*61046927SAndroid Build Coastguard Worker if (ret < 0) { \
198*61046927SAndroid Build Coastguard Worker state.invalid = true; \
199*61046927SAndroid Build Coastguard Worker } else { \
200*61046927SAndroid Build Coastguard Worker state.total += ret; \
201*61046927SAndroid Build Coastguard Worker if (ret >= state.rem) \
202*61046927SAndroid Build Coastguard Worker ret = state.rem; \
203*61046927SAndroid Build Coastguard Worker state.cur += ret; \
204*61046927SAndroid Build Coastguard Worker state.rem -= ret; \
205*61046927SAndroid Build Coastguard Worker } \
206*61046927SAndroid Build Coastguard Worker } while (false)
207*61046927SAndroid Build Coastguard Worker
208*61046927SAndroid Build Coastguard Worker if (affixes & LOGGER_VASNPRINTF_AFFIX_TAG)
209*61046927SAndroid Build Coastguard Worker APPEND(state, snprintf, "%s: ", tag);
210*61046927SAndroid Build Coastguard Worker if (affixes & LOGGER_VASNPRINTF_AFFIX_LEVEL)
211*61046927SAndroid Build Coastguard Worker APPEND(state, snprintf, "%s: ", level_to_str(level));
212*61046927SAndroid Build Coastguard Worker
213*61046927SAndroid Build Coastguard Worker APPEND(state, vsnprintf, format, va);
214*61046927SAndroid Build Coastguard Worker
215*61046927SAndroid Build Coastguard Worker if (affixes & LOGGER_VASNPRINTF_AFFIX_NEWLINE) {
216*61046927SAndroid Build Coastguard Worker if (state.cur == buf || state.cur[-1] != '\n')
217*61046927SAndroid Build Coastguard Worker APPEND(state, snprintf, "\n");
218*61046927SAndroid Build Coastguard Worker }
219*61046927SAndroid Build Coastguard Worker #undef APPEND
220*61046927SAndroid Build Coastguard Worker
221*61046927SAndroid Build Coastguard Worker assert(size >= 64);
222*61046927SAndroid Build Coastguard Worker if (state.invalid) {
223*61046927SAndroid Build Coastguard Worker strncpy(buf, "invalid message format", size);
224*61046927SAndroid Build Coastguard Worker } else if (state.total >= size) {
225*61046927SAndroid Build Coastguard Worker /* print again into alloc to avoid truncation */
226*61046927SAndroid Build Coastguard Worker void *alloc = malloc(state.total + 1);
227*61046927SAndroid Build Coastguard Worker if (alloc) {
228*61046927SAndroid Build Coastguard Worker buf = logger_vasnprintf(alloc, state.total + 1, affixes, level, tag,
229*61046927SAndroid Build Coastguard Worker format, in_va);
230*61046927SAndroid Build Coastguard Worker assert(buf == alloc);
231*61046927SAndroid Build Coastguard Worker } else {
232*61046927SAndroid Build Coastguard Worker /* pretty-truncate the message */
233*61046927SAndroid Build Coastguard Worker strncpy(buf + size - 4, "...", 4);
234*61046927SAndroid Build Coastguard Worker }
235*61046927SAndroid Build Coastguard Worker }
236*61046927SAndroid Build Coastguard Worker
237*61046927SAndroid Build Coastguard Worker va_end(va);
238*61046927SAndroid Build Coastguard Worker
239*61046927SAndroid Build Coastguard Worker return buf;
240*61046927SAndroid Build Coastguard Worker }
241*61046927SAndroid Build Coastguard Worker
242*61046927SAndroid Build Coastguard Worker static void
logger_file(enum mesa_log_level level,const char * tag,const char * format,va_list va)243*61046927SAndroid Build Coastguard Worker logger_file(enum mesa_log_level level,
244*61046927SAndroid Build Coastguard Worker const char *tag,
245*61046927SAndroid Build Coastguard Worker const char *format,
246*61046927SAndroid Build Coastguard Worker va_list va)
247*61046927SAndroid Build Coastguard Worker {
248*61046927SAndroid Build Coastguard Worker FILE *fp = mesa_log_file;
249*61046927SAndroid Build Coastguard Worker char local_msg[1024];
250*61046927SAndroid Build Coastguard Worker char *msg = logger_vasnprintf(local_msg, sizeof(local_msg),
251*61046927SAndroid Build Coastguard Worker LOGGER_VASNPRINTF_AFFIX_TAG |
252*61046927SAndroid Build Coastguard Worker LOGGER_VASNPRINTF_AFFIX_LEVEL |
253*61046927SAndroid Build Coastguard Worker LOGGER_VASNPRINTF_AFFIX_NEWLINE,
254*61046927SAndroid Build Coastguard Worker level, tag, format, va);
255*61046927SAndroid Build Coastguard Worker
256*61046927SAndroid Build Coastguard Worker fprintf(fp, "%s", msg);
257*61046927SAndroid Build Coastguard Worker fflush(fp);
258*61046927SAndroid Build Coastguard Worker
259*61046927SAndroid Build Coastguard Worker if (msg != local_msg)
260*61046927SAndroid Build Coastguard Worker free(msg);
261*61046927SAndroid Build Coastguard Worker }
262*61046927SAndroid Build Coastguard Worker
263*61046927SAndroid Build Coastguard Worker #if DETECT_OS_POSIX
264*61046927SAndroid Build Coastguard Worker
265*61046927SAndroid Build Coastguard Worker static inline int
level_to_syslog(enum mesa_log_level l)266*61046927SAndroid Build Coastguard Worker level_to_syslog(enum mesa_log_level l)
267*61046927SAndroid Build Coastguard Worker {
268*61046927SAndroid Build Coastguard Worker switch (l) {
269*61046927SAndroid Build Coastguard Worker case MESA_LOG_ERROR: return LOG_ERR;
270*61046927SAndroid Build Coastguard Worker case MESA_LOG_WARN: return LOG_WARNING;
271*61046927SAndroid Build Coastguard Worker case MESA_LOG_INFO: return LOG_INFO;
272*61046927SAndroid Build Coastguard Worker case MESA_LOG_DEBUG: return LOG_DEBUG;
273*61046927SAndroid Build Coastguard Worker }
274*61046927SAndroid Build Coastguard Worker
275*61046927SAndroid Build Coastguard Worker unreachable("bad mesa_log_level");
276*61046927SAndroid Build Coastguard Worker }
277*61046927SAndroid Build Coastguard Worker
278*61046927SAndroid Build Coastguard Worker static void
logger_syslog(enum mesa_log_level level,const char * tag,const char * format,va_list va)279*61046927SAndroid Build Coastguard Worker logger_syslog(enum mesa_log_level level,
280*61046927SAndroid Build Coastguard Worker const char *tag,
281*61046927SAndroid Build Coastguard Worker const char *format,
282*61046927SAndroid Build Coastguard Worker va_list va)
283*61046927SAndroid Build Coastguard Worker {
284*61046927SAndroid Build Coastguard Worker char local_msg[1024];
285*61046927SAndroid Build Coastguard Worker char *msg = logger_vasnprintf(local_msg, sizeof(local_msg),
286*61046927SAndroid Build Coastguard Worker LOGGER_VASNPRINTF_AFFIX_TAG, level, tag, format, va);
287*61046927SAndroid Build Coastguard Worker
288*61046927SAndroid Build Coastguard Worker syslog(level_to_syslog(level), "%s", msg);
289*61046927SAndroid Build Coastguard Worker
290*61046927SAndroid Build Coastguard Worker if (msg != local_msg)
291*61046927SAndroid Build Coastguard Worker free(msg);
292*61046927SAndroid Build Coastguard Worker }
293*61046927SAndroid Build Coastguard Worker
294*61046927SAndroid Build Coastguard Worker #endif /* DETECT_OS_POSIX */
295*61046927SAndroid Build Coastguard Worker
296*61046927SAndroid Build Coastguard Worker #if DETECT_OS_ANDROID
297*61046927SAndroid Build Coastguard Worker
298*61046927SAndroid Build Coastguard Worker static inline android_LogPriority
level_to_android(enum mesa_log_level l)299*61046927SAndroid Build Coastguard Worker level_to_android(enum mesa_log_level l)
300*61046927SAndroid Build Coastguard Worker {
301*61046927SAndroid Build Coastguard Worker switch (l) {
302*61046927SAndroid Build Coastguard Worker case MESA_LOG_ERROR: return ANDROID_LOG_ERROR;
303*61046927SAndroid Build Coastguard Worker case MESA_LOG_WARN: return ANDROID_LOG_WARN;
304*61046927SAndroid Build Coastguard Worker case MESA_LOG_INFO: return ANDROID_LOG_INFO;
305*61046927SAndroid Build Coastguard Worker case MESA_LOG_DEBUG: return ANDROID_LOG_DEBUG;
306*61046927SAndroid Build Coastguard Worker }
307*61046927SAndroid Build Coastguard Worker
308*61046927SAndroid Build Coastguard Worker unreachable("bad mesa_log_level");
309*61046927SAndroid Build Coastguard Worker }
310*61046927SAndroid Build Coastguard Worker
311*61046927SAndroid Build Coastguard Worker static void
logger_android(enum mesa_log_level level,const char * tag,const char * format,va_list va)312*61046927SAndroid Build Coastguard Worker logger_android(enum mesa_log_level level,
313*61046927SAndroid Build Coastguard Worker const char *tag,
314*61046927SAndroid Build Coastguard Worker const char *format,
315*61046927SAndroid Build Coastguard Worker va_list va)
316*61046927SAndroid Build Coastguard Worker {
317*61046927SAndroid Build Coastguard Worker /* Android can truncate/drop messages
318*61046927SAndroid Build Coastguard Worker *
319*61046927SAndroid Build Coastguard Worker * - the internal buffer for vsnprintf has a fixed size (usually 1024)
320*61046927SAndroid Build Coastguard Worker * - the socket to logd is non-blocking
321*61046927SAndroid Build Coastguard Worker *
322*61046927SAndroid Build Coastguard Worker * and provides no way to detect. Try our best.
323*61046927SAndroid Build Coastguard Worker */
324*61046927SAndroid Build Coastguard Worker char local_msg[1024];
325*61046927SAndroid Build Coastguard Worker char *msg = logger_vasnprintf(local_msg, sizeof(local_msg), 0, level, tag,
326*61046927SAndroid Build Coastguard Worker format, va);
327*61046927SAndroid Build Coastguard Worker
328*61046927SAndroid Build Coastguard Worker __android_log_write(level_to_android(level), tag, msg);
329*61046927SAndroid Build Coastguard Worker
330*61046927SAndroid Build Coastguard Worker if (msg != local_msg)
331*61046927SAndroid Build Coastguard Worker free(msg);
332*61046927SAndroid Build Coastguard Worker
333*61046927SAndroid Build Coastguard Worker /* increase the chance of logd doing its part */
334*61046927SAndroid Build Coastguard Worker if (mesa_log_control & MESA_LOG_CONTROL_WAIT)
335*61046927SAndroid Build Coastguard Worker thrd_yield();
336*61046927SAndroid Build Coastguard Worker }
337*61046927SAndroid Build Coastguard Worker
338*61046927SAndroid Build Coastguard Worker #endif /* DETECT_OS_ANDROID */
339*61046927SAndroid Build Coastguard Worker
340*61046927SAndroid Build Coastguard Worker #if DETECT_OS_WINDOWS
341*61046927SAndroid Build Coastguard Worker
342*61046927SAndroid Build Coastguard Worker static void
logger_windbg(enum mesa_log_level level,const char * tag,const char * format,va_list va)343*61046927SAndroid Build Coastguard Worker logger_windbg(enum mesa_log_level level,
344*61046927SAndroid Build Coastguard Worker const char *tag,
345*61046927SAndroid Build Coastguard Worker const char *format,
346*61046927SAndroid Build Coastguard Worker va_list va)
347*61046927SAndroid Build Coastguard Worker {
348*61046927SAndroid Build Coastguard Worker char local_msg[1024];
349*61046927SAndroid Build Coastguard Worker char *msg = logger_vasnprintf(local_msg, sizeof(local_msg),
350*61046927SAndroid Build Coastguard Worker LOGGER_VASNPRINTF_AFFIX_TAG |
351*61046927SAndroid Build Coastguard Worker LOGGER_VASNPRINTF_AFFIX_LEVEL |
352*61046927SAndroid Build Coastguard Worker LOGGER_VASNPRINTF_AFFIX_NEWLINE,
353*61046927SAndroid Build Coastguard Worker level, tag, format, va);
354*61046927SAndroid Build Coastguard Worker
355*61046927SAndroid Build Coastguard Worker OutputDebugStringA(msg);
356*61046927SAndroid Build Coastguard Worker
357*61046927SAndroid Build Coastguard Worker if (msg != local_msg)
358*61046927SAndroid Build Coastguard Worker free(msg);
359*61046927SAndroid Build Coastguard Worker }
360*61046927SAndroid Build Coastguard Worker
361*61046927SAndroid Build Coastguard Worker #endif /* DETECT_OS_WINDOWS */
362*61046927SAndroid Build Coastguard Worker
363*61046927SAndroid Build Coastguard Worker /* This is for use with debug functions that take a FILE, such as
364*61046927SAndroid Build Coastguard Worker * nir_print_shader, although switching to nir_log_shader* is preferred.
365*61046927SAndroid Build Coastguard Worker */
366*61046927SAndroid Build Coastguard Worker FILE *
mesa_log_get_file(void)367*61046927SAndroid Build Coastguard Worker mesa_log_get_file(void)
368*61046927SAndroid Build Coastguard Worker {
369*61046927SAndroid Build Coastguard Worker mesa_log_init();
370*61046927SAndroid Build Coastguard Worker return mesa_log_file;
371*61046927SAndroid Build Coastguard Worker }
372*61046927SAndroid Build Coastguard Worker
373*61046927SAndroid Build Coastguard Worker void
mesa_log(enum mesa_log_level level,const char * tag,const char * format,...)374*61046927SAndroid Build Coastguard Worker mesa_log(enum mesa_log_level level, const char *tag, const char *format, ...)
375*61046927SAndroid Build Coastguard Worker {
376*61046927SAndroid Build Coastguard Worker va_list va;
377*61046927SAndroid Build Coastguard Worker
378*61046927SAndroid Build Coastguard Worker va_start(va, format);
379*61046927SAndroid Build Coastguard Worker mesa_log_v(level, tag, format, va);
380*61046927SAndroid Build Coastguard Worker va_end(va);
381*61046927SAndroid Build Coastguard Worker }
382*61046927SAndroid Build Coastguard Worker
383*61046927SAndroid Build Coastguard Worker void
mesa_log_v(enum mesa_log_level level,const char * tag,const char * format,va_list va)384*61046927SAndroid Build Coastguard Worker mesa_log_v(enum mesa_log_level level, const char *tag, const char *format,
385*61046927SAndroid Build Coastguard Worker va_list va)
386*61046927SAndroid Build Coastguard Worker {
387*61046927SAndroid Build Coastguard Worker static const struct {
388*61046927SAndroid Build Coastguard Worker enum mesa_log_control bit;
389*61046927SAndroid Build Coastguard Worker void (*log)(enum mesa_log_level level,
390*61046927SAndroid Build Coastguard Worker const char *tag,
391*61046927SAndroid Build Coastguard Worker const char *format,
392*61046927SAndroid Build Coastguard Worker va_list va);
393*61046927SAndroid Build Coastguard Worker } loggers[] = {
394*61046927SAndroid Build Coastguard Worker { MESA_LOG_CONTROL_FILE, logger_file },
395*61046927SAndroid Build Coastguard Worker #if DETECT_OS_POSIX
396*61046927SAndroid Build Coastguard Worker { MESA_LOG_CONTROL_SYSLOG, logger_syslog },
397*61046927SAndroid Build Coastguard Worker #endif
398*61046927SAndroid Build Coastguard Worker #if DETECT_OS_ANDROID
399*61046927SAndroid Build Coastguard Worker { MESA_LOG_CONTROL_ANDROID, logger_android },
400*61046927SAndroid Build Coastguard Worker #endif
401*61046927SAndroid Build Coastguard Worker #if DETECT_OS_WINDOWS
402*61046927SAndroid Build Coastguard Worker { MESA_LOG_CONTROL_WINDBG, logger_windbg },
403*61046927SAndroid Build Coastguard Worker #endif
404*61046927SAndroid Build Coastguard Worker };
405*61046927SAndroid Build Coastguard Worker
406*61046927SAndroid Build Coastguard Worker mesa_log_init();
407*61046927SAndroid Build Coastguard Worker
408*61046927SAndroid Build Coastguard Worker for (uint32_t i = 0; i < ARRAY_SIZE(loggers); i++) {
409*61046927SAndroid Build Coastguard Worker if (mesa_log_control & loggers[i].bit) {
410*61046927SAndroid Build Coastguard Worker va_list copy;
411*61046927SAndroid Build Coastguard Worker va_copy(copy, va);
412*61046927SAndroid Build Coastguard Worker loggers[i].log(level, tag, format, copy);
413*61046927SAndroid Build Coastguard Worker va_end(copy);
414*61046927SAndroid Build Coastguard Worker }
415*61046927SAndroid Build Coastguard Worker }
416*61046927SAndroid Build Coastguard Worker }
417*61046927SAndroid Build Coastguard Worker
418*61046927SAndroid Build Coastguard Worker void
_mesa_log(const char * fmtString,...)419*61046927SAndroid Build Coastguard Worker _mesa_log(const char *fmtString, ...)
420*61046927SAndroid Build Coastguard Worker {
421*61046927SAndroid Build Coastguard Worker char s[MAX_LOG_MESSAGE_LENGTH];
422*61046927SAndroid Build Coastguard Worker va_list args;
423*61046927SAndroid Build Coastguard Worker va_start(args, fmtString);
424*61046927SAndroid Build Coastguard Worker vsnprintf(s, MAX_LOG_MESSAGE_LENGTH, fmtString, args);
425*61046927SAndroid Build Coastguard Worker va_end(args);
426*61046927SAndroid Build Coastguard Worker mesa_log_if_debug(MESA_LOG_INFO, s);
427*61046927SAndroid Build Coastguard Worker }
428*61046927SAndroid Build Coastguard Worker
429*61046927SAndroid Build Coastguard Worker void
_mesa_log_direct(const char * string)430*61046927SAndroid Build Coastguard Worker _mesa_log_direct(const char *string)
431*61046927SAndroid Build Coastguard Worker {
432*61046927SAndroid Build Coastguard Worker mesa_log_if_debug(MESA_LOG_INFO, string);
433*61046927SAndroid Build Coastguard Worker }
434*61046927SAndroid Build Coastguard Worker
435*61046927SAndroid Build Coastguard Worker struct log_stream *
_mesa_log_stream_create(enum mesa_log_level level,const char * tag)436*61046927SAndroid Build Coastguard Worker _mesa_log_stream_create(enum mesa_log_level level, const char *tag)
437*61046927SAndroid Build Coastguard Worker {
438*61046927SAndroid Build Coastguard Worker struct log_stream *stream = ralloc(NULL, struct log_stream);
439*61046927SAndroid Build Coastguard Worker stream->level = level;
440*61046927SAndroid Build Coastguard Worker stream->tag = tag;
441*61046927SAndroid Build Coastguard Worker stream->msg = ralloc_strdup(stream, "");
442*61046927SAndroid Build Coastguard Worker stream->pos = 0;
443*61046927SAndroid Build Coastguard Worker return stream;
444*61046927SAndroid Build Coastguard Worker }
445*61046927SAndroid Build Coastguard Worker
446*61046927SAndroid Build Coastguard Worker void
mesa_log_stream_destroy(struct log_stream * stream)447*61046927SAndroid Build Coastguard Worker mesa_log_stream_destroy(struct log_stream *stream)
448*61046927SAndroid Build Coastguard Worker {
449*61046927SAndroid Build Coastguard Worker /* If you left trailing stuff in the log stream, flush it out as a line. */
450*61046927SAndroid Build Coastguard Worker if (stream->pos != 0)
451*61046927SAndroid Build Coastguard Worker mesa_log(stream->level, stream->tag, "%s", stream->msg);
452*61046927SAndroid Build Coastguard Worker
453*61046927SAndroid Build Coastguard Worker ralloc_free(stream);
454*61046927SAndroid Build Coastguard Worker }
455*61046927SAndroid Build Coastguard Worker
456*61046927SAndroid Build Coastguard Worker static void
mesa_log_stream_flush(struct log_stream * stream,size_t scan_offset)457*61046927SAndroid Build Coastguard Worker mesa_log_stream_flush(struct log_stream *stream, size_t scan_offset)
458*61046927SAndroid Build Coastguard Worker {
459*61046927SAndroid Build Coastguard Worker char *end;
460*61046927SAndroid Build Coastguard Worker char *next = stream->msg;
461*61046927SAndroid Build Coastguard Worker while ((end = strchr(stream->msg + scan_offset, '\n'))) {
462*61046927SAndroid Build Coastguard Worker *end = 0;
463*61046927SAndroid Build Coastguard Worker mesa_log(stream->level, stream->tag, "%s", next);
464*61046927SAndroid Build Coastguard Worker next = end + 1;
465*61046927SAndroid Build Coastguard Worker scan_offset = next - stream->msg;
466*61046927SAndroid Build Coastguard Worker }
467*61046927SAndroid Build Coastguard Worker if (next != stream->msg) {
468*61046927SAndroid Build Coastguard Worker /* Clear out the lines we printed and move any trailing chars to the start. */
469*61046927SAndroid Build Coastguard Worker size_t remaining = stream->msg + stream->pos - next;
470*61046927SAndroid Build Coastguard Worker memmove(stream->msg, next, remaining);
471*61046927SAndroid Build Coastguard Worker stream->pos = remaining;
472*61046927SAndroid Build Coastguard Worker }
473*61046927SAndroid Build Coastguard Worker }
474*61046927SAndroid Build Coastguard Worker
mesa_log_stream_printf(struct log_stream * stream,const char * format,...)475*61046927SAndroid Build Coastguard Worker void mesa_log_stream_printf(struct log_stream *stream, const char *format, ...)
476*61046927SAndroid Build Coastguard Worker {
477*61046927SAndroid Build Coastguard Worker size_t old_pos = stream->pos;
478*61046927SAndroid Build Coastguard Worker
479*61046927SAndroid Build Coastguard Worker va_list va;
480*61046927SAndroid Build Coastguard Worker va_start(va, format);
481*61046927SAndroid Build Coastguard Worker ralloc_vasprintf_rewrite_tail(&stream->msg, &stream->pos, format, va);
482*61046927SAndroid Build Coastguard Worker va_end(va);
483*61046927SAndroid Build Coastguard Worker
484*61046927SAndroid Build Coastguard Worker mesa_log_stream_flush(stream, old_pos);
485*61046927SAndroid Build Coastguard Worker }
486*61046927SAndroid Build Coastguard Worker
487*61046927SAndroid Build Coastguard Worker void
_mesa_log_multiline(enum mesa_log_level level,const char * tag,const char * lines)488*61046927SAndroid Build Coastguard Worker _mesa_log_multiline(enum mesa_log_level level, const char *tag, const char *lines)
489*61046927SAndroid Build Coastguard Worker {
490*61046927SAndroid Build Coastguard Worker struct log_stream tmp = {
491*61046927SAndroid Build Coastguard Worker .level = level,
492*61046927SAndroid Build Coastguard Worker .tag = tag,
493*61046927SAndroid Build Coastguard Worker .msg = strdup(lines),
494*61046927SAndroid Build Coastguard Worker .pos = strlen(lines),
495*61046927SAndroid Build Coastguard Worker };
496*61046927SAndroid Build Coastguard Worker mesa_log_stream_flush(&tmp, 0);
497*61046927SAndroid Build Coastguard Worker free(tmp.msg);
498*61046927SAndroid Build Coastguard Worker }
499