1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright © 2016 Intel Corporation 3bf215546Sopenharmony_ci * 4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation 7bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 9bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions: 10bf215546Sopenharmony_ci * 11bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next 12bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the 13bf215546Sopenharmony_ci * Software. 14bf215546Sopenharmony_ci * 15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20bf215546Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21bf215546Sopenharmony_ci * IN THE SOFTWARE. 22bf215546Sopenharmony_ci */ 23bf215546Sopenharmony_ci 24bf215546Sopenharmony_ci#ifndef VULKAN_WSI_COMMON_QUEUE_H 25bf215546Sopenharmony_ci#define VULKAN_WSI_COMMON_QUEUE_H 26bf215546Sopenharmony_ci 27bf215546Sopenharmony_ci#include <time.h> 28bf215546Sopenharmony_ci#include <pthread.h> 29bf215546Sopenharmony_ci#include "util/u_vector.h" 30bf215546Sopenharmony_ci 31bf215546Sopenharmony_cistruct wsi_queue { 32bf215546Sopenharmony_ci struct u_vector vector; 33bf215546Sopenharmony_ci pthread_mutex_t mutex; 34bf215546Sopenharmony_ci pthread_cond_t cond; 35bf215546Sopenharmony_ci}; 36bf215546Sopenharmony_ci 37bf215546Sopenharmony_cistatic inline int 38bf215546Sopenharmony_ciwsi_queue_init(struct wsi_queue *queue, int length) 39bf215546Sopenharmony_ci{ 40bf215546Sopenharmony_ci int ret; 41bf215546Sopenharmony_ci 42bf215546Sopenharmony_ci if (length < 4) 43bf215546Sopenharmony_ci length = 4; 44bf215546Sopenharmony_ci 45bf215546Sopenharmony_ci ret = u_vector_init(&queue->vector, length, sizeof(uint32_t)); 46bf215546Sopenharmony_ci if (!ret) 47bf215546Sopenharmony_ci return ENOMEM; 48bf215546Sopenharmony_ci 49bf215546Sopenharmony_ci pthread_condattr_t condattr; 50bf215546Sopenharmony_ci ret = pthread_condattr_init(&condattr); 51bf215546Sopenharmony_ci if (ret) 52bf215546Sopenharmony_ci goto fail_vector; 53bf215546Sopenharmony_ci 54bf215546Sopenharmony_ci ret = pthread_condattr_setclock(&condattr, CLOCK_MONOTONIC); 55bf215546Sopenharmony_ci if (ret) 56bf215546Sopenharmony_ci goto fail_condattr; 57bf215546Sopenharmony_ci 58bf215546Sopenharmony_ci ret = pthread_cond_init(&queue->cond, &condattr); 59bf215546Sopenharmony_ci if (ret) 60bf215546Sopenharmony_ci goto fail_condattr; 61bf215546Sopenharmony_ci 62bf215546Sopenharmony_ci ret = pthread_mutex_init(&queue->mutex, NULL); 63bf215546Sopenharmony_ci if (ret) 64bf215546Sopenharmony_ci goto fail_cond; 65bf215546Sopenharmony_ci 66bf215546Sopenharmony_ci pthread_condattr_destroy(&condattr); 67bf215546Sopenharmony_ci return 0; 68bf215546Sopenharmony_ci 69bf215546Sopenharmony_cifail_cond: 70bf215546Sopenharmony_ci pthread_cond_destroy(&queue->cond); 71bf215546Sopenharmony_cifail_condattr: 72bf215546Sopenharmony_ci pthread_condattr_destroy(&condattr); 73bf215546Sopenharmony_cifail_vector: 74bf215546Sopenharmony_ci u_vector_finish(&queue->vector); 75bf215546Sopenharmony_ci 76bf215546Sopenharmony_ci return ret; 77bf215546Sopenharmony_ci} 78bf215546Sopenharmony_ci 79bf215546Sopenharmony_cistatic inline void 80bf215546Sopenharmony_ciwsi_queue_destroy(struct wsi_queue *queue) 81bf215546Sopenharmony_ci{ 82bf215546Sopenharmony_ci u_vector_finish(&queue->vector); 83bf215546Sopenharmony_ci pthread_mutex_destroy(&queue->mutex); 84bf215546Sopenharmony_ci pthread_cond_destroy(&queue->cond); 85bf215546Sopenharmony_ci} 86bf215546Sopenharmony_ci 87bf215546Sopenharmony_cistatic inline void 88bf215546Sopenharmony_ciwsi_queue_push(struct wsi_queue *queue, uint32_t index) 89bf215546Sopenharmony_ci{ 90bf215546Sopenharmony_ci uint32_t *elem; 91bf215546Sopenharmony_ci 92bf215546Sopenharmony_ci pthread_mutex_lock(&queue->mutex); 93bf215546Sopenharmony_ci 94bf215546Sopenharmony_ci if (u_vector_length(&queue->vector) == 0) 95bf215546Sopenharmony_ci pthread_cond_signal(&queue->cond); 96bf215546Sopenharmony_ci 97bf215546Sopenharmony_ci elem = u_vector_add(&queue->vector); 98bf215546Sopenharmony_ci *elem = index; 99bf215546Sopenharmony_ci 100bf215546Sopenharmony_ci pthread_mutex_unlock(&queue->mutex); 101bf215546Sopenharmony_ci} 102bf215546Sopenharmony_ci 103bf215546Sopenharmony_ci#define NSEC_PER_SEC 1000000000 104bf215546Sopenharmony_ci#define INT_TYPE_MAX(type) ((1ull << (sizeof(type) * 8 - 1)) - 1) 105bf215546Sopenharmony_ci 106bf215546Sopenharmony_cistatic inline VkResult 107bf215546Sopenharmony_ciwsi_queue_pull(struct wsi_queue *queue, uint32_t *index, uint64_t timeout) 108bf215546Sopenharmony_ci{ 109bf215546Sopenharmony_ci VkResult result; 110bf215546Sopenharmony_ci int32_t ret; 111bf215546Sopenharmony_ci 112bf215546Sopenharmony_ci pthread_mutex_lock(&queue->mutex); 113bf215546Sopenharmony_ci 114bf215546Sopenharmony_ci struct timespec now; 115bf215546Sopenharmony_ci clock_gettime(CLOCK_MONOTONIC, &now); 116bf215546Sopenharmony_ci 117bf215546Sopenharmony_ci uint32_t abs_nsec = now.tv_nsec + timeout % NSEC_PER_SEC; 118bf215546Sopenharmony_ci uint64_t abs_sec = now.tv_sec + (abs_nsec / NSEC_PER_SEC) + 119bf215546Sopenharmony_ci (timeout / NSEC_PER_SEC); 120bf215546Sopenharmony_ci abs_nsec %= NSEC_PER_SEC; 121bf215546Sopenharmony_ci 122bf215546Sopenharmony_ci /* Avoid roll-over in tv_sec on 32-bit systems if the user provided timeout 123bf215546Sopenharmony_ci * is UINT64_MAX 124bf215546Sopenharmony_ci */ 125bf215546Sopenharmony_ci struct timespec abstime; 126bf215546Sopenharmony_ci abstime.tv_nsec = abs_nsec; 127bf215546Sopenharmony_ci abstime.tv_sec = MIN2(abs_sec, INT_TYPE_MAX(abstime.tv_sec)); 128bf215546Sopenharmony_ci 129bf215546Sopenharmony_ci while (u_vector_length(&queue->vector) == 0) { 130bf215546Sopenharmony_ci ret = pthread_cond_timedwait(&queue->cond, &queue->mutex, &abstime); 131bf215546Sopenharmony_ci if (ret == 0) { 132bf215546Sopenharmony_ci continue; 133bf215546Sopenharmony_ci } else if (ret == ETIMEDOUT) { 134bf215546Sopenharmony_ci result = VK_TIMEOUT; 135bf215546Sopenharmony_ci goto end; 136bf215546Sopenharmony_ci } else { 137bf215546Sopenharmony_ci /* Something went badly wrong */ 138bf215546Sopenharmony_ci result = VK_ERROR_OUT_OF_DATE_KHR; 139bf215546Sopenharmony_ci goto end; 140bf215546Sopenharmony_ci } 141bf215546Sopenharmony_ci } 142bf215546Sopenharmony_ci 143bf215546Sopenharmony_ci uint32_t *elem = u_vector_remove(&queue->vector); 144bf215546Sopenharmony_ci *index = *elem; 145bf215546Sopenharmony_ci result = VK_SUCCESS; 146bf215546Sopenharmony_ci 147bf215546Sopenharmony_ciend: 148bf215546Sopenharmony_ci pthread_mutex_unlock(&queue->mutex); 149bf215546Sopenharmony_ci 150bf215546Sopenharmony_ci return result; 151bf215546Sopenharmony_ci} 152bf215546Sopenharmony_ci 153bf215546Sopenharmony_ci#endif /* VULKAN_WSI_COMMON_QUEUE_H */ 154