1 /*
2 * Copyright © 2016 Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * 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 OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21 * IN THE SOFTWARE.
22 */
23
24 #ifndef VULKAN_WSI_COMMON_QUEUE_H
25 #define VULKAN_WSI_COMMON_QUEUE_H
26
27 #include <time.h>
28 #include "util/cnd_monotonic.h"
29 #include "util/u_vector.h"
30
31 struct wsi_queue {
32 struct u_vector vector;
33 mtx_t mutex;
34 struct u_cnd_monotonic cond;
35 };
36
37 static inline int
wsi_queue_init(struct wsi_queue * queue,int length)38 wsi_queue_init(struct wsi_queue *queue, int length)
39 {
40 int ret;
41
42 if (length < 4)
43 length = 4;
44
45 ret = u_vector_init(&queue->vector, length, sizeof(uint32_t));
46 if (!ret)
47 return ENOMEM;
48
49 ret = u_cnd_monotonic_init(&queue->cond);
50 if (ret != thrd_success)
51 goto fail_vector;
52
53 ret = mtx_init(&queue->mutex, mtx_plain);
54 if (ret != thrd_success)
55 goto fail_cond;
56
57 return 0;
58
59 fail_cond:
60 u_cnd_monotonic_destroy(&queue->cond);
61 fail_vector:
62 u_vector_finish(&queue->vector);
63
64 return ret;
65 }
66
67 static inline void
wsi_queue_destroy(struct wsi_queue * queue)68 wsi_queue_destroy(struct wsi_queue *queue)
69 {
70 u_vector_finish(&queue->vector);
71 mtx_destroy(&queue->mutex);
72 u_cnd_monotonic_destroy(&queue->cond);
73 }
74
75 static inline void
wsi_queue_push(struct wsi_queue * queue,uint32_t index)76 wsi_queue_push(struct wsi_queue *queue, uint32_t index)
77 {
78 uint32_t *elem;
79
80 mtx_lock(&queue->mutex);
81
82 if (u_vector_length(&queue->vector) == 0)
83 u_cnd_monotonic_signal(&queue->cond);
84
85 elem = u_vector_add(&queue->vector);
86 *elem = index;
87
88 mtx_unlock(&queue->mutex);
89 }
90
91 static inline VkResult
wsi_queue_pull(struct wsi_queue * queue,uint32_t * index,uint64_t timeout)92 wsi_queue_pull(struct wsi_queue *queue, uint32_t *index, uint64_t timeout)
93 {
94 VkResult result;
95 int32_t ret;
96
97 mtx_lock(&queue->mutex);
98
99 struct timespec abs_timeout_ts;
100 timespec_from_nsec(&abs_timeout_ts, os_time_get_absolute_timeout(timeout));
101
102 while (u_vector_length(&queue->vector) == 0) {
103 ret = u_cnd_monotonic_timedwait(&queue->cond, &queue->mutex,
104 &abs_timeout_ts);
105 if (ret == thrd_success) {
106 continue;
107 } else if (ret == thrd_timedout) {
108 result = VK_TIMEOUT;
109 goto end;
110 } else {
111 /* Something went badly wrong */
112 result = VK_ERROR_OUT_OF_DATE_KHR;
113 goto end;
114 }
115 }
116
117 uint32_t *elem = u_vector_remove(&queue->vector);
118 *index = *elem;
119 result = VK_SUCCESS;
120
121 end:
122 mtx_unlock(&queue->mutex);
123
124 return result;
125 }
126
127 #endif /* VULKAN_WSI_COMMON_QUEUE_H */
128