/** * This is the thread's main entrypoint. * It's a simple loop: * 1. wait for work * 2. do work * 3. signal that we're done */ static PIPE_THREAD_ROUTINE( thread_function, init_data ) { struct lp_rasterizer_task *task = (struct lp_rasterizer_task *) init_data; struct lp_rasterizer *rast = task->rast; boolean debug = false; while (1) { /* wait for work */ if (debug) debug_printf("thread %d waiting for work\n", task->thread_index); pipe_semaphore_wait(&task->work_ready); if (rast->exit_flag) break; if (task->thread_index == 0) { /* thread[0]: * - get next scene to rasterize * - map the framebuffer surfaces */ lp_rast_begin( rast, lp_scene_dequeue( rast->full_scenes, TRUE ) ); } /* Wait for all threads to get here so that threads[1+] don't * get a null rast->curr_scene pointer. */ pipe_barrier_wait( &rast->barrier ); /* do work */ if (debug) debug_printf("thread %d doing work\n", task->thread_index); rasterize_scene(task, rast->curr_scene); /* wait for all threads to finish with this scene */ pipe_barrier_wait( &rast->barrier ); /* XXX: shouldn't be necessary: */ if (task->thread_index == 0) { lp_rast_end( rast ); } /* signal done with work */ if (debug) debug_printf("thread %d done working\n", task->thread_index); pipe_semaphore_signal(&task->work_done); } return NULL; }
void radeon_drm_ws_queue_cs(struct radeon_drm_winsys *ws, struct radeon_drm_cs *cs) { retry: pipe_mutex_lock(ws->cs_stack_lock); if (ws->ncs >= RING_LAST) { /* no room left for a flush */ pipe_mutex_unlock(ws->cs_stack_lock); goto retry; } ws->cs_stack[ws->ncs++] = cs; pipe_mutex_unlock(ws->cs_stack_lock); pipe_semaphore_signal(&ws->cs_queued); }
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; pipe_semaphore_wait(&queue->queued); if (queue->kill_thread) 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; pipe_mutex_unlock(queue->lock); pipe_semaphore_signal(&queue->has_space); if (job.job) { queue->execute_job(job.job); pipe_semaphore_signal(&job.fence->done); } } /* 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; } queue->num_jobs = 0; pipe_mutex_unlock(queue->lock); return 0; }
static void radeon_drm_cs_flush(struct radeon_winsys_cs *rcs, unsigned flags) { struct radeon_drm_cs *cs = radeon_drm_cs(rcs); struct radeon_cs_context *tmp; radeon_drm_cs_sync_flush(cs); /* Flip command streams. */ tmp = cs->csc; cs->csc = cs->cst; 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 (flags & RADEON_FLUSH_KEEP_TILING_FLAGS) { cs->cst->cs.num_chunks = 3; cs->cst->flags = RADEON_CS_KEEP_TILING_FLAGS; } else { cs->cst->cs.num_chunks = 2; } 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. */ cs->base.buf = cs->csc->buf; cs->base.cdw = 0; }
void util_queue_add_job(struct util_queue *queue, void *job, struct util_queue_fence *fence) { /* Set the semaphore to "busy". */ pipe_semaphore_wait(&fence->done); /* if the queue is full, wait until there is space */ 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++; pipe_mutex_unlock(queue->lock); pipe_semaphore_signal(&queue->queued); }
static void radeon_drm_cs_destroy(struct radeon_winsys_cs *rcs) { struct radeon_drm_cs *cs = radeon_drm_cs(rcs); 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_semaphore_destroy(&cs->flush_queued); pipe_semaphore_destroy(&cs->flush_completed); radeon_cs_context_cleanup(&cs->csc1); radeon_cs_context_cleanup(&cs->csc2); p_atomic_dec(&cs->ws->num_cs); radeon_destroy_cs_context(&cs->csc1); radeon_destroy_cs_context(&cs->csc2); FREE(cs); }
/* Shutdown: */ void lp_rast_destroy( struct lp_rasterizer *rast ) { unsigned i; /* Set exit_flag and signal each thread's work_ready semaphore. * Each thread will be woken up, notice that the exit_flag is set and * break out of its main loop. The thread will then exit. */ rast->exit_flag = TRUE; for (i = 0; i < rast->num_threads; i++) { pipe_semaphore_signal(&rast->tasks[i].work_ready); } /* Wait for threads to terminate before cleaning up per-thread data. * We don't actually call pipe_thread_wait to avoid dead lock on Windows * per https://bugs.freedesktop.org/show_bug.cgi?id=76252 */ for (i = 0; i < rast->num_threads; i++) { #ifdef _WIN32 pipe_semaphore_wait(&rast->tasks[i].work_done); #else thrd_join(rast->threads[i], NULL); #endif } /* Clean up per-thread data */ for (i = 0; i < rast->num_threads; i++) { pipe_semaphore_destroy(&rast->tasks[i].work_ready); pipe_semaphore_destroy(&rast->tasks[i].work_done); } for (i = 0; i < MAX2(1, rast->num_threads); i++) { align_free(rast->tasks[i].thread_data.cache); } /* for synchronizing rasterization threads */ if (rast->num_threads > 0) { pipe_barrier_destroy( &rast->barrier ); } lp_scene_queue_destroy(rast->full_scenes); FREE(rast); }
/** * Called by setup module when it has something for us to render. */ void lp_rast_queue_scene( struct lp_rasterizer *rast, struct lp_scene *scene) { LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__); if (rast->num_threads == 0) { /* no threading */ unsigned fpstate = util_fpstate_get(); /* Make sure that denorms are treated like zeros. This is * the behavior required by D3D10. OpenGL doesn't care. */ util_fpstate_set_denorms_to_zero(fpstate); lp_rast_begin( rast, scene ); rasterize_scene( &rast->tasks[0], scene ); lp_rast_end( rast ); util_fpstate_set(fpstate); rast->curr_scene = NULL; } else { /* threaded rendering! */ unsigned i; lp_scene_enqueue( rast->full_scenes, scene ); /* signal the threads that there's work to do */ for (i = 0; i < rast->num_threads; i++) { pipe_semaphore_signal(&rast->tasks[i].work_ready); } } LP_DBG(DEBUG_SETUP, "%s done \n", __FUNCTION__); }
static void radeon_winsys_destroy(struct radeon_winsys *rws) { struct radeon_drm_winsys *ws = (struct radeon_drm_winsys*)rws; if (ws->thread) { ws->kill_thread = 1; pipe_semaphore_signal(&ws->cs_queued); pipe_thread_wait(ws->thread); } pipe_semaphore_destroy(&ws->cs_queued); pipe_mutex_destroy(ws->hyperz_owner_mutex); pipe_mutex_destroy(ws->cmask_owner_mutex); pipe_mutex_destroy(ws->cs_stack_lock); ws->cman->destroy(ws->cman); ws->kman->destroy(ws->kman); if (ws->gen >= DRV_R600) { radeon_surface_manager_free(ws->surf_man); } FREE(rws); }
/** * This is the thread's main entrypoint. * It's a simple loop: * 1. wait for work * 2. do work * 3. signal that we're done */ static int thread_function(void *init_data) { struct lp_rasterizer_task *task = (struct lp_rasterizer_task *) init_data; struct lp_rasterizer *rast = task->rast; boolean debug = false; char thread_name[16]; unsigned fpstate; util_snprintf(thread_name, sizeof thread_name, "llvmpipe-%u", task->thread_index); u_thread_setname(thread_name); /* Make sure that denorms are treated like zeros. This is * the behavior required by D3D10. OpenGL doesn't care. */ fpstate = util_fpstate_get(); util_fpstate_set_denorms_to_zero(fpstate); while (1) { /* wait for work */ if (debug) debug_printf("thread %d waiting for work\n", task->thread_index); pipe_semaphore_wait(&task->work_ready); if (rast->exit_flag) break; if (task->thread_index == 0) { /* thread[0]: * - get next scene to rasterize * - map the framebuffer surfaces */ lp_rast_begin( rast, lp_scene_dequeue( rast->full_scenes, TRUE ) ); } /* Wait for all threads to get here so that threads[1+] don't * get a null rast->curr_scene pointer. */ pipe_barrier_wait( &rast->barrier ); /* do work */ if (debug) debug_printf("thread %d doing work\n", task->thread_index); rasterize_scene(task, rast->curr_scene); /* wait for all threads to finish with this scene */ pipe_barrier_wait( &rast->barrier ); /* XXX: shouldn't be necessary: */ if (task->thread_index == 0) { lp_rast_end( rast ); } /* signal done with work */ if (debug) debug_printf("thread %d done working\n", task->thread_index); pipe_semaphore_signal(&task->work_done); } #ifdef _WIN32 pipe_semaphore_signal(&task->work_done); #endif return 0; }