1/*
2 * Copyright 2019 Google LLC
3 * SPDX-License-Identifier: MIT
4 *
5 * based in part on anv and radv which are:
6 * Copyright © 2015 Intel Corporation
7 * Copyright © 2016 Red Hat.
8 * Copyright © 2016 Bas Nieuwenhuizen
9 */
10
11#include "vn_common.h"
12
13#include <stdarg.h>
14
15#include "util/debug.h"
16#include "util/log.h"
17#include "util/os_misc.h"
18#include "util/u_debug.h"
19#include "venus-protocol/vn_protocol_driver_info.h"
20#include "vk_enum_to_str.h"
21
22#define VN_RELAX_MIN_BASE_SLEEP_US (10)
23
24static const struct debug_control vn_debug_options[] = {
25   { "init", VN_DEBUG_INIT },
26   { "result", VN_DEBUG_RESULT },
27   { "vtest", VN_DEBUG_VTEST },
28   { "wsi", VN_DEBUG_WSI },
29   { "no_abort", VN_DEBUG_NO_ABORT },
30   { NULL, 0 },
31};
32
33static const struct debug_control vn_perf_options[] = {
34   { "no_async_set_alloc", VN_PERF_NO_ASYNC_SET_ALLOC },
35   { "no_async_buffer_create", VN_PERF_NO_ASYNC_BUFFER_CREATE },
36   { "no_async_queue_submit", VN_PERF_NO_ASYNC_QUEUE_SUBMIT },
37   { "no_event_feedback", VN_PERF_NO_EVENT_FEEDBACK },
38   { "no_fence_feedback", VN_PERF_NO_FENCE_FEEDBACK },
39   { NULL, 0 },
40};
41
42struct vn_env vn_env;
43
44static void
45vn_env_init_once(void)
46{
47   vn_env.debug =
48      parse_debug_string(os_get_option("VN_DEBUG"), vn_debug_options);
49   vn_env.perf =
50      parse_debug_string(os_get_option("VN_PERF"), vn_perf_options);
51   vn_env.draw_cmd_batch_limit =
52      debug_get_num_option("VN_DRAW_CMD_BATCH_LIMIT", UINT32_MAX);
53   if (!vn_env.draw_cmd_batch_limit)
54      vn_env.draw_cmd_batch_limit = UINT32_MAX;
55   vn_env.relax_base_sleep_us = debug_get_num_option(
56      "VN_RELAX_BASE_SLEEP_US", VN_RELAX_MIN_BASE_SLEEP_US);
57   vn_env.relax_base_sleep_us =
58      MAX2(vn_env.relax_base_sleep_us, VN_RELAX_MIN_BASE_SLEEP_US);
59}
60
61void
62vn_env_init(void)
63{
64   static once_flag once = ONCE_FLAG_INIT;
65   call_once(&once, vn_env_init_once);
66
67   /* log per VkInstance creation */
68   if (VN_DEBUG(INIT)) {
69      vn_log(NULL,
70             "vn_env is as below:"
71             "\n\tdebug = 0x%" PRIx64 ""
72             "\n\tperf = 0x%" PRIx64 ""
73             "\n\tdraw_cmd_batch_limit = %u"
74             "\n\trelax_base_sleep_us = %u",
75             vn_env.debug, vn_env.perf, vn_env.draw_cmd_batch_limit,
76             vn_env.relax_base_sleep_us);
77   }
78}
79
80void
81vn_trace_init(void)
82{
83#ifdef ANDROID
84   atrace_init();
85#endif
86}
87
88void
89vn_log(struct vn_instance *instance, const char *format, ...)
90{
91   va_list ap;
92
93   va_start(ap, format);
94   mesa_log_v(MESA_LOG_DEBUG, "MESA-VIRTIO", format, ap);
95   va_end(ap);
96
97   /* instance may be NULL or partially initialized */
98}
99
100VkResult
101vn_log_result(struct vn_instance *instance,
102              VkResult result,
103              const char *where)
104{
105   vn_log(instance, "%s: %s", where, vk_Result_to_str(result));
106   return result;
107}
108
109uint32_t
110vn_extension_get_spec_version(const char *name)
111{
112   const int32_t index = vn_info_extension_index(name);
113   return index >= 0 ? vn_info_extension_get(index)->spec_version : 0;
114}
115
116void
117vn_relax(uint32_t *iter, const char *reason)
118{
119   /* Yield for the first 2^busy_wait_order times and then sleep for
120    * base_sleep_us microseconds for the same number of times.  After that,
121    * keep doubling both sleep length and count.
122    */
123   const uint32_t busy_wait_order = 4;
124   const uint32_t base_sleep_us = vn_env.relax_base_sleep_us;
125   const uint32_t warn_order = 12;
126   const uint32_t abort_order = 14;
127
128   (*iter)++;
129   if (*iter < (1 << busy_wait_order)) {
130      thrd_yield();
131      return;
132   }
133
134   /* warn occasionally if we have slept at least 1.28ms for 2048 times (plus
135    * another 2047 shorter sleeps)
136    */
137   if (unlikely(*iter % (1 << warn_order) == 0)) {
138      vn_log(NULL, "stuck in %s wait with iter at %d", reason, *iter);
139
140      if (*iter >= (1 << abort_order) && !VN_DEBUG(NO_ABORT)) {
141         vn_log(NULL, "aborting");
142         abort();
143      }
144   }
145
146   const uint32_t shift = util_last_bit(*iter) - busy_wait_order - 1;
147   os_time_sleep(base_sleep_us << shift);
148}
149