• 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 "os/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(void * key)56 unsigned hash_func_u32(void *key)
57 {
58    intptr_t ip = pointer_to_intptr(key);
59    return (unsigned)(ip & 0xffffffff);
60 }
61 
compare_func(void * key1,void * key2)62 int compare_func(void *key1, void *key2)
63 {
64    if (key1 < key2)
65       return -1;
66    if (key1 > key2)
67       return 1;
68    else
69       return 0;
70 }
71 
has_eventfd(void)72 bool has_eventfd(void)
73 {
74 #ifdef HAVE_EVENTFD_H
75    return true;
76 #else
77    return false;
78 #endif
79 }
80 
create_eventfd(unsigned int initval)81 int create_eventfd(unsigned int initval)
82 {
83 #ifdef HAVE_EVENTFD_H
84    return eventfd(initval, EFD_CLOEXEC | EFD_NONBLOCK);
85 #else
86    (void)initval;
87    return -1;
88 #endif
89 }
90 
write_eventfd(int fd,uint64_t val)91 int write_eventfd(int fd, uint64_t val)
92 {
93    const char *buf = (const char *)&val;
94    size_t count = sizeof(val);
95    ssize_t ret = 0;
96 
97    while (count) {
98       ret = write(fd, buf, count);
99       if (ret < 0) {
100          if (errno == EINTR)
101             continue;
102          break;
103       }
104       count -= ret;
105       buf += ret;
106    }
107 
108    return count ? -1 : 0;
109 }
110 
flush_eventfd(int fd)111 void flush_eventfd(int fd)
112 {
113     ssize_t len;
114     uint64_t value;
115     do {
116        len = read(fd, &value, sizeof(value));
117     } while ((len == -1 && errno == EINTR) || len == sizeof(value));
118 }
119 
120 static
virgl_default_logger(const char * fmt,va_list va)121 void virgl_default_logger(const char *fmt, va_list va)
122 {
123    static FILE* fp = NULL;
124    if (NULL == fp) {
125       const char* log = getenv("VIRGL_LOG_FILE");
126       if (log) {
127          char *log_prefix = strdup(log);
128          char *log_suffix = strstr(log_prefix, "%PID%");
129          if (log_suffix) {
130             *log_suffix = 0;
131             log_suffix += 5;
132             int len = strlen(log) + 32;
133             char *name = malloc(len);
134             snprintf(name, len, "%s%d%s", log_prefix, getpid(), log_suffix);
135             fp = fopen(name, "a");
136             free(name);
137          } else {
138             fp = fopen(log, "a");
139          }
140          free(log_prefix);
141          if (NULL == fp) {
142             fprintf(stderr, "Can't open %s\n", log);
143             fp = stderr;
144          }
145       } else {
146             fp = stderr;
147       }
148    }
149    vfprintf(fp, fmt, va);
150    fflush(fp);
151 }
152 
153 static
virgl_null_logger(UNUSED const char * fmt,UNUSED va_list va)154 void virgl_null_logger(UNUSED const char *fmt, UNUSED va_list va)
155 {
156 }
157 
158 static virgl_debug_callback_type virgl_logger = virgl_default_logger;
159 
virgl_log_set_logger(virgl_debug_callback_type logger)160 virgl_debug_callback_type virgl_log_set_logger(virgl_debug_callback_type logger)
161 {
162    virgl_debug_callback_type old = virgl_logger;
163 
164    /* virgl_null_logger is internal */
165    if (old == virgl_null_logger)
166       old = NULL;
167    if (!logger)
168       logger = virgl_null_logger;
169 
170    virgl_logger = logger;
171    return old;
172 }
173 
virgl_logv(const char * fmt,va_list va)174 void virgl_logv(const char *fmt, va_list va)
175 {
176    assert(virgl_logger);
177    virgl_logger(fmt, va);
178 }
179 
180 #if ENABLE_TRACING == TRACE_WITH_PERCETTO
PERCETTO_CATEGORY_DEFINE(VIRGL_PERCETTO_CATEGORIES)181 PERCETTO_CATEGORY_DEFINE(VIRGL_PERCETTO_CATEGORIES)
182 
183 void trace_init(void)
184 {
185   PERCETTO_INIT(PERCETTO_CLOCK_DONT_CARE);
186 }
187 #endif
188 
189 #if ENABLE_TRACING == TRACE_WITH_PERFETTO
trace_init(void)190 void trace_init(void)
191 {
192    struct vperfetto_min_config config = {
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