From 0d7ad7e43ca212b1e9f16cd18f36493cab455e61 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 20 Oct 2009 14:19:38 -0700 Subject: intel: Only call clock_gettime once per unreference_final. Notably when freeing a batchbuffer, we often end up freeing many of the buffers it points at as well. Avoiding repeated calls brings us a 9% CPU win for cairo-gl. [ # ] backend test min(s) median(s) stddev. count before: [ 0] gl firefox-talos-gfx 58.941 58.966 0.75% 3/3 after: [ 0] gl firefox-talos-gfx 54.186 54.195 0.49% 3/3 --- libdrm/intel/intel_bufmgr_gem.c | 47 ++++++++++++++++++++++++++++------------- 1 file changed, 32 insertions(+), 15 deletions(-) (limited to 'libdrm') diff --git a/libdrm/intel/intel_bufmgr_gem.c b/libdrm/intel/intel_bufmgr_gem.c index 739c99bd..87795f33 100644 --- a/libdrm/intel/intel_bufmgr_gem.c +++ b/libdrm/intel/intel_bufmgr_gem.c @@ -188,6 +188,8 @@ drm_intel_gem_bo_set_tiling(drm_intel_bo *bo, uint32_t * tiling_mode, uint32_t stride); static void drm_intel_gem_bo_unreference_locked(drm_intel_bo *bo); +static void drm_intel_gem_bo_unreference_locked_timed(drm_intel_bo *bo, + time_t time); static void drm_intel_gem_bo_unreference(drm_intel_bo *bo); @@ -708,20 +710,20 @@ drm_intel_gem_cleanup_bo_cache(drm_intel_bufmgr_gem *bufmgr_gem, time_t time) } } -static void drm_intel_gem_bo_unreference_final(drm_intel_bo *bo) +static void +drm_intel_gem_bo_unreference_final(drm_intel_bo *bo, time_t time) { drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr; drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; struct drm_intel_gem_bo_bucket *bucket; uint32_t tiling_mode; + int i; - if (bo_gem->relocs != NULL) { - int i; - - /* Unreference all the target buffers */ - for (i = 0; i < bo_gem->reloc_count; i++) - drm_intel_gem_bo_unreference_locked(bo_gem-> - reloc_target_bo[i]); + /* Unreference all the target buffers */ + for (i = 0; i < bo_gem->reloc_count; i++) { + drm_intel_gem_bo_unreference_locked_timed(bo_gem-> + reloc_target_bo[i], + time); } DBG("bo_unreference final: %d (%s)\n", @@ -732,10 +734,7 @@ static void drm_intel_gem_bo_unreference_final(drm_intel_bo *bo) tiling_mode = I915_TILING_NONE; if (bufmgr_gem->bo_reuse && bo_gem->reusable && bucket != NULL && drm_intel_gem_bo_set_tiling(bo, &tiling_mode, 0) == 0) { - struct timespec time; - - clock_gettime(CLOCK_MONOTONIC, &time); - bo_gem->free_time = time.tv_sec; + bo_gem->free_time = time; bo_gem->name = NULL; bo_gem->validate_index = -1; @@ -745,7 +744,7 @@ static void drm_intel_gem_bo_unreference_final(drm_intel_bo *bo) drm_intel_gem_bo_madvise(bufmgr_gem, bo_gem, I915_MADV_DONTNEED); - drm_intel_gem_cleanup_bo_cache(bufmgr_gem, time.tv_sec); + drm_intel_gem_cleanup_bo_cache(bufmgr_gem, time); } else { drm_intel_gem_bo_free(bo); } @@ -755,9 +754,23 @@ static void drm_intel_gem_bo_unreference_locked(drm_intel_bo *bo) { drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; + assert(atomic_read(&bo_gem->refcount) > 0); + if (atomic_dec_and_test(&bo_gem->refcount)) { + struct timespec time; + + clock_gettime(CLOCK_MONOTONIC, &time); + drm_intel_gem_bo_unreference_final(bo, time.tv_sec); + } +} + +static void drm_intel_gem_bo_unreference_locked_timed(drm_intel_bo *bo, + time_t time) +{ + drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; + assert(atomic_read(&bo_gem->refcount) > 0); if (atomic_dec_and_test(&bo_gem->refcount)) - drm_intel_gem_bo_unreference_final(bo); + drm_intel_gem_bo_unreference_final(bo, time); } static void drm_intel_gem_bo_unreference(drm_intel_bo *bo) @@ -768,8 +781,12 @@ static void drm_intel_gem_bo_unreference(drm_intel_bo *bo) if (atomic_dec_and_test(&bo_gem->refcount)) { drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr; + struct timespec time; + + clock_gettime(CLOCK_MONOTONIC, &time); + pthread_mutex_lock(&bufmgr_gem->lock); - drm_intel_gem_bo_unreference_final(bo); + drm_intel_gem_bo_unreference_final(bo, time.tv_sec); pthread_mutex_unlock(&bufmgr_gem->lock); } } -- cgit v1.2.3