From d8367e91f2e3d8426e77674b39f36c09ed9992ec Mon Sep 17 00:00:00 2001 From: =?utf8?q?Marek=20Ol=C5=A1=C3=A1k?= Date: Sun, 12 Jun 2016 12:54:42 +0200 Subject: [PATCH] gallium/u_queue: use a ring instead of a stack MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit and allow specifying its size in util_queue_init. v2: use CALLOC & FREE Reviewed-by: Nicolai Hähnle --- src/gallium/auxiliary/util/u_queue.c | 55 ++++++++++++++----- src/gallium/auxiliary/util/u_queue.h | 8 ++- src/gallium/winsys/amdgpu/drm/amdgpu_winsys.c | 2 +- .../winsys/radeon/drm/radeon_drm_winsys.c | 2 +- 4 files changed, 47 insertions(+), 20 deletions(-) diff --git a/src/gallium/auxiliary/util/u_queue.c b/src/gallium/auxiliary/util/u_queue.c index 8e58414247b..2b6850d02e4 100644 --- a/src/gallium/auxiliary/util/u_queue.c +++ b/src/gallium/auxiliary/util/u_queue.c @@ -29,7 +29,6 @@ static PIPE_THREAD_ROUTINE(util_queue_thread_func, param) { struct util_queue *queue = (struct util_queue*)param; - unsigned i; while (1) { struct util_queue_job job; @@ -39,10 +38,9 @@ static PIPE_THREAD_ROUTINE(util_queue_thread_func, param) break; pipe_mutex_lock(queue->lock); - job = queue->jobs[0]; - for (i = 1; i < queue->num_jobs; i++) - queue->jobs[i - 1] = queue->jobs[i]; - queue->jobs[--queue->num_jobs].job = NULL; + job = queue->jobs[queue->read_idx]; + queue->jobs[queue->read_idx].job = NULL; + queue->read_idx = (queue->read_idx + 1) % queue->max_jobs; pipe_mutex_unlock(queue->lock); pipe_semaphore_signal(&queue->has_space); @@ -55,25 +53,49 @@ static PIPE_THREAD_ROUTINE(util_queue_thread_func, param) /* signal remaining jobs before terminating */ pipe_mutex_lock(queue->lock); - for (i = 0; i < queue->num_jobs; i++) { - pipe_semaphore_signal(&queue->jobs[i].fence->done); - queue->jobs[i].job = NULL; + while (queue->jobs[queue->read_idx].job) { + pipe_semaphore_signal(&queue->jobs[queue->read_idx].fence->done); + queue->jobs[queue->read_idx].job = NULL; + queue->read_idx = (queue->read_idx + 1) % queue->max_jobs; } - queue->num_jobs = 0; pipe_mutex_unlock(queue->lock); return 0; } -void +bool util_queue_init(struct util_queue *queue, + unsigned max_jobs, void (*execute_job)(void *)) { memset(queue, 0, sizeof(*queue)); + queue->max_jobs = max_jobs; + + queue->jobs = (struct util_queue_job*) + CALLOC(max_jobs, sizeof(struct util_queue_job)); + if (!queue->jobs) + goto fail; + queue->execute_job = execute_job; pipe_mutex_init(queue->lock); - pipe_semaphore_init(&queue->has_space, ARRAY_SIZE(queue->jobs)); + pipe_semaphore_init(&queue->has_space, max_jobs); pipe_semaphore_init(&queue->queued, 0); + queue->thread = pipe_thread_create(util_queue_thread_func, queue); + if (!queue->thread) + goto fail; + + return true; + +fail: + if (queue->jobs) { + pipe_semaphore_destroy(&queue->has_space); + pipe_semaphore_destroy(&queue->queued); + pipe_mutex_destroy(queue->lock); + FREE(queue->jobs); + } + /* also util_queue_is_initialized can be used to check for success */ + memset(queue, 0, sizeof(*queue)); + return false; } void @@ -85,6 +107,7 @@ util_queue_destroy(struct util_queue *queue) pipe_semaphore_destroy(&queue->has_space); pipe_semaphore_destroy(&queue->queued); pipe_mutex_destroy(queue->lock); + FREE(queue->jobs); } void @@ -104,6 +127,7 @@ util_queue_add_job(struct util_queue *queue, void *job, struct util_queue_fence *fence) { + struct util_queue_job *ptr; /* Set the semaphore to "busy". */ pipe_semaphore_wait(&fence->done); @@ -111,10 +135,11 @@ util_queue_add_job(struct util_queue *queue, pipe_semaphore_wait(&queue->has_space); pipe_mutex_lock(queue->lock); - assert(queue->num_jobs < ARRAY_SIZE(queue->jobs)); - queue->jobs[queue->num_jobs].job = job; - queue->jobs[queue->num_jobs].fence = fence; - queue->num_jobs++; + ptr = &queue->jobs[queue->write_idx]; + assert(ptr->job == NULL); + ptr->job = job; + ptr->fence = fence; + queue->write_idx = (queue->write_idx + 1) % queue->max_jobs; pipe_mutex_unlock(queue->lock); pipe_semaphore_signal(&queue->queued); } diff --git a/src/gallium/auxiliary/util/u_queue.h b/src/gallium/auxiliary/util/u_queue.h index db5a266fd41..48cd9f4c707 100644 --- a/src/gallium/auxiliary/util/u_queue.h +++ b/src/gallium/auxiliary/util/u_queue.h @@ -54,12 +54,14 @@ struct util_queue { pipe_semaphore queued; pipe_thread thread; int kill_thread; - int num_jobs; - struct util_queue_job jobs[8]; + int max_jobs; + int write_idx, read_idx; /* ring buffer pointers */ + struct util_queue_job *jobs; void (*execute_job)(void *job); }; -void util_queue_init(struct util_queue *queue, +bool util_queue_init(struct util_queue *queue, + unsigned max_jobs, void (*execute_job)(void *)); void util_queue_destroy(struct util_queue *queue); void util_queue_fence_init(struct util_queue_fence *fence); diff --git a/src/gallium/winsys/amdgpu/drm/amdgpu_winsys.c b/src/gallium/winsys/amdgpu/drm/amdgpu_winsys.c index 7ef35298aa8..ddcdc865f1b 100644 --- a/src/gallium/winsys/amdgpu/drm/amdgpu_winsys.c +++ b/src/gallium/winsys/amdgpu/drm/amdgpu_winsys.c @@ -493,7 +493,7 @@ amdgpu_winsys_create(int fd, radeon_screen_create_t screen_create) pipe_mutex_init(ws->bo_fence_lock); if (sysconf(_SC_NPROCESSORS_ONLN) > 1 && debug_get_option_thread()) - util_queue_init(&ws->cs_queue, amdgpu_cs_submit_ib); + util_queue_init(&ws->cs_queue, 8, amdgpu_cs_submit_ib); /* Create the screen at the end. The winsys must be initialized * completely. diff --git a/src/gallium/winsys/radeon/drm/radeon_drm_winsys.c b/src/gallium/winsys/radeon/drm/radeon_drm_winsys.c index 1f296f44de0..453cbfc935c 100644 --- a/src/gallium/winsys/radeon/drm/radeon_drm_winsys.c +++ b/src/gallium/winsys/radeon/drm/radeon_drm_winsys.c @@ -783,7 +783,7 @@ radeon_drm_winsys_create(int fd, radeon_screen_create_t screen_create) ws->info.gart_page_size = sysconf(_SC_PAGESIZE); if (ws->num_cpus > 1 && debug_get_option_thread()) - util_queue_init(&ws->cs_queue, + util_queue_init(&ws->cs_queue, 8, radeon_drm_cs_emit_ioctl_oneshot); /* Create the screen at the end. The winsys must be initialized -- 2.30.2