[PATCH 2/2] drm/ttm: Optimize delayed buffer destruction
Dave Airlie
airlied at gmail.com
Mon Oct 18 20:57:32 PDT 2010
On Thu, Oct 14, 2010 at 3:18 AM, Thomas Hellstrom <thellstrom at vmware.com> wrote:
> This commit replaces the ttm_bo_cleanup_ref function with two new functions.
> One for the case where the bo is not yet on the delayed destroy list, and
> one for the case where the bo was on the delayed destroy list, at least at
> the time of call. This makes it possible to optimize the two cases somewhat.
I tried booting this today, but on radeon starting X hit a recursive
spin lock on the lru lock.
(annotated below)
> + *
> + * @interruptible Any sleeps should occur interruptibly.
> + * @no_wait_reserve Never wait for reserve. Return -EBUSY instead.
> + * @no_wait_gpu Never wait for gpu. Return -EBUSY instead.
> + */
> +
> +static int ttm_bo_cleanup_refs(struct ttm_buffer_object *bo,
> + bool interruptible,
> + bool no_wait_reserve,
> + bool no_wait_gpu)
> +{
> + struct ttm_bo_global *glob = bo->glob;
> + int put_count;
> + int ret = 0;
> +
> +retry:
> + spin_lock(&bo->lock);
> + ret = ttm_bo_wait(bo, false, interruptible, no_wait_gpu);
> + spin_unlock(&bo->lock);
> +
> + if (unlikely(ret != 0))
> + return ret;
> +
> spin_lock(&glob->lru_lock);
^^ take LRU lock
> - if (list_empty(&bo->ddestroy)) {
> - void *sync_obj = bo->sync_obj;
> - void *sync_obj_arg = bo->sync_obj_arg;
> + ret = ttm_bo_reserve_locked(bo, interruptible,
> + no_wait_reserve, false, 0);
>
> - kref_get(&bo->list_kref);
> - list_add_tail(&bo->ddestroy, &bdev->ddestroy);
> + if (unlikely(ret != 0) || list_empty(&bo->ddestroy)) {
> spin_unlock(&glob->lru_lock);
^^ drop in error path.
> - spin_unlock(&bo->lock);
> + return ret;
> + }
>
> - if (sync_obj)
> - driver->sync_obj_flush(sync_obj, sync_obj_arg);
> - schedule_delayed_work(&bdev->wq,
> - ((HZ / 100) < 1) ? 1 : HZ / 100);
> - ret = 0;
> + /**
> + * We can re-check for sync object without taking
> + * the bo::lock since setting the sync object requires
> + * also bo::reserved. A busy object at this point may
> + * be caused by another thread recently starting an accelerated
> + * eviction.
> + */
>
> - } else {
> + if (unlikely(bo->sync_obj)) {
> + atomic_set(&bo->reserved, 0);
> + wake_up_all(&bo->event_queue);
> spin_unlock(&glob->lru_lock);
^^ drop for retry path.
> - spin_unlock(&bo->lock);
> - ret = -EBUSY;
> + goto retry;
> }
>
> - return ret;
> + put_count = ttm_bo_del_from_lru(bo);
> + list_del_init(&bo->ddestroy);
> + ++put_count;
> +
> + ttm_bo_cleanup_memtype_use(bo);
^^ get into cleanup_memtype_use, which calls the ttm_bo_mem_put which
tries to take the lru lock inside
ttm_bo_man_put_node
Dave.
More information about the dri-devel
mailing list