winsys/radeon: Create async thread only once

I noticed that a thread was created for every time async flush was called, so I moved it and used some semaphores to synch.

Signed-off-by: Maarten Lankhorst <m.b.lankhorst@gmail.com>
Reviewed-by: Marek Olšák <maraeo@gmail.com>
Signed-off-by: Christian König <deathsimple@vodafone.de>
This commit is contained in:
Maarten Lankhorst 2011-08-27 22:57:19 +02:00 committed by Christian König
parent 3b3d2e53bc
commit 210ddf0819
2 changed files with 58 additions and 29 deletions

View file

@ -130,6 +130,9 @@ static void radeon_destroy_cs_context(struct radeon_cs_context *csc)
FREE(csc->relocs); FREE(csc->relocs);
} }
DEBUG_GET_ONCE_BOOL_OPTION(thread, "RADEON_THREAD", TRUE)
static PIPE_THREAD_ROUTINE(radeon_drm_cs_emit_ioctl, param);
static struct radeon_winsys_cs *radeon_drm_cs_create(struct radeon_winsys *rws) static struct radeon_winsys_cs *radeon_drm_cs_create(struct radeon_winsys *rws)
{ {
struct radeon_drm_winsys *ws = radeon_drm_winsys(rws); struct radeon_drm_winsys *ws = radeon_drm_winsys(rws);
@ -139,6 +142,8 @@ static struct radeon_winsys_cs *radeon_drm_cs_create(struct radeon_winsys *rws)
if (!cs) { if (!cs) {
return NULL; return NULL;
} }
pipe_semaphore_init(&cs->flush_queued, 0);
pipe_semaphore_init(&cs->flush_completed, 0);
cs->ws = ws; cs->ws = ws;
@ -158,6 +163,8 @@ static struct radeon_winsys_cs *radeon_drm_cs_create(struct radeon_winsys *rws)
cs->base.buf = cs->csc->buf; cs->base.buf = cs->csc->buf;
p_atomic_inc(&ws->num_cs); p_atomic_inc(&ws->num_cs);
if (cs->ws->num_cpus > 1 && debug_get_option_thread())
cs->thread = pipe_thread_create(radeon_drm_cs_emit_ioctl, cs);
return &cs->base; return &cs->base;
} }
@ -357,9 +364,8 @@ static void radeon_drm_cs_write_reloc(struct radeon_winsys_cs *rcs,
OUT_CS(&cs->base, index * RELOC_DWORDS); OUT_CS(&cs->base, index * RELOC_DWORDS);
} }
static PIPE_THREAD_ROUTINE(radeon_drm_cs_emit_ioctl, param) static void radeon_drm_cs_emit_ioctl_oneshot(struct radeon_cs_context *csc)
{ {
struct radeon_cs_context *csc = (struct radeon_cs_context*)param;
unsigned i; unsigned i;
if (drmCommandWriteRead(csc->fd, DRM_RADEON_CS, if (drmCommandWriteRead(csc->fd, DRM_RADEON_CS,
@ -381,20 +387,32 @@ static PIPE_THREAD_ROUTINE(radeon_drm_cs_emit_ioctl, param)
p_atomic_dec(&csc->relocs_bo[i]->num_active_ioctls); p_atomic_dec(&csc->relocs_bo[i]->num_active_ioctls);
radeon_cs_context_cleanup(csc); radeon_cs_context_cleanup(csc);
}
static PIPE_THREAD_ROUTINE(radeon_drm_cs_emit_ioctl, param)
{
struct radeon_drm_cs *cs = (struct radeon_drm_cs*)param;
while (1) {
pipe_semaphore_wait(&cs->flush_queued);
if (cs->kill_thread)
break;
radeon_drm_cs_emit_ioctl_oneshot(cs->cst);
pipe_semaphore_signal(&cs->flush_completed);
}
pipe_semaphore_signal(&cs->flush_completed);
return NULL; return NULL;
} }
void radeon_drm_cs_sync_flush(struct radeon_drm_cs *cs) void radeon_drm_cs_sync_flush(struct radeon_drm_cs *cs)
{ {
/* Wait for any pending ioctl to complete. */ /* Wait for any pending ioctl to complete. */
if (cs->thread) { if (cs->thread && cs->flush_started) {
pipe_thread_wait(cs->thread); pipe_semaphore_wait(&cs->flush_completed);
cs->thread = 0; cs->flush_started = 0;
} }
} }
DEBUG_GET_ONCE_BOOL_OPTION(thread, "RADEON_THREAD", TRUE)
static void radeon_drm_cs_flush(struct radeon_winsys_cs *rcs, unsigned flags) static void radeon_drm_cs_flush(struct radeon_winsys_cs *rcs, unsigned flags)
{ {
struct radeon_drm_cs *cs = radeon_drm_cs(rcs); struct radeon_drm_cs *cs = radeon_drm_cs(rcs);
@ -402,33 +420,33 @@ static void radeon_drm_cs_flush(struct radeon_winsys_cs *rcs, unsigned flags)
radeon_drm_cs_sync_flush(cs); radeon_drm_cs_sync_flush(cs);
/* If the CS is not empty, emit it in a newly-spawned thread. */
if (cs->base.cdw) {
unsigned i, crelocs = cs->csc->crelocs;
cs->csc->chunks[0].length_dw = cs->base.cdw;
for (i = 0; i < crelocs; i++) {
/* Update the number of active asynchronous CS ioctls for the buffer. */
p_atomic_inc(&cs->csc->relocs_bo[i]->num_active_ioctls);
}
if (cs->ws->num_cpus > 1 && debug_get_option_thread() &&
(flags & RADEON_FLUSH_ASYNC)) {
cs->thread = pipe_thread_create(radeon_drm_cs_emit_ioctl, cs->csc);
assert(cs->thread);
} else {
radeon_drm_cs_emit_ioctl(cs->csc);
}
} else {
radeon_cs_context_cleanup(cs->csc);
}
/* Flip command streams. */ /* Flip command streams. */
tmp = cs->csc; tmp = cs->csc;
cs->csc = cs->cst; cs->csc = cs->cst;
cs->cst = tmp; cs->cst = tmp;
/* If the CS is not empty, emit it in a separate thread. */
if (cs->base.cdw) {
unsigned i, crelocs = cs->cst->crelocs;
cs->cst->chunks[0].length_dw = cs->base.cdw;
for (i = 0; i < crelocs; i++) {
/* Update the number of active asynchronous CS ioctls for the buffer. */
p_atomic_inc(&cs->cst->relocs_bo[i]->num_active_ioctls);
}
if (cs->thread &&
(flags & RADEON_FLUSH_ASYNC)) {
cs->flush_started = 1;
pipe_semaphore_signal(&cs->flush_queued);
} else {
radeon_drm_cs_emit_ioctl_oneshot(cs->cst);
}
} else {
radeon_cs_context_cleanup(cs->cst);
}
/* Prepare a new CS. */ /* Prepare a new CS. */
cs->base.buf = cs->csc->buf; cs->base.buf = cs->csc->buf;
cs->base.cdw = 0; cs->base.cdw = 0;
@ -438,6 +456,15 @@ static void radeon_drm_cs_destroy(struct radeon_winsys_cs *rcs)
{ {
struct radeon_drm_cs *cs = radeon_drm_cs(rcs); struct radeon_drm_cs *cs = radeon_drm_cs(rcs);
radeon_drm_cs_sync_flush(cs); radeon_drm_cs_sync_flush(cs);
if (cs->thread) {
cs->kill_thread = 1;
pipe_semaphore_signal(&cs->flush_queued);
pipe_semaphore_wait(&cs->flush_completed);
pipe_thread_wait(cs->thread);
pipe_thread_destroy(cs->thread);
}
pipe_semaphore_destroy(&cs->flush_queued);
pipe_semaphore_destroy(&cs->flush_completed);
radeon_cs_context_cleanup(&cs->csc1); radeon_cs_context_cleanup(&cs->csc1);
radeon_cs_context_cleanup(&cs->csc2); radeon_cs_context_cleanup(&cs->csc2);
p_atomic_dec(&cs->ws->num_cs); p_atomic_dec(&cs->ws->num_cs);

View file

@ -75,6 +75,8 @@ struct radeon_drm_cs {
void *flush_data; void *flush_data;
pipe_thread thread; pipe_thread thread;
int flush_started, kill_thread;
pipe_semaphore flush_queued, flush_completed;
}; };
int radeon_get_reloc(struct radeon_cs_context *csc, struct radeon_bo *bo); int radeon_get_reloc(struct radeon_cs_context *csc, struct radeon_bo *bo);