diff options
author | Dave Airlie <airlied@redhat.com> | 2010-09-27 02:17:17 -0400 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2010-09-30 19:17:44 -0400 |
commit | 29d08b3efddca628b0360411ab2b85f7b1723f48 (patch) | |
tree | f89a8a3069ebe9828b8a08c4b123f52625bf0bc7 /include/drm | |
parent | 130b9851933e6da636502cd85e1ba8f45f862e8c (diff) |
drm/gem: handlecount isn't really a kref so don't make it one.
There were lots of places being inconsistent since handle count
looked like a kref but it really wasn't.
Fix this my just making handle count an atomic on the object,
and have it increase the normal object kref.
Now i915/radeon/nouveau drivers can drop the normal reference on
userspace object creation, and have the handle hold it.
This patch fixes a memory leak or corruption on unload, because
the driver had no way of knowing if a handle had been actually
added for this object, and the fbcon object needed to know this
to clean itself up properly.
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'include/drm')
-rw-r--r-- | include/drm/drmP.h | 18 |
1 files changed, 13 insertions, 5 deletions
diff --git a/include/drm/drmP.h b/include/drm/drmP.h index 774e1d49509b..07e4726a4ee0 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h | |||
@@ -612,7 +612,7 @@ struct drm_gem_object { | |||
612 | struct kref refcount; | 612 | struct kref refcount; |
613 | 613 | ||
614 | /** Handle count of this object. Each handle also holds a reference */ | 614 | /** Handle count of this object. Each handle also holds a reference */ |
615 | struct kref handlecount; | 615 | atomic_t handle_count; /* number of handles on this object */ |
616 | 616 | ||
617 | /** Related drm device */ | 617 | /** Related drm device */ |
618 | struct drm_device *dev; | 618 | struct drm_device *dev; |
@@ -1461,7 +1461,7 @@ struct drm_gem_object *drm_gem_object_alloc(struct drm_device *dev, | |||
1461 | size_t size); | 1461 | size_t size); |
1462 | int drm_gem_object_init(struct drm_device *dev, | 1462 | int drm_gem_object_init(struct drm_device *dev, |
1463 | struct drm_gem_object *obj, size_t size); | 1463 | struct drm_gem_object *obj, size_t size); |
1464 | void drm_gem_object_handle_free(struct kref *kref); | 1464 | void drm_gem_object_handle_free(struct drm_gem_object *obj); |
1465 | void drm_gem_vm_open(struct vm_area_struct *vma); | 1465 | void drm_gem_vm_open(struct vm_area_struct *vma); |
1466 | void drm_gem_vm_close(struct vm_area_struct *vma); | 1466 | void drm_gem_vm_close(struct vm_area_struct *vma); |
1467 | int drm_gem_mmap(struct file *filp, struct vm_area_struct *vma); | 1467 | int drm_gem_mmap(struct file *filp, struct vm_area_struct *vma); |
@@ -1496,7 +1496,7 @@ static inline void | |||
1496 | drm_gem_object_handle_reference(struct drm_gem_object *obj) | 1496 | drm_gem_object_handle_reference(struct drm_gem_object *obj) |
1497 | { | 1497 | { |
1498 | drm_gem_object_reference(obj); | 1498 | drm_gem_object_reference(obj); |
1499 | kref_get(&obj->handlecount); | 1499 | atomic_inc(&obj->handle_count); |
1500 | } | 1500 | } |
1501 | 1501 | ||
1502 | static inline void | 1502 | static inline void |
@@ -1505,12 +1505,15 @@ drm_gem_object_handle_unreference(struct drm_gem_object *obj) | |||
1505 | if (obj == NULL) | 1505 | if (obj == NULL) |
1506 | return; | 1506 | return; |
1507 | 1507 | ||
1508 | if (atomic_read(&obj->handle_count) == 0) | ||
1509 | return; | ||
1508 | /* | 1510 | /* |
1509 | * Must bump handle count first as this may be the last | 1511 | * Must bump handle count first as this may be the last |
1510 | * ref, in which case the object would disappear before we | 1512 | * ref, in which case the object would disappear before we |
1511 | * checked for a name | 1513 | * checked for a name |
1512 | */ | 1514 | */ |
1513 | kref_put(&obj->handlecount, drm_gem_object_handle_free); | 1515 | if (atomic_dec_and_test(&obj->handle_count)) |
1516 | drm_gem_object_handle_free(obj); | ||
1514 | drm_gem_object_unreference(obj); | 1517 | drm_gem_object_unreference(obj); |
1515 | } | 1518 | } |
1516 | 1519 | ||
@@ -1520,12 +1523,17 @@ drm_gem_object_handle_unreference_unlocked(struct drm_gem_object *obj) | |||
1520 | if (obj == NULL) | 1523 | if (obj == NULL) |
1521 | return; | 1524 | return; |
1522 | 1525 | ||
1526 | if (atomic_read(&obj->handle_count) == 0) | ||
1527 | return; | ||
1528 | |||
1523 | /* | 1529 | /* |
1524 | * Must bump handle count first as this may be the last | 1530 | * Must bump handle count first as this may be the last |
1525 | * ref, in which case the object would disappear before we | 1531 | * ref, in which case the object would disappear before we |
1526 | * checked for a name | 1532 | * checked for a name |
1527 | */ | 1533 | */ |
1528 | kref_put(&obj->handlecount, drm_gem_object_handle_free); | 1534 | |
1535 | if (atomic_dec_and_test(&obj->handle_count)) | ||
1536 | drm_gem_object_handle_free(obj); | ||
1529 | drm_gem_object_unreference_unlocked(obj); | 1537 | drm_gem_object_unreference_unlocked(obj); |
1530 | } | 1538 | } |
1531 | 1539 | ||