xref: /aosp_15_r20/external/XNNPACK/src/log.c (revision 4bdc94577ba0e567308109d787f7fec7b531ce36)
1 // Copyright (c) Facebook, Inc. and its affiliates.
2 // All rights reserved.
3 //
4 // Copyright 2022 Google LLC
5 //
6 // This source code is licensed under the BSD-style license found in the
7 // LICENSE file in the root directory of this source tree.
8 
9 #include <assert.h>
10 #include <stdarg.h>
11 #include <string.h>
12 #include <stdlib.h>
13 #include <stdio.h>
14 #ifdef _WIN32
15   #include <windows.h>
16 #else
17   #include <unistd.h>
18 #endif
19 #if defined(__ANDROID__)
20   #include <android/log.h>
21 #endif
22 
23 #ifndef XNN_LOG_TO_STDIO
24   #if defined(__ANDROID__)
25     #define XNN_LOG_TO_STDIO 0
26   #else
27     #define XNN_LOG_TO_STDIO 1
28   #endif
29 #endif
30 
31 #include <xnnpack/log.h>
32 
33 
34 /* Messages up to this size are formatted entirely on-stack, and don't allocate heap memory */
35 #define XNN_LOG_STACK_BUFFER_SIZE 1024
36 
37 #ifdef _WIN32
38   #define XNN_LOG_NEWLINE_LENGTH 2
39 
40   #define XNN_LOG_STDERR STD_ERROR_HANDLE
41   #define XNN_LOG_STDOUT STD_OUTPUT_HANDLE
42 #else
43   #define XNN_LOG_NEWLINE_LENGTH 1
44 
45   #define XNN_LOG_STDERR STDERR_FILENO
46   #define XNN_LOG_STDOUT STDOUT_FILENO
47 #endif
48 
49 #if XNN_LOG_TO_STDIO
xnn_vlog(int output_handle,const char * prefix,size_t prefix_length,const char * format,va_list args)50 static void xnn_vlog(int output_handle, const char* prefix, size_t prefix_length, const char* format, va_list args) {
51   char stack_buffer[XNN_LOG_STACK_BUFFER_SIZE];
52   char* heap_buffer = NULL;
53   char* out_buffer = &stack_buffer[0];
54 
55   /* The first call to vsnprintf will clobber args, thus need a copy in case a second vsnprintf call is needed */
56   va_list args_copy;
57   va_copy(args_copy, args);
58 
59   memcpy(stack_buffer, prefix, prefix_length * sizeof(char));
60   assert((prefix_length + XNN_LOG_NEWLINE_LENGTH) * sizeof(char) <= XNN_LOG_STACK_BUFFER_SIZE);
61 
62   const int format_chars = vsnprintf(
63     &stack_buffer[prefix_length],
64     XNN_LOG_STACK_BUFFER_SIZE - (prefix_length + XNN_LOG_NEWLINE_LENGTH) * sizeof(char),
65     format,
66     args);
67   if (format_chars < 0) {
68     /* Format error in the message: silently ignore this particular message. */
69     goto cleanup;
70   }
71   const size_t format_length = (size_t) format_chars;
72   if ((prefix_length + format_length + XNN_LOG_NEWLINE_LENGTH) * sizeof(char) > XNN_LOG_STACK_BUFFER_SIZE) {
73     /* Allocate a buffer on heap, and vsnprintf to this buffer */
74     const size_t heap_buffer_size = (prefix_length + format_length + XNN_LOG_NEWLINE_LENGTH) * sizeof(char);
75     #if _WIN32
76       heap_buffer = HeapAlloc(GetProcessHeap(), 0, heap_buffer_size);
77     #else
78       heap_buffer = malloc(heap_buffer_size);
79     #endif
80     if (heap_buffer == NULL) {
81       goto cleanup;
82     }
83 
84     /* Copy pre-formatted prefix into the on-heap buffer */
85     memcpy(heap_buffer, prefix, prefix_length * sizeof(char));
86     vsnprintf(&heap_buffer[prefix_length], (format_length + XNN_LOG_NEWLINE_LENGTH) * sizeof(char), format, args_copy);
87     out_buffer = heap_buffer;
88   }
89   #ifdef _WIN32
90     out_buffer[prefix_length + format_length] = '\r';
91     out_buffer[prefix_length + format_length + 1] = '\n';
92 
93     DWORD bytes_written;
94     WriteFile(
95       GetStdHandle((DWORD) output_handle),
96       out_buffer, (prefix_length + format_length + XNN_LOG_NEWLINE_LENGTH) * sizeof(char),
97       &bytes_written, NULL);
98   #else
99     out_buffer[prefix_length + format_length] = '\n';
100 
101     ssize_t bytes_written = write(output_handle, out_buffer, (prefix_length + format_length + XNN_LOG_NEWLINE_LENGTH) * sizeof(char));
102     (void) bytes_written;
103   #endif
104 
105 cleanup:
106   #ifdef _WIN32
107     HeapFree(GetProcessHeap(), 0, heap_buffer);
108   #else
109     free(heap_buffer);
110   #endif
111   va_end(args_copy);
112 }
113 #elif defined(__ANDROID__)
114   static const char xnnpack_module[] = "XNNPACK";
115 #endif
116 
117 #if XNN_LOG_LEVEL >= XNN_LOG_DEBUG
xnn_vlog_debug(const char * format,va_list args)118   void xnn_vlog_debug(const char* format, va_list args) {
119     #if XNN_LOG_TO_STDIO
120       static const char debug_prefix[17] = {
121         'D', 'e', 'b', 'u', 'g', ' ', '(', 'X', 'N', 'N', 'P', 'A', 'C', 'K', ')', ':', ' '
122       };
123       xnn_vlog(XNN_LOG_STDOUT, debug_prefix, 17, format, args);
124     #elif defined(__ANDROID__)
125       __android_log_vprint(ANDROID_LOG_DEBUG, xnnpack_module, format, args);
126     #else
127       #error "Platform-specific implementation required"
128     #endif
129   }
130 #endif
131 
132 #if XNN_LOG_LEVEL >= XNN_LOG_INFO
xnn_vlog_info(const char * format,va_list args)133   void xnn_vlog_info(const char* format, va_list args) {
134     #if XNN_LOG_TO_STDIO
135       static const char info_prefix[16] = {
136         'N', 'o', 't', 'e', ' ', '(', 'X', 'N', 'N', 'P', 'A', 'C', 'K', ')', ':', ' '
137       };
138       xnn_vlog(XNN_LOG_STDOUT, info_prefix, 16, format, args);
139     #elif defined(__ANDROID__)
140       __android_log_vprint(ANDROID_LOG_INFO, xnnpack_module, format, args);
141     #else
142       #error "Platform-specific implementation required"
143     #endif
144   }
145 #endif
146 
147 #if XNN_LOG_LEVEL >= XNN_LOG_WARNING
xnn_vlog_warning(const char * format,va_list args)148   void xnn_vlog_warning(const char* format, va_list args) {
149     #if XNN_LOG_TO_STDIO
150       static const char warning_prefix[20] = {
151         'W', 'a', 'r', 'n', 'i', 'n', 'g', ' ', 'i', 'n', ' ', 'X', 'N', 'N', 'P', 'A', 'C', 'K', ':', ' '
152       };
153       xnn_vlog(XNN_LOG_STDERR, warning_prefix, 20, format, args);
154     #elif defined(__ANDROID__)
155       __android_log_vprint(ANDROID_LOG_WARN, xnnpack_module, format, args);
156     #else
157       #error "Platform-specific implementation required"
158     #endif
159   }
160 #endif
161 
162 #if XNN_LOG_LEVEL >= XNN_LOG_ERROR
xnn_vlog_error(const char * format,va_list args)163   void xnn_vlog_error(const char* format, va_list args) {
164     #if XNN_LOG_TO_STDIO
165       static const char error_prefix[18] = {
166         'E', 'r', 'r', 'o', 'r', ' ', 'i', 'n', ' ', 'X', 'N', 'N', 'P', 'A', 'C', 'K', ':', ' '
167       };
168       xnn_vlog(XNN_LOG_STDERR, error_prefix, 18, format, args);
169     #elif defined(__ANDROID__)
170       __android_log_vprint(ANDROID_LOG_ERROR, xnnpack_module, format, args);
171     #else
172       #error "Platform-specific implementation required"
173     #endif
174   }
175 #endif
176 
177 #if XNN_LOG_LEVEL >= XNN_LOG_FATAL
xnn_vlog_fatal(const char * format,va_list args)178   void xnn_vlog_fatal(const char* format, va_list args) {
179     #if XNN_LOG_TO_STDIO
180       static const char fatal_prefix[24] = {
181         'F', 'a', 't', 'a', 'l', ' ', 'e', 'r', 'r', 'o', 'r', ' ', 'i', 'n', ' ', 'X', 'N', 'N', 'P', 'A', 'C', 'K', ':', ' '
182       };
183       xnn_vlog(XNN_LOG_STDERR, fatal_prefix, 24, format, args);
184     #elif defined(__ANDROID__)
185       __android_log_vprint(ANDROID_LOG_FATAL, xnnpack_module, format, args);
186     #else
187       #error "Platform-specific implementation required"
188     #endif
189   }
190 #endif
191