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