17ec681f3Smrg/*
27ec681f3Smrg * Copyright 2019 Google LLC
37ec681f3Smrg * SPDX-License-Identifier: MIT
47ec681f3Smrg *
57ec681f3Smrg * based in part on anv and radv which are:
67ec681f3Smrg * Copyright © 2015 Intel Corporation
77ec681f3Smrg * Copyright © 2016 Red Hat.
87ec681f3Smrg * Copyright © 2016 Bas Nieuwenhuizen
97ec681f3Smrg */
107ec681f3Smrg
117ec681f3Smrg#include "vn_common.h"
127ec681f3Smrg
137ec681f3Smrg#include <stdarg.h>
147ec681f3Smrg
157ec681f3Smrg#include "util/debug.h"
167ec681f3Smrg#include "util/log.h"
177ec681f3Smrg#include "util/os_misc.h"
187ec681f3Smrg#include "vk_enum_to_str.h"
197ec681f3Smrg
207ec681f3Smrgstatic const struct debug_control vn_debug_options[] = {
217ec681f3Smrg   { "init", VN_DEBUG_INIT },
227ec681f3Smrg   { "result", VN_DEBUG_RESULT },
237ec681f3Smrg   { "vtest", VN_DEBUG_VTEST },
247ec681f3Smrg   { "wsi", VN_DEBUG_WSI },
257ec681f3Smrg   { NULL, 0 },
267ec681f3Smrg};
277ec681f3Smrg
287ec681f3Smrguint64_t vn_debug;
297ec681f3Smrg
307ec681f3Smrgstatic void
317ec681f3Smrgvn_debug_init_once(void)
327ec681f3Smrg{
337ec681f3Smrg   vn_debug = parse_debug_string(os_get_option("VN_DEBUG"), vn_debug_options);
347ec681f3Smrg}
357ec681f3Smrg
367ec681f3Smrgvoid
377ec681f3Smrgvn_debug_init(void)
387ec681f3Smrg{
397ec681f3Smrg   static once_flag once = ONCE_FLAG_INIT;
407ec681f3Smrg   call_once(&once, vn_debug_init_once);
417ec681f3Smrg}
427ec681f3Smrg
437ec681f3Smrgvoid
447ec681f3Smrgvn_trace_init(void)
457ec681f3Smrg{
467ec681f3Smrg#ifdef ANDROID
477ec681f3Smrg   atrace_init();
487ec681f3Smrg#endif
497ec681f3Smrg}
507ec681f3Smrg
517ec681f3Smrgvoid
527ec681f3Smrgvn_log(struct vn_instance *instance, const char *format, ...)
537ec681f3Smrg{
547ec681f3Smrg   va_list ap;
557ec681f3Smrg
567ec681f3Smrg   va_start(ap, format);
577ec681f3Smrg   mesa_log_v(MESA_LOG_DEBUG, "MESA-VIRTIO", format, ap);
587ec681f3Smrg   va_end(ap);
597ec681f3Smrg
607ec681f3Smrg   /* instance may be NULL or partially initialized */
617ec681f3Smrg}
627ec681f3Smrg
637ec681f3SmrgVkResult
647ec681f3Smrgvn_log_result(struct vn_instance *instance,
657ec681f3Smrg              VkResult result,
667ec681f3Smrg              const char *where)
677ec681f3Smrg{
687ec681f3Smrg   vn_log(instance, "%s: %s", where, vk_Result_to_str(result));
697ec681f3Smrg   return result;
707ec681f3Smrg}
717ec681f3Smrg
727ec681f3Smrgvoid
737ec681f3Smrgvn_relax(uint32_t *iter, const char *reason)
747ec681f3Smrg{
757ec681f3Smrg   /* Yield for the first 2^busy_wait_order times and then sleep for
767ec681f3Smrg    * base_sleep_us microseconds for the same number of times.  After that,
777ec681f3Smrg    * keep doubling both sleep length and count.
787ec681f3Smrg    */
797ec681f3Smrg   const uint32_t busy_wait_order = 4;
807ec681f3Smrg   const uint32_t base_sleep_us = 10;
817ec681f3Smrg   const uint32_t warn_order = 12;
827ec681f3Smrg
837ec681f3Smrg   (*iter)++;
847ec681f3Smrg   if (*iter < (1 << busy_wait_order)) {
857ec681f3Smrg      thrd_yield();
867ec681f3Smrg      return;
877ec681f3Smrg   }
887ec681f3Smrg
897ec681f3Smrg   /* warn occasionally if we have slept at least 1.28ms for 2048 times (plus
907ec681f3Smrg    * another 2047 shorter sleeps)
917ec681f3Smrg    */
927ec681f3Smrg   if (unlikely(*iter % (1 << warn_order) == 0))
937ec681f3Smrg      vn_log(NULL, "stuck in %s wait with iter at %d", reason, *iter);
947ec681f3Smrg
957ec681f3Smrg   const uint32_t shift = util_last_bit(*iter) - busy_wait_order - 1;
967ec681f3Smrg   os_time_sleep(base_sleep_us << shift);
977ec681f3Smrg}
98