If we enable RCU for the requests (providing a grace period where we can inspect a "dead" request before it is freed), we can allow callers to carefully perform lockless lookup of an active request. However, by enabling deferred freeing of requests, we can potentially hog a lot of memory when dealing with tens of thousands of requests per second - with a quick insertion of the a synchronize_rcu() inside our shrinker callback, that issue disappears. Signed-off-by: Chris Wilson <chris@xxxxxxxxxxxxxxxxxx> --- drivers/gpu/drm/i915/i915_gem.c | 3 ++- drivers/gpu/drm/i915/i915_gem_request.c | 2 +- drivers/gpu/drm/i915/i915_gem_request.h | 24 +++++++++++++++++++++++- drivers/gpu/drm/i915/i915_gem_shrinker.c | 1 + 4 files changed, 27 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index c169574758d5..696ada3891ed 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -4222,7 +4222,8 @@ i915_gem_load(struct drm_device *dev) dev_priv->requests = kmem_cache_create("i915_gem_request", sizeof(struct drm_i915_gem_request), 0, - SLAB_HWCACHE_ALIGN, + SLAB_HWCACHE_ALIGN | + SLAB_DESTROY_BY_RCU, NULL); INIT_LIST_HEAD(&dev_priv->context_list); diff --git a/drivers/gpu/drm/i915/i915_gem_request.c b/drivers/gpu/drm/i915/i915_gem_request.c index 4e087143b1d2..380a5963d957 100644 --- a/drivers/gpu/drm/i915/i915_gem_request.c +++ b/drivers/gpu/drm/i915/i915_gem_request.c @@ -335,7 +335,7 @@ static void __i915_gem_request_retire_active(struct drm_i915_gem_request *req) * and pass along the auxiliary information. */ INIT_LIST_HEAD(&active->link); - active->request = NULL; + rcu_assign_pointer(active->request, NULL); active->retire(active, req); } diff --git a/drivers/gpu/drm/i915/i915_gem_request.h b/drivers/gpu/drm/i915/i915_gem_request.h index 4eb15ed9205e..fae85b111a1e 100644 --- a/drivers/gpu/drm/i915/i915_gem_request.h +++ b/drivers/gpu/drm/i915/i915_gem_request.h @@ -139,6 +139,12 @@ i915_gem_request_get(struct drm_i915_gem_request *req) return to_request(fence_get(&req->fence)); } +static inline struct drm_i915_gem_request * +i915_gem_request_get_rcu(struct drm_i915_gem_request *req) +{ + return to_request(fence_get_rcu(&req->fence)); +} + static inline void i915_gem_request_put(struct drm_i915_gem_request *req) { @@ -243,7 +249,23 @@ i915_gem_request_mark_active(struct drm_i915_gem_request *request, struct i915_gem_active *active) { list_move(&active->link, &request->active_list); - active->request = request; + rcu_assign_pointer(active->request, request); +} + +static inline struct drm_i915_gem_request * +i915_gem_active_get_request_rcu(struct i915_gem_active *active) +{ + do { + struct drm_i915_gem_request *request; + + request = rcu_dereference(active->request); + if (request == NULL) + return NULL; + + request = i915_gem_request_get_rcu(request); + if (request) + return request; + } while (1); } #endif /* I915_GEM_REQUEST_H */ diff --git a/drivers/gpu/drm/i915/i915_gem_shrinker.c b/drivers/gpu/drm/i915/i915_gem_shrinker.c index c561ed2b8287..03a8bbb3e31e 100644 --- a/drivers/gpu/drm/i915/i915_gem_shrinker.c +++ b/drivers/gpu/drm/i915/i915_gem_shrinker.c @@ -142,6 +142,7 @@ i915_gem_shrink(struct drm_i915_private *dev_priv, } i915_gem_retire_requests(dev_priv->dev); + synchronize_rcu(); /* expedite the grace period to free the requests */ return count; } -- 2.6.4 _______________________________________________ Intel-gfx mailing list Intel-gfx@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/intel-gfx