summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRafał Sapała <rafal.a.sapala@intel.com>2015-07-24 11:22:34 +0200
committerDamien Lespiau <damien.lespiau@intel.com>2015-08-21 14:43:23 +0100
commitcf40cf05a4d7f3945d534790e7768a048adc3ab0 (patch)
tree2013d4f51df7c8426bd89c880c75b4e92875e40d
parent6e84ada4ccf604c32a008fc20c00d79302135601 (diff)
intel: Serialize drmPrimeFDToHandle with struct_mutex
It is possible to hit a race condition in create_from_prime, when trying to import a BO that's currently being freed. In case of prime sharing we'll succesfully get a handle, but fail on get_tiling call, potentially confusing the caller (and requiring different locking scheme than with sharing using flink). Wrap fd_to_handle with struct_mutex to force a more consistent behaviour between prime/flink, convert fprintf to DBG when handling errors. (From Chris: The race is that the kernel returns us the same file-private handle as the first thread, but that first thread is about to call gem_close (thereby removing the handle from the file completely) and does so between us acquiring the handle and taking the mutex. If we take the mutex, then we acquire the refcnt on the bo prior to the first thread completing its unref (and so preventing the early close). Or we acquire the handle after the earlier close, in which case we are the new owner. ) Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk> Testcase: igt/drm_import_export/import-close-race-prime Signed-off-by: Rafał Sapała <rafal.a.sapala@intel.com> Signed-off-by: Michał Winiarski <michal.winiarski@intel.com>
-rw-r--r--intel/intel_bufmgr_gem.c14
1 files changed, 7 insertions, 7 deletions
diff --git a/intel/intel_bufmgr_gem.c b/intel/intel_bufmgr_gem.c
index 41de396b..2723e21b 100644
--- a/intel/intel_bufmgr_gem.c
+++ b/intel/intel_bufmgr_gem.c
@@ -2428,14 +2428,19 @@ drm_intel_bo_gem_create_from_prime(drm_intel_bufmgr *bufmgr, int prime_fd, int s
struct drm_i915_gem_get_tiling get_tiling;
drmMMListHead *list;
+ pthread_mutex_lock(&bufmgr_gem->lock);
ret = drmPrimeFDToHandle(bufmgr_gem->fd, prime_fd, &handle);
+ if (ret) {
+ DBG("create_from_prime: failed to obtain handle from fd: %s\n", strerror(errno));
+ pthread_mutex_unlock(&bufmgr_gem->lock);
+ return NULL;
+ }
/*
* See if the kernel has already returned this buffer to us. Just as
* for named buffers, we must not create two bo's pointing at the same
* kernel object
*/
- pthread_mutex_lock(&bufmgr_gem->lock);
for (list = bufmgr_gem->named.next;
list != &bufmgr_gem->named;
list = list->next) {
@@ -2447,12 +2452,6 @@ drm_intel_bo_gem_create_from_prime(drm_intel_bufmgr *bufmgr, int prime_fd, int s
}
}
- if (ret) {
- fprintf(stderr,"ret is %d %d\n", ret, errno);
- pthread_mutex_unlock(&bufmgr_gem->lock);
- return NULL;
- }
-
bo_gem = calloc(1, sizeof(*bo_gem));
if (!bo_gem) {
pthread_mutex_unlock(&bufmgr_gem->lock);
@@ -2493,6 +2492,7 @@ drm_intel_bo_gem_create_from_prime(drm_intel_bufmgr *bufmgr, int prime_fd, int s
DRM_IOCTL_I915_GEM_GET_TILING,
&get_tiling);
if (ret != 0) {
+ DBG("create_from_prime: failed to get tiling: %s\n", strerror(errno));
drm_intel_gem_bo_unreference(&bo_gem->bo);
return NULL;
}