<div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote">On Fri, Nov 4, 2016 at 8:58 AM, Eric Engestrom <span dir="ltr"><<a href="mailto:eric.engestrom@imgtec.com" target="_blank">eric.engestrom@imgtec.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div class="HOEnZb"><div class="h5">On Thursday, 2016-11-03 20:51:59 -0700, Jason Ekstrand wrote:<br>
> From: Kevin Strasser <<a href="mailto:kevin.strasser@intel.com">kevin.strasser@intel.com</a>><br>
><br>
> In order to support FIFO mode without blocking the application on calls<br>
> to vkQueuePresentKHR it is necessary to enqueue the request and defer<br>
> calling the server until the next vblank period. The xcb present api<br>
> doesn't offer a way to register a callback, so we will have to spawn a<br>
> worker thread that will wait for a request to be added to the queue, call<br>
> to the server, and then make the image available for reuse.  This commit<br>
> introduces the queue data structure needed to implement this.<br>
><br>
> Signed-off-by: Jason Ekstrand <<a href="mailto:jason@jlekstrand.net">jason@jlekstrand.net</a>><br>
> ---<br>
>  src/vulkan/wsi/Makefile.<wbr>sources   |   3 +-<br>
>  src/vulkan/wsi/wsi_common_<wbr>queue.h | 156 ++++++++++++++++++++++++++++++<wbr>++++++++<br>
>  2 files changed, 158 insertions(+), 1 deletion(-)<br>
>  create mode 100644 src/vulkan/wsi/wsi_common_<wbr>queue.h<br>
><br>
> diff --git a/src/vulkan/wsi/Makefile.<wbr>sources b/src/vulkan/wsi/Makefile.<wbr>sources<br>
> index 3139e6d..50660f9 100644<br>
> --- a/src/vulkan/wsi/Makefile.<wbr>sources<br>
> +++ b/src/vulkan/wsi/Makefile.<wbr>sources<br>
> @@ -1,6 +1,7 @@<br>
><br>
>  VULKAN_WSI_FILES := \<br>
> -     wsi_common.h<br>
> +     wsi_common.h \<br>
> +     wsi_common_queue.h<br>
><br>
>  VULKAN_WSI_WAYLAND_FILES := \<br>
>       wsi_common_wayland.c \<br>
> diff --git a/src/vulkan/wsi/wsi_common_<wbr>queue.h b/src/vulkan/wsi/wsi_common_<wbr>queue.h<br>
> new file mode 100644<br>
> index 0000000..ec2a925<br>
> --- /dev/null<br>
> +++ b/src/vulkan/wsi/wsi_common_<wbr>queue.h<br>
> @@ -0,0 +1,156 @@<br>
> +/*<br>
> + * Copyright © 2016 Intel Corporation<br>
> + *<br>
> + * Permission is hereby granted, free of charge, to any person obtaining a<br>
> + * copy of this software and associated documentation files (the "Software"),<br>
> + * to deal in the Software without restriction, including without limitation<br>
> + * the rights to use, copy, modify, merge, publish, distribute, sublicense,<br>
> + * and/or sell copies of the Software, and to permit persons to whom the<br>
> + * Software is furnished to do so, subject to the following conditions:<br>
> + *<br>
> + * The above copyright notice and this permission notice (including the next<br>
> + * paragraph) shall be included in all copies or substantial portions of the<br>
> + * Software.<br>
> + *<br>
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR<br>
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,<br>
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL<br>
> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER<br>
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING<br>
> + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS<br>
> + * IN THE SOFTWARE.<br>
> + */<br>
> +<br>
> +#ifndef VULKAN_WSI_COMMON_QUEUE_H<br>
> +#define VULKAN_WSI_COMMON_QUEUE_H<br>
> +<br>
> +#include <time.h><br>
> +#include <pthread.h><br>
> +#include "util/u_vector.h"<br>
> +<br>
> +struct wsi_queue {<br>
> +   struct u_vector vector;<br>
> +   pthread_mutex_t mutex;<br>
> +   pthread_cond_t cond;<br>
> +};<br>
> +<br>
> +static inline int<br>
> +wsi_queue_init(struct wsi_queue *queue, int length)<br>
> +{<br>
> +   int ret;<br>
> +<br>
> +   uint32_t length_pow2 = 4;<br>
> +   while (length_pow2 < length)<br>
> +      length_pow2 *= 2;<br>
> +<br>
> +   ret = u_vector_init(&queue->vector, sizeof(uint32_t),<br>
> +                       sizeof(uint32_t) * length_pow2);<br>
> +   if (!ret)<br>
> +      return -ENOMEM;<br>
<br>
</div></div>I thought pthread_* functions returned positive errors?<br>
I couldn't find a confirmation of that in the docs (and I was unable to<br>
actually make a test app that makes one fail), and the actual return<br>
value is currently unused (even after patch 2) so it doesn't matter yet,<br>
but it'd be nice to have the same sign-ness so that the value can be<br>
used at a later point.<br>
Otherwise, we might as well make this a boolean, I don't think much<br>
information would be lost really :)<span class=""><br></span></blockquote><div><br></div><div>Sure.  I'll make it positive.<br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span class="">
> +<br>
> +   pthread_condattr_t condattr;<br>
> +   ret = pthread_condattr_init(&<wbr>condattr);<br>
> +   if (ret)<br>
> +      goto fail_vector;<br>
> +<br>
> +   ret = pthread_condattr_setclock(&<wbr>condattr, CLOCK_MONOTONIC);<br>
> +   if (ret)<br>
> +      goto fail_condattr;<br>
> +<br>
> +   ret = pthread_cond_init(&queue-><wbr>cond, &condattr);<br>
> +   if (ret)<br>
> +      goto fail_condattr;<br>
> +<br>
> +   ret = pthread_mutex_init(&queue-><wbr>mutex, NULL);<br>
> +   if (ret) {<br>
> +      pthread_cond_destroy(&queue-><wbr>cond);<br>
<br>
</span>Double-free.<br></blockquote><div><br></div><div>Good catch!<br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
Other than that, the series is:<br>
Reviewed-by: Eric Engestrom <<a href="mailto:eric.engestrom@imgtec.com">eric.engestrom@imgtec.com</a>><br></blockquote><div><br></div><div>Thanks!<br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div class="HOEnZb"><div class="h5">
> +      goto fail_cond;<br>
> +   }<br>
> +<br>
> +   return 0;<br>
> +<br>
> +fail_cond:<br>
> +   pthread_cond_destroy(&queue-><wbr>cond);<br>
> +fail_condattr:<br>
> +   pthread_condattr_destroy(&<wbr>condattr);<br>
> +fail_vector:<br>
> +   u_vector_finish(&queue-><wbr>vector);<br>
> +<br>
> +   return ret;<br>
> +}<br>
> +<br>
> +static inline void<br>
> +wsi_queue_destroy(struct wsi_queue *queue)<br>
> +{<br>
> +   u_vector_finish(&queue-><wbr>vector);<br>
> +   pthread_mutex_destroy(&queue-><wbr>mutex);<br>
> +   pthread_cond_destroy(&queue-><wbr>cond);<br>
> +}<br>
> +<br>
> +static inline void<br>
> +wsi_queue_push(struct wsi_queue *queue, uint32_t index)<br>
> +{<br>
> +   uint32_t *elem;<br>
> +<br>
> +   pthread_mutex_lock(&queue-><wbr>mutex);<br>
> +<br>
> +   if (u_vector_length(&queue-><wbr>vector) == 0)<br>
> +      pthread_cond_signal(&queue-><wbr>cond);<br>
> +<br>
> +   elem = u_vector_add(&queue->vector);<br>
> +   *elem = index;<br>
> +<br>
> +   pthread_mutex_unlock(&queue-><wbr>mutex);<br>
> +}<br>
> +<br>
> +#define NSEC_PER_SEC 1000000000<br>
> +#define INT_TYPE_MAX(type) ((1ull << (sizeof(type) * 8 - 1)) - 1)<br>
> +<br>
> +static inline VkResult<br>
> +wsi_queue_pull(struct wsi_queue *queue, uint32_t *index, uint64_t timeout)<br>
> +{<br>
> +   VkResult result;<br>
> +   int32_t ret;<br>
> +<br>
> +   pthread_mutex_lock(&queue-><wbr>mutex);<br>
> +<br>
> +   struct timespec now;<br>
> +   clock_gettime(CLOCK_MONOTONIC, &now);<br>
> +<br>
> +   uint32_t abs_nsec = now.tv_nsec + timeout % NSEC_PER_SEC;<br>
> +   uint64_t abs_sec = now.tv_sec + (abs_nsec / NSEC_PER_SEC) +<br>
> +                      (timeout / NSEC_PER_SEC);<br>
> +   abs_nsec %= NSEC_PER_SEC;<br>
> +<br>
> +   /* Avoid roll-over in tv_sec on 32-bit systems if the user provided timeout<br>
> +    * is UINT64_MAX<br>
> +    */<br>
> +   struct timespec abstime;<br>
> +   abstime.tv_nsec = abs_nsec;<br>
> +   abstime.tv_sec = MIN2(abs_sec, INT_TYPE_MAX(abstime.tv_sec));<br>
> +<br>
> +   while (u_vector_length(&queue-><wbr>vector) == 0) {<br>
> +      ret = pthread_cond_timedwait(&queue-<wbr>>cond, &queue->mutex, &abstime);<br>
> +      if (ret == 0) {<br>
> +         continue;<br>
> +      } else if (ret == ETIMEDOUT) {<br>
> +         result = VK_TIMEOUT;<br>
> +         goto end;<br>
> +      } else {<br>
> +         /* Something went badly wrong */<br>
> +         result = VK_ERROR_OUT_OF_DATE_KHR;<br>
> +         goto end;<br>
> +      }<br>
> +   }<br>
> +<br>
> +   uint32_t *elem = u_vector_remove(&queue-><wbr>vector);<br>
> +   *index = *elem;<br>
> +   result = VK_SUCCESS;<br>
> +<br>
> +end:<br>
> +   pthread_mutex_unlock(&queue-><wbr>mutex);<br>
> +<br>
> +   return result;<br>
> +}<br>
> +<br>
> +#endif /* VULKAN_WSI_COMMON_QUEUE_H */<br>
> --<br>
> 2.5.0.400.gff86faf<br>
><br>
</div></div></blockquote></div><br></div></div>