1562cb03d76e4788d1d832f069e2c2f716e344fa4Marek Olšák/* 2562cb03d76e4788d1d832f069e2c2f716e344fa4Marek Olšák * Copyright © 2016 Advanced Micro Devices, Inc. 3562cb03d76e4788d1d832f069e2c2f716e344fa4Marek Olšák * All Rights Reserved. 4562cb03d76e4788d1d832f069e2c2f716e344fa4Marek Olšák * 5562cb03d76e4788d1d832f069e2c2f716e344fa4Marek Olšák * Permission is hereby granted, free of charge, to any person obtaining 6562cb03d76e4788d1d832f069e2c2f716e344fa4Marek Olšák * a copy of this software and associated documentation files (the 7562cb03d76e4788d1d832f069e2c2f716e344fa4Marek Olšák * "Software"), to deal in the Software without restriction, including 8562cb03d76e4788d1d832f069e2c2f716e344fa4Marek Olšák * without limitation the rights to use, copy, modify, merge, publish, 9562cb03d76e4788d1d832f069e2c2f716e344fa4Marek Olšák * distribute, sub license, and/or sell copies of the Software, and to 10562cb03d76e4788d1d832f069e2c2f716e344fa4Marek Olšák * permit persons to whom the Software is furnished to do so, subject to 11562cb03d76e4788d1d832f069e2c2f716e344fa4Marek Olšák * the following conditions: 12562cb03d76e4788d1d832f069e2c2f716e344fa4Marek Olšák * 13562cb03d76e4788d1d832f069e2c2f716e344fa4Marek Olšák * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 14562cb03d76e4788d1d832f069e2c2f716e344fa4Marek Olšák * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 15562cb03d76e4788d1d832f069e2c2f716e344fa4Marek Olšák * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 16562cb03d76e4788d1d832f069e2c2f716e344fa4Marek Olšák * NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS, AUTHORS 17562cb03d76e4788d1d832f069e2c2f716e344fa4Marek Olšák * AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18562cb03d76e4788d1d832f069e2c2f716e344fa4Marek Olšák * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19562cb03d76e4788d1d832f069e2c2f716e344fa4Marek Olšák * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 20562cb03d76e4788d1d832f069e2c2f716e344fa4Marek Olšák * USE OR OTHER DEALINGS IN THE SOFTWARE. 21562cb03d76e4788d1d832f069e2c2f716e344fa4Marek Olšák * 22562cb03d76e4788d1d832f069e2c2f716e344fa4Marek Olšák * The above copyright notice and this permission notice (including the 23562cb03d76e4788d1d832f069e2c2f716e344fa4Marek Olšák * next paragraph) shall be included in all copies or substantial portions 24562cb03d76e4788d1d832f069e2c2f716e344fa4Marek Olšák * of the Software. 25562cb03d76e4788d1d832f069e2c2f716e344fa4Marek Olšák */ 26562cb03d76e4788d1d832f069e2c2f716e344fa4Marek Olšák 27562cb03d76e4788d1d832f069e2c2f716e344fa4Marek Olšák#include "u_queue.h" 28404d0d50d8aaf60597668e65a2d7c96cdea53aeaMarek Olšák#include "u_memory.h" 292fba0aaa700bbdef37ac5da6da005b24be570e48Marek Olšák#include "u_string.h" 304358f6dd130680d60d48d6646959c11c8d7ca13dMarek Olšák#include "os/os_time.h" 314358f6dd130680d60d48d6646959c11c8d7ca13dMarek Olšák 326d2c4e940e5f6d80c94cc0ee9d26fee50202a4e0Marek Olšákstatic void util_queue_killall_and_wait(struct util_queue *queue); 336d2c4e940e5f6d80c94cc0ee9d26fee50202a4e0Marek Olšák 346d2c4e940e5f6d80c94cc0ee9d26fee50202a4e0Marek Olšák/**************************************************************************** 356d2c4e940e5f6d80c94cc0ee9d26fee50202a4e0Marek Olšák * Wait for all queues to assert idle when exit() is called. 366d2c4e940e5f6d80c94cc0ee9d26fee50202a4e0Marek Olšák * 376d2c4e940e5f6d80c94cc0ee9d26fee50202a4e0Marek Olšák * Otherwise, C++ static variable destructors can be called while threads 386d2c4e940e5f6d80c94cc0ee9d26fee50202a4e0Marek Olšák * are using the static variables. 396d2c4e940e5f6d80c94cc0ee9d26fee50202a4e0Marek Olšák */ 406d2c4e940e5f6d80c94cc0ee9d26fee50202a4e0Marek Olšák 416d2c4e940e5f6d80c94cc0ee9d26fee50202a4e0Marek Olšákstatic once_flag atexit_once_flag = ONCE_FLAG_INIT; 426d2c4e940e5f6d80c94cc0ee9d26fee50202a4e0Marek Olšákstatic struct list_head queue_list; 436d2c4e940e5f6d80c94cc0ee9d26fee50202a4e0Marek Olšákpipe_static_mutex(exit_mutex); 446d2c4e940e5f6d80c94cc0ee9d26fee50202a4e0Marek Olšák 456d2c4e940e5f6d80c94cc0ee9d26fee50202a4e0Marek Olšákstatic void 466d2c4e940e5f6d80c94cc0ee9d26fee50202a4e0Marek Olšákatexit_handler(void) 476d2c4e940e5f6d80c94cc0ee9d26fee50202a4e0Marek Olšák{ 486d2c4e940e5f6d80c94cc0ee9d26fee50202a4e0Marek Olšák struct util_queue *iter; 496d2c4e940e5f6d80c94cc0ee9d26fee50202a4e0Marek Olšák 506d2c4e940e5f6d80c94cc0ee9d26fee50202a4e0Marek Olšák pipe_mutex_lock(exit_mutex); 516d2c4e940e5f6d80c94cc0ee9d26fee50202a4e0Marek Olšák /* Wait for all queues to assert idle. */ 526d2c4e940e5f6d80c94cc0ee9d26fee50202a4e0Marek Olšák LIST_FOR_EACH_ENTRY(iter, &queue_list, head) { 536d2c4e940e5f6d80c94cc0ee9d26fee50202a4e0Marek Olšák util_queue_killall_and_wait(iter); 546d2c4e940e5f6d80c94cc0ee9d26fee50202a4e0Marek Olšák } 556d2c4e940e5f6d80c94cc0ee9d26fee50202a4e0Marek Olšák pipe_mutex_unlock(exit_mutex); 566d2c4e940e5f6d80c94cc0ee9d26fee50202a4e0Marek Olšák} 576d2c4e940e5f6d80c94cc0ee9d26fee50202a4e0Marek Olšák 586d2c4e940e5f6d80c94cc0ee9d26fee50202a4e0Marek Olšákstatic void 596d2c4e940e5f6d80c94cc0ee9d26fee50202a4e0Marek Olšákglobal_init(void) 606d2c4e940e5f6d80c94cc0ee9d26fee50202a4e0Marek Olšák{ 616d2c4e940e5f6d80c94cc0ee9d26fee50202a4e0Marek Olšák LIST_INITHEAD(&queue_list); 626d2c4e940e5f6d80c94cc0ee9d26fee50202a4e0Marek Olšák atexit(atexit_handler); 636d2c4e940e5f6d80c94cc0ee9d26fee50202a4e0Marek Olšák} 646d2c4e940e5f6d80c94cc0ee9d26fee50202a4e0Marek Olšák 656d2c4e940e5f6d80c94cc0ee9d26fee50202a4e0Marek Olšákstatic void 666d2c4e940e5f6d80c94cc0ee9d26fee50202a4e0Marek Olšákadd_to_atexit_list(struct util_queue *queue) 676d2c4e940e5f6d80c94cc0ee9d26fee50202a4e0Marek Olšák{ 686d2c4e940e5f6d80c94cc0ee9d26fee50202a4e0Marek Olšák call_once(&atexit_once_flag, global_init); 696d2c4e940e5f6d80c94cc0ee9d26fee50202a4e0Marek Olšák 706d2c4e940e5f6d80c94cc0ee9d26fee50202a4e0Marek Olšák pipe_mutex_lock(exit_mutex); 716d2c4e940e5f6d80c94cc0ee9d26fee50202a4e0Marek Olšák LIST_ADD(&queue->head, &queue_list); 726d2c4e940e5f6d80c94cc0ee9d26fee50202a4e0Marek Olšák pipe_mutex_unlock(exit_mutex); 736d2c4e940e5f6d80c94cc0ee9d26fee50202a4e0Marek Olšák} 746d2c4e940e5f6d80c94cc0ee9d26fee50202a4e0Marek Olšák 756d2c4e940e5f6d80c94cc0ee9d26fee50202a4e0Marek Olšákstatic void 766d2c4e940e5f6d80c94cc0ee9d26fee50202a4e0Marek Olšákremove_from_atexit_list(struct util_queue *queue) 776d2c4e940e5f6d80c94cc0ee9d26fee50202a4e0Marek Olšák{ 786d2c4e940e5f6d80c94cc0ee9d26fee50202a4e0Marek Olšák struct util_queue *iter, *tmp; 796d2c4e940e5f6d80c94cc0ee9d26fee50202a4e0Marek Olšák 806d2c4e940e5f6d80c94cc0ee9d26fee50202a4e0Marek Olšák pipe_mutex_lock(exit_mutex); 816d2c4e940e5f6d80c94cc0ee9d26fee50202a4e0Marek Olšák LIST_FOR_EACH_ENTRY_SAFE(iter, tmp, &queue_list, head) { 826d2c4e940e5f6d80c94cc0ee9d26fee50202a4e0Marek Olšák if (iter == queue) { 836d2c4e940e5f6d80c94cc0ee9d26fee50202a4e0Marek Olšák LIST_DEL(&iter->head); 846d2c4e940e5f6d80c94cc0ee9d26fee50202a4e0Marek Olšák break; 856d2c4e940e5f6d80c94cc0ee9d26fee50202a4e0Marek Olšák } 866d2c4e940e5f6d80c94cc0ee9d26fee50202a4e0Marek Olšák } 876d2c4e940e5f6d80c94cc0ee9d26fee50202a4e0Marek Olšák pipe_mutex_unlock(exit_mutex); 886d2c4e940e5f6d80c94cc0ee9d26fee50202a4e0Marek Olšák} 896d2c4e940e5f6d80c94cc0ee9d26fee50202a4e0Marek Olšák 906d2c4e940e5f6d80c94cc0ee9d26fee50202a4e0Marek Olšák/**************************************************************************** 916d2c4e940e5f6d80c94cc0ee9d26fee50202a4e0Marek Olšák * util_queue implementation 926d2c4e940e5f6d80c94cc0ee9d26fee50202a4e0Marek Olšák */ 936d2c4e940e5f6d80c94cc0ee9d26fee50202a4e0Marek Olšák 944358f6dd130680d60d48d6646959c11c8d7ca13dMarek Olšákstatic void 954358f6dd130680d60d48d6646959c11c8d7ca13dMarek Olšákutil_queue_fence_signal(struct util_queue_fence *fence) 964358f6dd130680d60d48d6646959c11c8d7ca13dMarek Olšák{ 974358f6dd130680d60d48d6646959c11c8d7ca13dMarek Olšák pipe_mutex_lock(fence->mutex); 984358f6dd130680d60d48d6646959c11c8d7ca13dMarek Olšák fence->signalled = true; 994358f6dd130680d60d48d6646959c11c8d7ca13dMarek Olšák pipe_condvar_broadcast(fence->cond); 1004358f6dd130680d60d48d6646959c11c8d7ca13dMarek Olšák pipe_mutex_unlock(fence->mutex); 1014358f6dd130680d60d48d6646959c11c8d7ca13dMarek Olšák} 1024358f6dd130680d60d48d6646959c11c8d7ca13dMarek Olšák 1034358f6dd130680d60d48d6646959c11c8d7ca13dMarek Olšákvoid 1044358f6dd130680d60d48d6646959c11c8d7ca13dMarek Olšákutil_queue_job_wait(struct util_queue_fence *fence) 1054358f6dd130680d60d48d6646959c11c8d7ca13dMarek Olšák{ 1064358f6dd130680d60d48d6646959c11c8d7ca13dMarek Olšák pipe_mutex_lock(fence->mutex); 1074358f6dd130680d60d48d6646959c11c8d7ca13dMarek Olšák while (!fence->signalled) 1084358f6dd130680d60d48d6646959c11c8d7ca13dMarek Olšák pipe_condvar_wait(fence->cond, fence->mutex); 1094358f6dd130680d60d48d6646959c11c8d7ca13dMarek Olšák pipe_mutex_unlock(fence->mutex); 1104358f6dd130680d60d48d6646959c11c8d7ca13dMarek Olšák} 111562cb03d76e4788d1d832f069e2c2f716e344fa4Marek Olšák 112404d0d50d8aaf60597668e65a2d7c96cdea53aeaMarek Olšákstruct thread_input { 113404d0d50d8aaf60597668e65a2d7c96cdea53aeaMarek Olšák struct util_queue *queue; 114404d0d50d8aaf60597668e65a2d7c96cdea53aeaMarek Olšák int thread_index; 115404d0d50d8aaf60597668e65a2d7c96cdea53aeaMarek Olšák}; 116404d0d50d8aaf60597668e65a2d7c96cdea53aeaMarek Olšák 117404d0d50d8aaf60597668e65a2d7c96cdea53aeaMarek Olšákstatic PIPE_THREAD_ROUTINE(util_queue_thread_func, input) 118562cb03d76e4788d1d832f069e2c2f716e344fa4Marek Olšák{ 119404d0d50d8aaf60597668e65a2d7c96cdea53aeaMarek Olšák struct util_queue *queue = ((struct thread_input*)input)->queue; 120404d0d50d8aaf60597668e65a2d7c96cdea53aeaMarek Olšák int thread_index = ((struct thread_input*)input)->thread_index; 121404d0d50d8aaf60597668e65a2d7c96cdea53aeaMarek Olšák 122404d0d50d8aaf60597668e65a2d7c96cdea53aeaMarek Olšák FREE(input); 123562cb03d76e4788d1d832f069e2c2f716e344fa4Marek Olšák 1242fba0aaa700bbdef37ac5da6da005b24be570e48Marek Olšák if (queue->name) { 1252fba0aaa700bbdef37ac5da6da005b24be570e48Marek Olšák char name[16]; 1262fba0aaa700bbdef37ac5da6da005b24be570e48Marek Olšák util_snprintf(name, sizeof(name), "%s:%i", queue->name, thread_index); 1272fba0aaa700bbdef37ac5da6da005b24be570e48Marek Olšák pipe_thread_setname(name); 1282fba0aaa700bbdef37ac5da6da005b24be570e48Marek Olšák } 1292fba0aaa700bbdef37ac5da6da005b24be570e48Marek Olšák 130562cb03d76e4788d1d832f069e2c2f716e344fa4Marek Olšák while (1) { 131562cb03d76e4788d1d832f069e2c2f716e344fa4Marek Olšák struct util_queue_job job; 132562cb03d76e4788d1d832f069e2c2f716e344fa4Marek Olšák 1334a06786efd42abfdb0babf65ed4ac59ae58fe4b5Marek Olšák pipe_mutex_lock(queue->lock); 1344a06786efd42abfdb0babf65ed4ac59ae58fe4b5Marek Olšák assert(queue->num_queued >= 0 && queue->num_queued <= queue->max_jobs); 1354a06786efd42abfdb0babf65ed4ac59ae58fe4b5Marek Olšák 1364a06786efd42abfdb0babf65ed4ac59ae58fe4b5Marek Olšák /* wait if the queue is empty */ 1374a06786efd42abfdb0babf65ed4ac59ae58fe4b5Marek Olšák while (!queue->kill_threads && queue->num_queued == 0) 1384a06786efd42abfdb0babf65ed4ac59ae58fe4b5Marek Olšák pipe_condvar_wait(queue->has_queued_cond, queue->lock); 1394a06786efd42abfdb0babf65ed4ac59ae58fe4b5Marek Olšák 1404a06786efd42abfdb0babf65ed4ac59ae58fe4b5Marek Olšák if (queue->kill_threads) { 1414a06786efd42abfdb0babf65ed4ac59ae58fe4b5Marek Olšák pipe_mutex_unlock(queue->lock); 142562cb03d76e4788d1d832f069e2c2f716e344fa4Marek Olšák break; 1434a06786efd42abfdb0babf65ed4ac59ae58fe4b5Marek Olšák } 144562cb03d76e4788d1d832f069e2c2f716e344fa4Marek Olšák 145d8367e91f2e3d8426e77674b39f36c09ed9992ecMarek Olšák job = queue->jobs[queue->read_idx]; 146cbb5adb90893a7c03f96f72f0665766a4007affdMarek Olšák memset(&queue->jobs[queue->read_idx], 0, sizeof(struct util_queue_job)); 147d8367e91f2e3d8426e77674b39f36c09ed9992ecMarek Olšák queue->read_idx = (queue->read_idx + 1) % queue->max_jobs; 148562cb03d76e4788d1d832f069e2c2f716e344fa4Marek Olšák 1494a06786efd42abfdb0babf65ed4ac59ae58fe4b5Marek Olšák queue->num_queued--; 1504a06786efd42abfdb0babf65ed4ac59ae58fe4b5Marek Olšák pipe_condvar_signal(queue->has_space_cond); 1514a06786efd42abfdb0babf65ed4ac59ae58fe4b5Marek Olšák pipe_mutex_unlock(queue->lock); 152562cb03d76e4788d1d832f069e2c2f716e344fa4Marek Olšák 153562cb03d76e4788d1d832f069e2c2f716e344fa4Marek Olšák if (job.job) { 154cbb5adb90893a7c03f96f72f0665766a4007affdMarek Olšák job.execute(job.job, thread_index); 1554358f6dd130680d60d48d6646959c11c8d7ca13dMarek Olšák util_queue_fence_signal(job.fence); 15644bbfedbd9983c61f6a461cbfe2e0dc74eda6d37Rob Clark if (job.cleanup) 15744bbfedbd9983c61f6a461cbfe2e0dc74eda6d37Rob Clark job.cleanup(job.job, thread_index); 158562cb03d76e4788d1d832f069e2c2f716e344fa4Marek Olšák } 159562cb03d76e4788d1d832f069e2c2f716e344fa4Marek Olšák } 160562cb03d76e4788d1d832f069e2c2f716e344fa4Marek Olšák 161562cb03d76e4788d1d832f069e2c2f716e344fa4Marek Olšák /* signal remaining jobs before terminating */ 162562cb03d76e4788d1d832f069e2c2f716e344fa4Marek Olšák pipe_mutex_lock(queue->lock); 163d8367e91f2e3d8426e77674b39f36c09ed9992ecMarek Olšák while (queue->jobs[queue->read_idx].job) { 1644358f6dd130680d60d48d6646959c11c8d7ca13dMarek Olšák util_queue_fence_signal(queue->jobs[queue->read_idx].fence); 1654358f6dd130680d60d48d6646959c11c8d7ca13dMarek Olšák 166d8367e91f2e3d8426e77674b39f36c09ed9992ecMarek Olšák queue->jobs[queue->read_idx].job = NULL; 167d8367e91f2e3d8426e77674b39f36c09ed9992ecMarek Olšák queue->read_idx = (queue->read_idx + 1) % queue->max_jobs; 168562cb03d76e4788d1d832f069e2c2f716e344fa4Marek Olšák } 1696d2c4e940e5f6d80c94cc0ee9d26fee50202a4e0Marek Olšák queue->num_queued = 0; /* reset this when exiting the thread */ 170562cb03d76e4788d1d832f069e2c2f716e344fa4Marek Olšák pipe_mutex_unlock(queue->lock); 171562cb03d76e4788d1d832f069e2c2f716e344fa4Marek Olšák return 0; 172562cb03d76e4788d1d832f069e2c2f716e344fa4Marek Olšák} 173562cb03d76e4788d1d832f069e2c2f716e344fa4Marek Olšák 174d8367e91f2e3d8426e77674b39f36c09ed9992ecMarek Olšákbool 175562cb03d76e4788d1d832f069e2c2f716e344fa4Marek Olšákutil_queue_init(struct util_queue *queue, 1762fba0aaa700bbdef37ac5da6da005b24be570e48Marek Olšák const char *name, 177d8367e91f2e3d8426e77674b39f36c09ed9992ecMarek Olšák unsigned max_jobs, 178cbb5adb90893a7c03f96f72f0665766a4007affdMarek Olšák unsigned num_threads) 179562cb03d76e4788d1d832f069e2c2f716e344fa4Marek Olšák{ 180404d0d50d8aaf60597668e65a2d7c96cdea53aeaMarek Olšák unsigned i; 181404d0d50d8aaf60597668e65a2d7c96cdea53aeaMarek Olšák 182562cb03d76e4788d1d832f069e2c2f716e344fa4Marek Olšák memset(queue, 0, sizeof(*queue)); 1832fba0aaa700bbdef37ac5da6da005b24be570e48Marek Olšák queue->name = name; 184404d0d50d8aaf60597668e65a2d7c96cdea53aeaMarek Olšák queue->num_threads = num_threads; 185d8367e91f2e3d8426e77674b39f36c09ed9992ecMarek Olšák queue->max_jobs = max_jobs; 186d8367e91f2e3d8426e77674b39f36c09ed9992ecMarek Olšák 187d8367e91f2e3d8426e77674b39f36c09ed9992ecMarek Olšák queue->jobs = (struct util_queue_job*) 188d8367e91f2e3d8426e77674b39f36c09ed9992ecMarek Olšák CALLOC(max_jobs, sizeof(struct util_queue_job)); 189d8367e91f2e3d8426e77674b39f36c09ed9992ecMarek Olšák if (!queue->jobs) 190d8367e91f2e3d8426e77674b39f36c09ed9992ecMarek Olšák goto fail; 191d8367e91f2e3d8426e77674b39f36c09ed9992ecMarek Olšák 192562cb03d76e4788d1d832f069e2c2f716e344fa4Marek Olšák pipe_mutex_init(queue->lock); 1934a06786efd42abfdb0babf65ed4ac59ae58fe4b5Marek Olšák 1944a06786efd42abfdb0babf65ed4ac59ae58fe4b5Marek Olšák queue->num_queued = 0; 1954a06786efd42abfdb0babf65ed4ac59ae58fe4b5Marek Olšák pipe_condvar_init(queue->has_queued_cond); 1964a06786efd42abfdb0babf65ed4ac59ae58fe4b5Marek Olšák pipe_condvar_init(queue->has_space_cond); 197d8367e91f2e3d8426e77674b39f36c09ed9992ecMarek Olšák 198404d0d50d8aaf60597668e65a2d7c96cdea53aeaMarek Olšák queue->threads = (pipe_thread*)CALLOC(num_threads, sizeof(pipe_thread)); 199404d0d50d8aaf60597668e65a2d7c96cdea53aeaMarek Olšák if (!queue->threads) 200d8367e91f2e3d8426e77674b39f36c09ed9992ecMarek Olšák goto fail; 201d8367e91f2e3d8426e77674b39f36c09ed9992ecMarek Olšák 202404d0d50d8aaf60597668e65a2d7c96cdea53aeaMarek Olšák /* start threads */ 203404d0d50d8aaf60597668e65a2d7c96cdea53aeaMarek Olšák for (i = 0; i < num_threads; i++) { 204404d0d50d8aaf60597668e65a2d7c96cdea53aeaMarek Olšák struct thread_input *input = MALLOC_STRUCT(thread_input); 205404d0d50d8aaf60597668e65a2d7c96cdea53aeaMarek Olšák input->queue = queue; 206404d0d50d8aaf60597668e65a2d7c96cdea53aeaMarek Olšák input->thread_index = i; 207404d0d50d8aaf60597668e65a2d7c96cdea53aeaMarek Olšák 208404d0d50d8aaf60597668e65a2d7c96cdea53aeaMarek Olšák queue->threads[i] = pipe_thread_create(util_queue_thread_func, input); 209404d0d50d8aaf60597668e65a2d7c96cdea53aeaMarek Olšák 210404d0d50d8aaf60597668e65a2d7c96cdea53aeaMarek Olšák if (!queue->threads[i]) { 211404d0d50d8aaf60597668e65a2d7c96cdea53aeaMarek Olšák FREE(input); 212404d0d50d8aaf60597668e65a2d7c96cdea53aeaMarek Olšák 213404d0d50d8aaf60597668e65a2d7c96cdea53aeaMarek Olšák if (i == 0) { 214404d0d50d8aaf60597668e65a2d7c96cdea53aeaMarek Olšák /* no threads created, fail */ 215404d0d50d8aaf60597668e65a2d7c96cdea53aeaMarek Olšák goto fail; 216404d0d50d8aaf60597668e65a2d7c96cdea53aeaMarek Olšák } else { 217404d0d50d8aaf60597668e65a2d7c96cdea53aeaMarek Olšák /* at least one thread created, so use it */ 218cfdda1939779782d36e144fa9a1d30e97163199eGrazvydas Ignotas queue->num_threads = i; 219404d0d50d8aaf60597668e65a2d7c96cdea53aeaMarek Olšák break; 220404d0d50d8aaf60597668e65a2d7c96cdea53aeaMarek Olšák } 221404d0d50d8aaf60597668e65a2d7c96cdea53aeaMarek Olšák } 222404d0d50d8aaf60597668e65a2d7c96cdea53aeaMarek Olšák } 2236d2c4e940e5f6d80c94cc0ee9d26fee50202a4e0Marek Olšák 2246d2c4e940e5f6d80c94cc0ee9d26fee50202a4e0Marek Olšák add_to_atexit_list(queue); 225d8367e91f2e3d8426e77674b39f36c09ed9992ecMarek Olšák return true; 226d8367e91f2e3d8426e77674b39f36c09ed9992ecMarek Olšák 227d8367e91f2e3d8426e77674b39f36c09ed9992ecMarek Olšákfail: 228404d0d50d8aaf60597668e65a2d7c96cdea53aeaMarek Olšák FREE(queue->threads); 229404d0d50d8aaf60597668e65a2d7c96cdea53aeaMarek Olšák 230d8367e91f2e3d8426e77674b39f36c09ed9992ecMarek Olšák if (queue->jobs) { 2314a06786efd42abfdb0babf65ed4ac59ae58fe4b5Marek Olšák pipe_condvar_destroy(queue->has_space_cond); 2324a06786efd42abfdb0babf65ed4ac59ae58fe4b5Marek Olšák pipe_condvar_destroy(queue->has_queued_cond); 233d8367e91f2e3d8426e77674b39f36c09ed9992ecMarek Olšák pipe_mutex_destroy(queue->lock); 234d8367e91f2e3d8426e77674b39f36c09ed9992ecMarek Olšák FREE(queue->jobs); 235d8367e91f2e3d8426e77674b39f36c09ed9992ecMarek Olšák } 236d8367e91f2e3d8426e77674b39f36c09ed9992ecMarek Olšák /* also util_queue_is_initialized can be used to check for success */ 237d8367e91f2e3d8426e77674b39f36c09ed9992ecMarek Olšák memset(queue, 0, sizeof(*queue)); 238d8367e91f2e3d8426e77674b39f36c09ed9992ecMarek Olšák return false; 239562cb03d76e4788d1d832f069e2c2f716e344fa4Marek Olšák} 240562cb03d76e4788d1d832f069e2c2f716e344fa4Marek Olšák 2416d2c4e940e5f6d80c94cc0ee9d26fee50202a4e0Marek Olšákstatic void 2426d2c4e940e5f6d80c94cc0ee9d26fee50202a4e0Marek Olšákutil_queue_killall_and_wait(struct util_queue *queue) 243562cb03d76e4788d1d832f069e2c2f716e344fa4Marek Olšák{ 244404d0d50d8aaf60597668e65a2d7c96cdea53aeaMarek Olšák unsigned i; 245404d0d50d8aaf60597668e65a2d7c96cdea53aeaMarek Olšák 246404d0d50d8aaf60597668e65a2d7c96cdea53aeaMarek Olšák /* Signal all threads to terminate. */ 2474a06786efd42abfdb0babf65ed4ac59ae58fe4b5Marek Olšák pipe_mutex_lock(queue->lock); 248404d0d50d8aaf60597668e65a2d7c96cdea53aeaMarek Olšák queue->kill_threads = 1; 2494a06786efd42abfdb0babf65ed4ac59ae58fe4b5Marek Olšák pipe_condvar_broadcast(queue->has_queued_cond); 2504a06786efd42abfdb0babf65ed4ac59ae58fe4b5Marek Olšák pipe_mutex_unlock(queue->lock); 251404d0d50d8aaf60597668e65a2d7c96cdea53aeaMarek Olšák 252404d0d50d8aaf60597668e65a2d7c96cdea53aeaMarek Olšák for (i = 0; i < queue->num_threads; i++) 253404d0d50d8aaf60597668e65a2d7c96cdea53aeaMarek Olšák pipe_thread_wait(queue->threads[i]); 2546b8c9e115e9921fe9c4ea5a8c0dc0a9f0adf39c2Grazvydas Ignotas queue->num_threads = 0; 2556d2c4e940e5f6d80c94cc0ee9d26fee50202a4e0Marek Olšák} 2566d2c4e940e5f6d80c94cc0ee9d26fee50202a4e0Marek Olšák 2576d2c4e940e5f6d80c94cc0ee9d26fee50202a4e0Marek Olšákvoid 2586d2c4e940e5f6d80c94cc0ee9d26fee50202a4e0Marek Olšákutil_queue_destroy(struct util_queue *queue) 2596d2c4e940e5f6d80c94cc0ee9d26fee50202a4e0Marek Olšák{ 2606d2c4e940e5f6d80c94cc0ee9d26fee50202a4e0Marek Olšák util_queue_killall_and_wait(queue); 2616d2c4e940e5f6d80c94cc0ee9d26fee50202a4e0Marek Olšák remove_from_atexit_list(queue); 262404d0d50d8aaf60597668e65a2d7c96cdea53aeaMarek Olšák 2634a06786efd42abfdb0babf65ed4ac59ae58fe4b5Marek Olšák pipe_condvar_destroy(queue->has_space_cond); 2644a06786efd42abfdb0babf65ed4ac59ae58fe4b5Marek Olšák pipe_condvar_destroy(queue->has_queued_cond); 265562cb03d76e4788d1d832f069e2c2f716e344fa4Marek Olšák pipe_mutex_destroy(queue->lock); 266d8367e91f2e3d8426e77674b39f36c09ed9992ecMarek Olšák FREE(queue->jobs); 267404d0d50d8aaf60597668e65a2d7c96cdea53aeaMarek Olšák FREE(queue->threads); 268562cb03d76e4788d1d832f069e2c2f716e344fa4Marek Olšák} 269562cb03d76e4788d1d832f069e2c2f716e344fa4Marek Olšák 270562cb03d76e4788d1d832f069e2c2f716e344fa4Marek Olšákvoid 271562cb03d76e4788d1d832f069e2c2f716e344fa4Marek Olšákutil_queue_fence_init(struct util_queue_fence *fence) 272562cb03d76e4788d1d832f069e2c2f716e344fa4Marek Olšák{ 2734358f6dd130680d60d48d6646959c11c8d7ca13dMarek Olšák memset(fence, 0, sizeof(*fence)); 2744358f6dd130680d60d48d6646959c11c8d7ca13dMarek Olšák pipe_mutex_init(fence->mutex); 2754358f6dd130680d60d48d6646959c11c8d7ca13dMarek Olšák pipe_condvar_init(fence->cond); 2764358f6dd130680d60d48d6646959c11c8d7ca13dMarek Olšák fence->signalled = true; 277562cb03d76e4788d1d832f069e2c2f716e344fa4Marek Olšák} 278562cb03d76e4788d1d832f069e2c2f716e344fa4Marek Olšák 279562cb03d76e4788d1d832f069e2c2f716e344fa4Marek Olšákvoid 280562cb03d76e4788d1d832f069e2c2f716e344fa4Marek Olšákutil_queue_fence_destroy(struct util_queue_fence *fence) 281562cb03d76e4788d1d832f069e2c2f716e344fa4Marek Olšák{ 282374aa2bb27efbd5e20daee09b6aea2a86b4775cdNicolai Hähnle assert(fence->signalled); 2834358f6dd130680d60d48d6646959c11c8d7ca13dMarek Olšák pipe_condvar_destroy(fence->cond); 2844358f6dd130680d60d48d6646959c11c8d7ca13dMarek Olšák pipe_mutex_destroy(fence->mutex); 285562cb03d76e4788d1d832f069e2c2f716e344fa4Marek Olšák} 286562cb03d76e4788d1d832f069e2c2f716e344fa4Marek Olšák 287562cb03d76e4788d1d832f069e2c2f716e344fa4Marek Olšákvoid 288562cb03d76e4788d1d832f069e2c2f716e344fa4Marek Olšákutil_queue_add_job(struct util_queue *queue, 289562cb03d76e4788d1d832f069e2c2f716e344fa4Marek Olšák void *job, 290cbb5adb90893a7c03f96f72f0665766a4007affdMarek Olšák struct util_queue_fence *fence, 29144bbfedbd9983c61f6a461cbfe2e0dc74eda6d37Rob Clark util_queue_execute_func execute, 29244bbfedbd9983c61f6a461cbfe2e0dc74eda6d37Rob Clark util_queue_execute_func cleanup) 293562cb03d76e4788d1d832f069e2c2f716e344fa4Marek Olšák{ 294d8367e91f2e3d8426e77674b39f36c09ed9992ecMarek Olšák struct util_queue_job *ptr; 2954358f6dd130680d60d48d6646959c11c8d7ca13dMarek Olšák 2964358f6dd130680d60d48d6646959c11c8d7ca13dMarek Olšák assert(fence->signalled); 2974358f6dd130680d60d48d6646959c11c8d7ca13dMarek Olšák fence->signalled = false; 298562cb03d76e4788d1d832f069e2c2f716e344fa4Marek Olšák 2994a06786efd42abfdb0babf65ed4ac59ae58fe4b5Marek Olšák pipe_mutex_lock(queue->lock); 3004a06786efd42abfdb0babf65ed4ac59ae58fe4b5Marek Olšák assert(queue->num_queued >= 0 && queue->num_queued <= queue->max_jobs); 3014a06786efd42abfdb0babf65ed4ac59ae58fe4b5Marek Olšák 302562cb03d76e4788d1d832f069e2c2f716e344fa4Marek Olšák /* if the queue is full, wait until there is space */ 3034a06786efd42abfdb0babf65ed4ac59ae58fe4b5Marek Olšák while (queue->num_queued == queue->max_jobs) 3044a06786efd42abfdb0babf65ed4ac59ae58fe4b5Marek Olšák pipe_condvar_wait(queue->has_space_cond, queue->lock); 305562cb03d76e4788d1d832f069e2c2f716e344fa4Marek Olšák 306d8367e91f2e3d8426e77674b39f36c09ed9992ecMarek Olšák ptr = &queue->jobs[queue->write_idx]; 307d8367e91f2e3d8426e77674b39f36c09ed9992ecMarek Olšák assert(ptr->job == NULL); 308d8367e91f2e3d8426e77674b39f36c09ed9992ecMarek Olšák ptr->job = job; 309d8367e91f2e3d8426e77674b39f36c09ed9992ecMarek Olšák ptr->fence = fence; 310cbb5adb90893a7c03f96f72f0665766a4007affdMarek Olšák ptr->execute = execute; 31144bbfedbd9983c61f6a461cbfe2e0dc74eda6d37Rob Clark ptr->cleanup = cleanup; 312d8367e91f2e3d8426e77674b39f36c09ed9992ecMarek Olšák queue->write_idx = (queue->write_idx + 1) % queue->max_jobs; 3134a06786efd42abfdb0babf65ed4ac59ae58fe4b5Marek Olšák 3144a06786efd42abfdb0babf65ed4ac59ae58fe4b5Marek Olšák queue->num_queued++; 3154a06786efd42abfdb0babf65ed4ac59ae58fe4b5Marek Olšák pipe_condvar_signal(queue->has_queued_cond); 316562cb03d76e4788d1d832f069e2c2f716e344fa4Marek Olšák pipe_mutex_unlock(queue->lock); 317562cb03d76e4788d1d832f069e2c2f716e344fa4Marek Olšák} 318