Mesa (master): util/u_queue: add a way to remove a job when we just want to destroy it

Marek Olšák mareko at kemper.freedesktop.org
Wed Jun 7 16:43:55 UTC 2017


Module: Mesa
Branch: master
Commit: 33e507ec23db3778294b75a1485021d2a35b0a22
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=33e507ec23db3778294b75a1485021d2a35b0a22

Author: Marek Olšák <marek.olsak at amd.com>
Date:   Wed May 31 16:44:12 2017 +0200

util/u_queue: add a way to remove a job when we just want to destroy it

Reviewed-by: Nicolai Hähnle <nicolai.haehnle at amd.com>

---

 src/util/u_queue.c | 53 +++++++++++++++++++++++++++++++++++++++++++++++------
 src/util/u_queue.h |  2 ++
 2 files changed, 49 insertions(+), 6 deletions(-)

diff --git a/src/util/u_queue.c b/src/util/u_queue.c
index 8db09b027c..01c3a96d5f 100644
--- a/src/util/u_queue.c
+++ b/src/util/u_queue.c
@@ -180,13 +180,15 @@ util_queue_thread_func(void *input)
 
    /* signal remaining jobs before terminating */
    mtx_lock(&queue->lock);
-   while (queue->jobs[queue->read_idx].job) {
-      util_queue_fence_signal(queue->jobs[queue->read_idx].fence);
-
-      queue->jobs[queue->read_idx].job = NULL;
-      queue->read_idx = (queue->read_idx + 1) % queue->max_jobs;
+   for (unsigned i = queue->read_idx; i != queue->write_idx;
+        i = (i + 1) % queue->max_jobs) {
+      if (queue->jobs[i].job) {
+         util_queue_fence_signal(queue->jobs[i].fence);
+         queue->jobs[i].job = NULL;
+      }
    }
-   queue->num_queued = 0; /* reset this when exiting the thread */
+   queue->read_idx = queue->write_idx;
+   queue->num_queued = 0;
    mtx_unlock(&queue->lock);
    return 0;
 }
@@ -329,6 +331,45 @@ util_queue_add_job(struct util_queue *queue,
    mtx_unlock(&queue->lock);
 }
 
+/**
+ * Remove a queued job. If the job hasn't started execution, it's removed from
+ * the queue. If the job has started execution, the function waits for it to
+ * complete.
+ *
+ * In all cases, the fence is signalled when the function returns.
+ *
+ * The function can be used when destroying an object associated with the job
+ * when you don't care about the job completion state.
+ */
+void
+util_queue_drop_job(struct util_queue *queue, struct util_queue_fence *fence)
+{
+   bool removed = false;
+
+   if (util_queue_fence_is_signalled(fence))
+      return;
+
+   mtx_lock(&queue->lock);
+   for (unsigned i = queue->read_idx; i != queue->write_idx;
+        i = (i + 1) % queue->max_jobs) {
+      if (queue->jobs[i].fence == fence) {
+         if (queue->jobs[i].cleanup)
+            queue->jobs[i].cleanup(queue->jobs[i].job, -1);
+
+         /* Just clear it. The threads will treat as a no-op job. */
+         memset(&queue->jobs[i], 0, sizeof(queue->jobs[i]));
+         removed = true;
+         break;
+      }
+   }
+   mtx_unlock(&queue->lock);
+
+   if (removed)
+      util_queue_fence_signal(fence);
+   else
+      util_queue_fence_wait(fence);
+}
+
 int64_t
 util_queue_get_thread_time_nano(struct util_queue *queue, unsigned thread_index)
 {
diff --git a/src/util/u_queue.h b/src/util/u_queue.h
index 4aec1f2047..9876865c65 100644
--- a/src/util/u_queue.h
+++ b/src/util/u_queue.h
@@ -92,6 +92,8 @@ void util_queue_add_job(struct util_queue *queue,
                         struct util_queue_fence *fence,
                         util_queue_execute_func execute,
                         util_queue_execute_func cleanup);
+void util_queue_drop_job(struct util_queue *queue,
+                         struct util_queue_fence *fence);
 
 void util_queue_fence_wait(struct util_queue_fence *fence);
 int64_t util_queue_get_thread_time_nano(struct util_queue *queue,




More information about the mesa-commit mailing list