OSDN Git Service

Use krefs for refcounting.
authorKeith Packard <keithp@keithp.com>
Fri, 2 May 2008 03:12:39 +0000 (20:12 -0700)
committerKeith Packard <keithp@keithp.com>
Fri, 2 May 2008 03:12:39 +0000 (20:12 -0700)
krefs are way easier than a custom-coded spinlock+int combo.

linux-core/drmP.h
linux-core/drm_gem.c

index 2ed17b8..0df9f19 100644 (file)
@@ -54,6 +54,7 @@
 #include <linux/smp_lock.h>    /* For (un)lock_kernel */
 #include <linux/dma-mapping.h>
 #include <linux/mm.h>
+#include <linux/kref.h>
 #include <linux/pagemap.h>
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
 #include <linux/mutex.h>
@@ -614,20 +615,21 @@ struct drm_ati_pcigart_info {
  * DRM for its buffer objects.
  */
 struct drm_gem_object {
+       /** Reference count of this object */
+       struct kref refcount;
+
+       /** Related drm device */
+       struct drm_device *dev;
+       
        /** File representing the shmem storage */
        struct file *filp;
 
-       spinlock_t lock;
-
        /**
         * Size of the object, in bytes.  Immutable over the object's
         * lifetime.
         */
        size_t size;
 
-       /** Reference count of this object, protected by object_lock */
-       int refcount;
-
        void *driver_private;
 };
 
index ee3dbe4..d39585e 100644 (file)
@@ -73,13 +73,14 @@ drm_gem_object_alloc(struct drm_device *dev, size_t size)
 
        obj = kcalloc(1, sizeof(*obj), GFP_KERNEL);
 
+       obj->dev = dev;
        obj->filp = shmem_file_setup("drm mm object", size, 0);
        if (IS_ERR(obj->filp)) {
                kfree(obj);
                return NULL;
        }
 
-       obj->refcount = 1;
+       kref_init (&obj->refcount);
        obj->size = size;
 
        if (dev->driver->gem_init_object != NULL &&
@@ -352,27 +353,29 @@ drm_gem_release(struct drm_device *dev, struct drm_file *file_private)
 void
 drm_gem_object_reference(struct drm_device *dev, struct drm_gem_object *obj)
 {
-       spin_lock(&obj->lock);
-       obj->refcount++;
-       spin_unlock(&obj->lock);
+       kref_get(&obj->refcount);
 }
 EXPORT_SYMBOL(drm_gem_object_reference);
 
+static void
+drm_gem_object_free (struct kref *kref)
+{
+       struct drm_gem_object *obj = (struct drm_gem_object *) kref;
+       struct drm_device *dev = obj->dev;
+
+       if (dev->driver->gem_free_object != NULL)
+               dev->driver->gem_free_object(dev, obj);
+
+       fput(obj->filp);
+       kfree(obj);
+}
+
 void
 drm_gem_object_unreference(struct drm_device *dev, struct drm_gem_object *obj)
 {
        if (obj == NULL)
                return;
 
-       spin_lock(&obj->lock);
-       obj->refcount--;
-       spin_unlock(&obj->lock);
-       if (obj->refcount == 0) {
-               if (dev->driver->gem_free_object != NULL)
-                       dev->driver->gem_free_object(dev, obj);
-
-               fput(obj->filp);
-               kfree(obj);
-       }
+       kref_put (&obj->refcount, drm_gem_object_free);
 }
 EXPORT_SYMBOL(drm_gem_object_unreference);