• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**************************************************************************
2  *
3  * Copyright (C) 2019 Chromium.
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a
6  * copy of this software and associated documentation files (the "Software"),
7  * to deal in the Software without restriction, including without limitation
8  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9  * and/or sell copies of the Software, and to permit persons to whom the
10  * Software is furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be included
13  * in all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
16  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
19  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
20  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
21  * OTHER DEALINGS IN THE SOFTWARE.
22  *
23     **************************************************************************/
24 
25 #ifdef HAVE_CONFIG_H
26 #include "config.h"
27 #endif
28 
29 #include "virgl_util.h"
30 
31 #include <errno.h>
32 #ifdef HAVE_EVENTFD_H
33 #include <sys/eventfd.h>
34 #endif
35 #include <unistd.h>
36 
37 #include "util/os_misc.h"
38 #include "util/u_pointer.h"
39 
40 #include <assert.h>
41 #include <stdarg.h>
42 #include <stdio.h>
43 
44 #ifdef HAVE_CONFIG_H
45 #include "config.h"
46 #endif
47 
48 #if ENABLE_TRACING == TRACE_WITH_PERFETTO
49 #include <vperfetto-min.h>
50 #endif
51 
52 #if ENABLE_TRACING == TRACE_WITH_STDERR
53 #include <stdio.h>
54 #endif
55 
hash_func_u32(const void * key)56 uint32_t hash_func_u32(const void *key)
57 {
58    intptr_t ip = pointer_to_intptr(key);
59    return (uint32_t)(ip & 0xffffffff);
60 }
61 
equal_func(const void * key1,const void * key2)62 bool equal_func(const void *key1, const void *key2)
63 {
64    return key1 == key2;
65 }
66 
has_eventfd(void)67 bool has_eventfd(void)
68 {
69 #ifdef HAVE_EVENTFD_H
70    return true;
71 #else
72    return false;
73 #endif
74 }
75 
create_eventfd(unsigned int initval)76 int create_eventfd(unsigned int initval)
77 {
78 #ifdef HAVE_EVENTFD_H
79    return eventfd(initval, EFD_CLOEXEC | EFD_NONBLOCK);
80 #else
81    (void)initval;
82    return -1;
83 #endif
84 }
85 
write_eventfd(int fd,uint64_t val)86 int write_eventfd(int fd, uint64_t val)
87 {
88    const char *buf = (const char *)&val;
89    size_t count = sizeof(val);
90    ssize_t ret = 0;
91 
92    while (count) {
93       ret = write(fd, buf, count);
94       if (ret < 0) {
95          if (errno == EINTR)
96             continue;
97          break;
98       }
99       count -= ret;
100       buf += ret;
101    }
102 
103    return count ? -1 : 0;
104 }
105 
flush_eventfd(int fd)106 void flush_eventfd(int fd)
107 {
108     ssize_t len;
109     uint64_t value;
110     do {
111        len = read(fd, &value, sizeof(value));
112     } while ((len == -1 && errno == EINTR) || len == sizeof(value));
113 }
114 
115 static
virgl_default_logger(const char * fmt,va_list va)116 void virgl_default_logger(const char *fmt, va_list va)
117 {
118    static FILE* fp = NULL;
119    if (NULL == fp) {
120       const char* log = getenv("VIRGL_LOG_FILE");
121       if (log) {
122          char *log_prefix = strdup(log);
123          char *log_suffix = strstr(log_prefix, "%PID%");
124          if (log_suffix) {
125             *log_suffix = 0;
126             log_suffix += 5;
127             int len = strlen(log) + 32;
128             char *name = malloc(len);
129             snprintf(name, len, "%s%d%s", log_prefix, getpid(), log_suffix);
130             fp = fopen(name, "a");
131             free(name);
132          } else {
133             fp = fopen(log, "a");
134          }
135          free(log_prefix);
136          if (NULL == fp) {
137             fprintf(stderr, "Can't open %s\n", log);
138             fp = stderr;
139          }
140       } else {
141             fp = stderr;
142       }
143    }
144    vfprintf(fp, fmt, va);
145    fflush(fp);
146 }
147 
148 static
virgl_null_logger(UNUSED const char * fmt,UNUSED va_list va)149 void virgl_null_logger(UNUSED const char *fmt, UNUSED va_list va)
150 {
151 }
152 
153 static virgl_debug_callback_type virgl_logger = virgl_default_logger;
154 
virgl_log_set_logger(virgl_debug_callback_type logger)155 virgl_debug_callback_type virgl_log_set_logger(virgl_debug_callback_type logger)
156 {
157    virgl_debug_callback_type old = virgl_logger;
158 
159    /* virgl_null_logger is internal */
160    if (old == virgl_null_logger)
161       old = NULL;
162    if (!logger)
163       logger = virgl_null_logger;
164 
165    virgl_logger = logger;
166    return old;
167 }
168 
virgl_logv(const char * fmt,va_list va)169 void virgl_logv(const char *fmt, va_list va)
170 {
171    assert(virgl_logger);
172    virgl_logger(fmt, va);
173 }
174 
175 #if ENABLE_TRACING == TRACE_WITH_PERCETTO
PERCETTO_CATEGORY_DEFINE(VIRGL_PERCETTO_CATEGORIES)176 PERCETTO_CATEGORY_DEFINE(VIRGL_PERCETTO_CATEGORIES)
177 
178 void trace_init(void)
179 {
180   PERCETTO_INIT(PERCETTO_CLOCK_DONT_CARE);
181 }
182 #endif
183 
184 #if ENABLE_TRACING == TRACE_WITH_PERFETTO
on_tracing_state_change(bool enabled)185 static void on_tracing_state_change(bool enabled) {
186     virgl_log("%s: tracing state change: %d\n", __func__, enabled);
187 }
188 
trace_init(void)189 void trace_init(void)
190 {
191    struct vperfetto_min_config config = {
192       .on_tracing_state_change = on_tracing_state_change,
193       .init_flags = VPERFETTO_INIT_FLAG_USE_SYSTEM_BACKEND,
194             .filename = NULL,
195             .shmem_size_hint_kb = 32 * 1024,
196    };
197 
198    vperfetto_min_startTracing(&config);
199 }
200 
trace_begin(const char * scope)201 const char *trace_begin(const char *scope)
202 {
203    vperfetto_min_beginTrackEvent_VMM(scope);
204    return scope;
205 }
206 
trace_end(const char ** dummy)207 void trace_end(const char **dummy)
208 {
209    (void)dummy;
210    vperfetto_min_endTrackEvent_VMM();
211 }
212 #endif
213 
214 #if ENABLE_TRACING == TRACE_WITH_STDERR
215 static int nesting_depth = 0;
trace_init(void)216 void trace_init(void)
217 {
218 }
219 
trace_begin(const char * scope)220 const char *trace_begin(const char *scope)
221 {
222    for (int i = 0; i < nesting_depth; ++i)
223       fprintf(stderr, "  ");
224 
225    fprintf(stderr, "ENTER:%s\n", scope);
226    nesting_depth++;
227 
228    return scope;
229 }
230 
trace_end(const char ** func_name)231 void trace_end(const char **func_name)
232 {
233    --nesting_depth;
234    for (int i = 0; i < nesting_depth; ++i)
235       fprintf(stderr, "  ");
236    fprintf(stderr, "LEAVE %s\n", *func_name);
237 }
238 #endif
239