intel: Leak the userptr test bo

In order to use userptr, the kernel tracks the owner's mm with a
mmu_notifier. Setting that is very expensive - it involves taking all
mm_locks and a stop_machine(). This tracking lives only for as long as
the client is using userptr objects - so if the client allocates then
frees a userptr in a loop, we will be executing that heavyweight setup
everytime. To ammoritize this cost, just leak the test bo and the single
backing page we use for detecting userptr.

v2: Free the object and memory when bufmgr is destroyed.

Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
Cc: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Damien Lespiau <damien.lespiau@intel.com>
This commit is contained in:
Tvrtko Ursulin 2015-04-17 11:57:28 +01:00 committed by Damien Lespiau
parent 9915e68b3b
commit 30921483c7

View file

@ -132,6 +132,11 @@ typedef struct _drm_intel_bufmgr_gem {
unsigned int has_vebox : 1; unsigned int has_vebox : 1;
bool fenced_relocs; bool fenced_relocs;
struct {
void *ptr;
uint32_t handle;
} userptr_active;
char *aub_filename; char *aub_filename;
FILE *aub_file; FILE *aub_file;
uint32_t aub_offset; uint32_t aub_offset;
@ -943,7 +948,6 @@ has_userptr(drm_intel_bufmgr_gem *bufmgr_gem)
void *ptr; void *ptr;
long pgsz; long pgsz;
struct drm_i915_gem_userptr userptr; struct drm_i915_gem_userptr userptr;
struct drm_gem_close close_bo;
pgsz = sysconf(_SC_PAGESIZE); pgsz = sysconf(_SC_PAGESIZE);
assert(pgsz > 0); assert(pgsz > 0);
@ -970,15 +974,15 @@ retry:
return false; return false;
} }
memclear(close_bo); /* We don't release the userptr bo here as we want to keep the
close_bo.handle = userptr.handle; * kernel mm tracking alive for our lifetime. The first time we
ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_GEM_CLOSE, &close_bo); * create a userptr object the kernel has to install a mmu_notifer
free(ptr); * which is a heavyweight operation (e.g. it requires taking all
if (ret) { * mm_locks and stop_machine()).
fprintf(stderr, "Failed to release test userptr object! (%d) " */
"i915 kernel driver may not be sane!\n", errno);
return false; bufmgr_gem->userptr_active.ptr = ptr;
} bufmgr_gem->userptr_active.handle = userptr.handle;
return true; return true;
} }
@ -1805,7 +1809,8 @@ static void
drm_intel_bufmgr_gem_destroy(drm_intel_bufmgr *bufmgr) drm_intel_bufmgr_gem_destroy(drm_intel_bufmgr *bufmgr)
{ {
drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bufmgr; drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bufmgr;
int i; struct drm_gem_close close_bo;
int i, ret;
free(bufmgr_gem->exec2_objects); free(bufmgr_gem->exec2_objects);
free(bufmgr_gem->exec_objects); free(bufmgr_gem->exec_objects);
@ -1829,6 +1834,18 @@ drm_intel_bufmgr_gem_destroy(drm_intel_bufmgr *bufmgr)
} }
} }
/* Release userptr bo kept hanging around for optimisation. */
if (bufmgr_gem->userptr_active.ptr) {
memclear(close_bo);
close_bo.handle = bufmgr_gem->userptr_active.handle;
ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_GEM_CLOSE, &close_bo);
free(bufmgr_gem->userptr_active.ptr);
if (ret)
fprintf(stderr,
"Failed to release test userptr object! (%d) "
"i915 kernel driver may not be sane!\n", errno);
}
free(bufmgr); free(bufmgr);
} }