• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include <assert.h>
2 #include <stdarg.h>
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <string.h>
6 #ifdef _WIN32
7 #include <windows.h>
8 #else
9 #include <unistd.h>
10 #endif
11 #if defined(__ANDROID__)
12 #include <android/log.h>
13 #endif
14 #if defined(__hexagon__)
15 #include <qurt_printf.h>
16 #endif
17 
18 #ifndef CPUINFO_LOG_TO_STDIO
19 #if defined(__ANDROID__)
20 #define CPUINFO_LOG_TO_STDIO 0
21 #else
22 #define CPUINFO_LOG_TO_STDIO 1
23 #endif
24 #endif
25 
26 #include <cpuinfo/log.h>
27 
28 /* Messages up to this size are formatted entirely on-stack, and don't allocate
29  * heap memory */
30 #define CPUINFO_LOG_STACK_BUFFER_SIZE 1024
31 
32 #ifdef _WIN32
33 #define CPUINFO_LOG_NEWLINE_LENGTH 2
34 
35 #define CPUINFO_LOG_STDERR STD_ERROR_HANDLE
36 #define CPUINFO_LOG_STDOUT STD_OUTPUT_HANDLE
37 #elif defined(__hexagon__)
38 #define CPUINFO_LOG_NEWLINE_LENGTH 1
39 
40 #define CPUINFO_LOG_STDERR 0
41 #define CPUINFO_LOG_STDOUT 0
42 #else
43 #define CPUINFO_LOG_NEWLINE_LENGTH 1
44 
45 #define CPUINFO_LOG_STDERR STDERR_FILENO
46 #define CPUINFO_LOG_STDOUT STDOUT_FILENO
47 #endif
48 
49 #if CPUINFO_LOG_TO_STDIO
cpuinfo_vlog(int output_handle,const char * prefix,size_t prefix_length,const char * format,va_list args)50 static void cpuinfo_vlog(
51 	int output_handle,
52 	const char* prefix,
53 	size_t prefix_length,
54 	const char* format,
55 	va_list args) {
56 	char stack_buffer[CPUINFO_LOG_STACK_BUFFER_SIZE];
57 	char* heap_buffer = NULL;
58 	char* out_buffer = &stack_buffer[0];
59 
60 	/* The first call to vsnprintf will clobber args, thus need a copy in
61 	 * case a second vsnprintf call is needed */
62 	va_list args_copy;
63 	va_copy(args_copy, args);
64 
65 	memcpy(stack_buffer, prefix, prefix_length * sizeof(char));
66 	assert((prefix_length + CPUINFO_LOG_NEWLINE_LENGTH) * sizeof(char) <= CPUINFO_LOG_STACK_BUFFER_SIZE);
67 
68 	const int format_chars = vsnprintf(
69 		&stack_buffer[prefix_length],
70 		CPUINFO_LOG_STACK_BUFFER_SIZE - (prefix_length + CPUINFO_LOG_NEWLINE_LENGTH) * sizeof(char),
71 		format,
72 		args);
73 	if (format_chars < 0) {
74 		/* Format error in the message: silently ignore this particular
75 		 * message. */
76 		goto cleanup;
77 	}
78 	const size_t format_length = (size_t)format_chars;
79 	if ((prefix_length + format_length + CPUINFO_LOG_NEWLINE_LENGTH) * sizeof(char) >
80 	    CPUINFO_LOG_STACK_BUFFER_SIZE) {
81 		/* Allocate a buffer on heap, and vsnprintf to this buffer */
82 		const size_t heap_buffer_size =
83 			(prefix_length + format_length + CPUINFO_LOG_NEWLINE_LENGTH) * sizeof(char);
84 #if _WIN32
85 		heap_buffer = HeapAlloc(GetProcessHeap(), 0, heap_buffer_size);
86 #else
87 		heap_buffer = malloc(heap_buffer_size);
88 #endif
89 		if (heap_buffer == NULL) {
90 			goto cleanup;
91 		}
92 
93 		/* Copy pre-formatted prefix into the on-heap buffer */
94 		memcpy(heap_buffer, prefix, prefix_length * sizeof(char));
95 		vsnprintf(
96 			&heap_buffer[prefix_length],
97 			(format_length + CPUINFO_LOG_NEWLINE_LENGTH) * sizeof(char),
98 			format,
99 			args_copy);
100 		out_buffer = heap_buffer;
101 	}
102 #ifdef _WIN32
103 	out_buffer[prefix_length + format_length] = '\r';
104 	out_buffer[prefix_length + format_length + 1] = '\n';
105 
106 	DWORD bytes_written;
107 	WriteFile(
108 		GetStdHandle((DWORD)output_handle),
109 		out_buffer,
110 		(prefix_length + format_length + CPUINFO_LOG_NEWLINE_LENGTH) * sizeof(char),
111 		&bytes_written,
112 		NULL);
113 #elif defined(__hexagon__)
114 	qurt_printf("%s", out_buffer);
115 #else
116 	out_buffer[prefix_length + format_length] = '\n';
117 
118 	ssize_t bytes_written = write(
119 		output_handle, out_buffer, (prefix_length + format_length + CPUINFO_LOG_NEWLINE_LENGTH) * sizeof(char));
120 	(void)bytes_written;
121 #endif
122 
123 cleanup:
124 #ifdef _WIN32
125 	HeapFree(GetProcessHeap(), 0, heap_buffer);
126 #else
127 	free(heap_buffer);
128 #endif
129 	va_end(args_copy);
130 }
131 #elif defined(__ANDROID__) && CPUINFO_LOG_LEVEL > CPUINFO_LOG_NONE
132 static const char cpuinfo_module[] = "XNNPACK";
133 #endif
134 
135 #if CPUINFO_LOG_LEVEL >= CPUINFO_LOG_DEBUG
cpuinfo_vlog_debug(const char * format,va_list args)136 void cpuinfo_vlog_debug(const char* format, va_list args) {
137 #if CPUINFO_LOG_TO_STDIO
138 	static const char debug_prefix[17] = {
139 		'D', 'e', 'b', 'u', 'g', ' ', '(', 'c', 'p', 'u', 'i', 'n', 'f', 'o', ')', ':', ' '};
140 	cpuinfo_vlog(CPUINFO_LOG_STDOUT, debug_prefix, 17, format, args);
141 #elif defined(__ANDROID__)
142 	__android_log_vprint(ANDROID_LOG_DEBUG, cpuinfo_module, format, args);
143 #else
144 #error "Platform-specific implementation required"
145 #endif
146 }
147 #endif
148 
149 #if CPUINFO_LOG_LEVEL >= CPUINFO_LOG_INFO
cpuinfo_vlog_info(const char * format,va_list args)150 void cpuinfo_vlog_info(const char* format, va_list args) {
151 #if CPUINFO_LOG_TO_STDIO
152 	static const char info_prefix[16] = {
153 		'N', 'o', 't', 'e', ' ', '(', 'c', 'p', 'u', 'i', 'n', 'f', 'o', ')', ':', ' '};
154 	cpuinfo_vlog(CPUINFO_LOG_STDOUT, info_prefix, 16, format, args);
155 #elif defined(__ANDROID__)
156 	__android_log_vprint(ANDROID_LOG_INFO, cpuinfo_module, format, args);
157 #else
158 #error "Platform-specific implementation required"
159 #endif
160 }
161 #endif
162 
163 #if CPUINFO_LOG_LEVEL >= CPUINFO_LOG_WARNING
cpuinfo_vlog_warning(const char * format,va_list args)164 void cpuinfo_vlog_warning(const char* format, va_list args) {
165 #if CPUINFO_LOG_TO_STDIO
166 	static const char warning_prefix[20] = {'W', 'a', 'r', 'n', 'i', 'n', 'g', ' ', 'i', 'n',
167 						' ', 'c', 'p', 'u', 'i', 'n', 'f', 'o', ':', ' '};
168 	cpuinfo_vlog(CPUINFO_LOG_STDERR, warning_prefix, 20, format, args);
169 #elif defined(__ANDROID__)
170 	__android_log_vprint(ANDROID_LOG_WARN, cpuinfo_module, format, args);
171 #else
172 #error "Platform-specific implementation required"
173 #endif
174 }
175 #endif
176 
177 #if CPUINFO_LOG_LEVEL >= CPUINFO_LOG_ERROR
cpuinfo_vlog_error(const char * format,va_list args)178 void cpuinfo_vlog_error(const char* format, va_list args) {
179 #if CPUINFO_LOG_TO_STDIO
180 	static const char error_prefix[18] = {
181 		'E', 'r', 'r', 'o', 'r', ' ', 'i', 'n', ' ', 'c', 'p', 'u', 'i', 'n', 'f', 'o', ':', ' '};
182 	cpuinfo_vlog(CPUINFO_LOG_STDERR, error_prefix, 18, format, args);
183 #elif defined(__ANDROID__)
184 	__android_log_vprint(ANDROID_LOG_ERROR, cpuinfo_module, format, args);
185 #else
186 #error "Platform-specific implementation required"
187 #endif
188 }
189 #endif
190 
191 #if CPUINFO_LOG_LEVEL >= CPUINFO_LOG_FATAL
cpuinfo_vlog_fatal(const char * format,va_list args)192 void cpuinfo_vlog_fatal(const char* format, va_list args) {
193 #if CPUINFO_LOG_TO_STDIO
194 	static const char fatal_prefix[24] = {'F', 'a', 't', 'a', 'l', ' ', 'e', 'r', 'r', 'o', 'r', ' ',
195 					      'i', 'n', ' ', 'c', 'p', 'u', 'i', 'n', 'f', 'o', ':', ' '};
196 	cpuinfo_vlog(CPUINFO_LOG_STDERR, fatal_prefix, 24, format, args);
197 #elif defined(__ANDROID__)
198 	__android_log_vprint(ANDROID_LOG_FATAL, cpuinfo_module, format, args);
199 #else
200 #error "Platform-specific implementation required"
201 #endif
202 }
203 #endif
204