From: Nicolai Hähnle <nicolai.haeh...@amd.com> Schedule one job for every thread, and wait on a barrier inside the job execution function. --- src/util/u_queue.c | 35 +++++++++++++++++++++++++++++++++++ src/util/u_queue.h | 2 ++ 2 files changed, 37 insertions(+)
diff --git a/src/util/u_queue.c b/src/util/u_queue.c index 8293ec661b0..7008391d210 100644 --- a/src/util/u_queue.c +++ b/src/util/u_queue.c @@ -18,21 +18,25 @@ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE * USE OR OTHER DEALINGS IN THE SOFTWARE. * * The above copyright notice and this permission notice (including the * next paragraph) shall be included in all copies or substantial portions * of the Software. */ #include "u_queue.h" + +#include <alloca.h> + #include "util/u_string.h" +#include "util/u_thread.h" static void util_queue_killall_and_wait(struct util_queue *queue); /**************************************************************************** * Wait for all queues to assert idle when exit() is called. * * Otherwise, C++ static variable destructors can be called while threads * are using the static variables. */ @@ -422,19 +426,50 @@ util_queue_drop_job(struct util_queue *queue, struct util_queue_fence *fence) } } mtx_unlock(&queue->lock); if (removed) util_queue_fence_signal(fence); else util_queue_fence_wait(fence); } +static void +util_queue_finish_execute(void *data, int num_thread) +{ + util_barrier *barrier = data; + util_barrier_wait(barrier); +} + +/** + * Wait until all previously added jobs have completed. + */ +void +util_queue_finish(struct util_queue *queue) +{ + util_barrier barrier; + struct util_queue_fence *fences = alloca(queue->num_threads * sizeof(*fences)); + + util_barrier_init(&barrier, queue->num_threads); + + for (unsigned i = 0; i < queue->num_threads; ++i) { + util_queue_fence_init(&fences[i]); + util_queue_add_job(queue, &barrier, &fences[i], util_queue_finish_execute, NULL); + } + + for (unsigned i = 0; i < queue->num_threads; ++i) { + util_queue_fence_wait(&fences[i]); + util_queue_fence_destroy(&fences[i]); + } + + util_barrier_destroy(&barrier); +} + int64_t util_queue_get_thread_time_nano(struct util_queue *queue, unsigned thread_index) { /* Allow some flexibility by not raising an error. */ if (thread_index >= queue->num_threads) return 0; return u_thread_get_time_nano(queue->threads[thread_index]); } diff --git a/src/util/u_queue.h b/src/util/u_queue.h index 3d9f19f4e6c..f92797ba5aa 100644 --- a/src/util/u_queue.h +++ b/src/util/u_queue.h @@ -203,20 +203,22 @@ void util_queue_destroy(struct util_queue *queue); /* optional cleanup callback is called after fence is signaled: */ void util_queue_add_job(struct util_queue *queue, void *job, 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_finish(struct util_queue *queue); + int64_t util_queue_get_thread_time_nano(struct util_queue *queue, unsigned thread_index); /* util_queue needs to be cleared to zeroes for this to work */ static inline bool util_queue_is_initialized(struct util_queue *queue) { return queue->threads != NULL; } -- 2.11.0 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev