1 /* 2 * Copyright 2016 Advanced Micro Devices, Inc. 3 * All Rights Reserved. 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining 6 * a copy of this software and associated documentation files (the 7 * "Software"), to deal in the Software without restriction, including 8 * without limitation the rights to use, copy, modify, merge, publish, 9 * distribute, sub license, and/or sell copies of the Software, and to 10 * permit persons to whom the Software is furnished to do so, subject to 11 * the following conditions: 12 * 13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 14 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 15 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 16 * NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS, AUTHORS 17 * AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 20 * USE OR OTHER DEALINGS IN THE SOFTWARE. 21 * 22 * The above copyright notice and this permission notice (including the 23 * next paragraph) shall be included in all copies or substantial portions 24 * of the Software. 25 */ 26 27 /* Job queue with execution in a separate thread. 28 * 29 * Jobs can be added from any thread. After that, the wait call can be used 30 * to wait for completion of the job. 31 */ 32 33 #ifndef U_QUEUE_H 34 #define U_QUEUE_H 35 36 #include "os/os_thread.h" 37 #include "util/list.h" 38 39 /* Job completion fence. 40 * Put this into your job structure. 41 */ 42 struct util_queue_fence { 43 pipe_mutex mutex; 44 pipe_condvar cond; 45 int signalled; 46 }; 47 48 typedef void (*util_queue_execute_func)(void *job, int thread_index); 49 50 struct util_queue_job { 51 void *job; 52 struct util_queue_fence *fence; 53 util_queue_execute_func execute; 54 util_queue_execute_func cleanup; 55 }; 56 57 /* Put this into your context. */ 58 struct util_queue { 59 const char *name; 60 pipe_mutex lock; 61 pipe_condvar has_queued_cond; 62 pipe_condvar has_space_cond; 63 pipe_thread *threads; 64 int num_queued; 65 unsigned num_threads; 66 int kill_threads; 67 int max_jobs; 68 int write_idx, read_idx; /* ring buffer pointers */ 69 struct util_queue_job *jobs; 70 71 /* for cleanup at exit(), protected by exit_mutex */ 72 struct list_head head; 73 }; 74 75 bool util_queue_init(struct util_queue *queue, 76 const char *name, 77 unsigned max_jobs, 78 unsigned num_threads); 79 void util_queue_destroy(struct util_queue *queue); 80 void util_queue_fence_init(struct util_queue_fence *fence); 81 void util_queue_fence_destroy(struct util_queue_fence *fence); 82 83 /* optional cleanup callback is called after fence is signaled: */ 84 void util_queue_add_job(struct util_queue *queue, 85 void *job, 86 struct util_queue_fence *fence, 87 util_queue_execute_func execute, 88 util_queue_execute_func cleanup); 89 90 void util_queue_job_wait(struct util_queue_fence *fence); 91 92 /* util_queue needs to be cleared to zeroes for this to work */ 93 static inline bool 94 util_queue_is_initialized(struct util_queue *queue) 95 { 96 return queue->threads != NULL; 97 } 98 99 static inline bool 100 util_queue_fence_is_signalled(struct util_queue_fence *fence) 101 { 102 return fence->signalled != 0; 103 } 104 105 #endif 106