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/u_pointer.h"
38 
39 #include <stdarg.h>
40 #include <stdio.h>
41 
42 #ifdef HAVE_CONFIG_H
43 #include "config.h"
44 #endif
45 
46 #if ENABLE_TRACING == TRACE_WITH_PERFETTO
47 #include <vperfetto-min.h>
48 #endif
49 
50 #if ENABLE_TRACING == TRACE_WITH_STDERR
51 #include <stdio.h>
52 #endif
53 
hash_func_u32(void * key)54 unsigned hash_func_u32(void *key)
55 {
56    intptr_t ip = pointer_to_intptr(key);
57    return (unsigned)(ip & 0xffffffff);
58 }
59 
compare_func(void * key1,void * key2)60 int compare_func(void *key1, void *key2)
61 {
62    if (key1 < key2)
63       return -1;
64    if (key1 > key2)
65       return 1;
66    else
67       return 0;
68 }
69 
has_eventfd(void)70 bool has_eventfd(void)
71 {
72 #ifdef HAVE_EVENTFD_H
73    return true;
74 #else
75    return false;
76 #endif
77 }
78 
create_eventfd(unsigned int initval)79 int create_eventfd(unsigned int initval)
80 {
81 #ifdef HAVE_EVENTFD_H
82    return eventfd(initval, EFD_CLOEXEC | EFD_NONBLOCK);
83 #else
84    return -1;
85 #endif
86 }
87 
write_eventfd(int fd,uint64_t val)88 int write_eventfd(int fd, uint64_t val)
89 {
90    const char *buf = (const char *)&val;
91    size_t count = sizeof(val);
92    ssize_t ret = 0;
93 
94    while (count) {
95       ret = write(fd, buf, count);
96       if (ret < 0) {
97          if (errno == EINTR)
98             continue;
99          break;
100       }
101       count -= ret;
102       buf += ret;
103    }
104 
105    return count ? -1 : 0;
106 }
107 
flush_eventfd(int fd)108 void flush_eventfd(int fd)
109 {
110     ssize_t len;
111     uint64_t value;
112     do {
113        len = read(fd, &value, sizeof(value));
114     } while ((len == -1 && errno == EINTR) || len == sizeof(value));
115 }
116 
117 #if ENABLE_TRACING == TRACE_WITH_PERCETTO
PERCETTO_CATEGORY_DEFINE(VIRGL_PERCETTO_CATEGORIES)118 PERCETTO_CATEGORY_DEFINE(VIRGL_PERCETTO_CATEGORIES)
119 
120 void trace_init(void)
121 {
122   PERCETTO_INIT(PERCETTO_CLOCK_DONT_CARE);
123 }
124 #endif
125 
126 #if ENABLE_TRACING == TRACE_WITH_PERFETTO
trace_init(void)127 void trace_init(void)
128 {
129    struct vperfetto_min_config config = {
130       .init_flags = VPERFETTO_INIT_FLAG_USE_SYSTEM_BACKEND,
131             .filename = NULL,
132             .shmem_size_hint_kb = 32 * 1024,
133    };
134 
135    vperfetto_min_startTracing(&config);
136 }
137 
trace_begin(const char * scope)138 const char *trace_begin(const char *scope)
139 {
140    vperfetto_min_beginTrackEvent_VMM(scope);
141    return scope;
142 }
143 
trace_end(const char ** dummy)144 void trace_end(const char **dummy)
145 {
146    (void)dummy;
147    vperfetto_min_endTrackEvent_VMM();
148 }
149 #endif
150 
151 #if ENABLE_TRACING == TRACE_WITH_STDERR
152 static int nesting_depth = 0;
trace_init(void)153 void trace_init(void)
154 {
155 }
156 
trace_begin(const char * scope)157 const char *trace_begin(const char *scope)
158 {
159    for (int i = 0; i < nesting_depth; ++i)
160       fprintf(stderr, "  ");
161 
162    fprintf(stderr, "ENTER:%s\n", scope);
163    nesting_depth++;
164 
165    return scope;
166 }
167 
trace_end(const char ** func_name)168 void trace_end(const char **func_name)
169 {
170    --nesting_depth;
171    for (int i = 0; i < nesting_depth; ++i)
172       fprintf(stderr, "  ");
173    fprintf(stderr, "LEAVE %s\n", *func_name);
174 }
175 #endif
176