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