drm_ctx_dtor.patch Submitted by: Erdi Chen
authorKeith Whitwell <keith@tungstengraphics.com>
Fri, 20 Feb 2004 22:55:12 +0000 (22:55 +0000)
committerKeith Whitwell <keith@tungstengraphics.com>
Fri, 20 Feb 2004 22:55:12 +0000 (22:55 +0000)
linux-core/drmP.h
linux-core/drm_context.c
linux-core/drm_drv.c
linux-core/drm_memory_debug.h
linux/drmP.h
linux/drm_context.h
linux/drm_drv.h
linux/drm_memory_debug.h

index b7b346d..742c4ac 100644 (file)
 #define DRM_MEM_CTXBITMAP 18
 #define DRM_MEM_STUB      19
 #define DRM_MEM_SGLISTS   20
+#define DRM_MEM_CTXLIST  21
 
 #define DRM_MAX_CTXBITMAP (PAGE_SIZE * 8)
        
@@ -651,6 +652,15 @@ typedef struct drm_map_list {
 
 typedef drm_map_t drm_local_map_t;
 
+/**
+ * Context handle list
+ */
+typedef struct drm_ctx_list {
+       struct list_head        head;   /**< list head */
+       drm_context_t           handle; /**< context handle */
+       drm_file_t              *tag;   /**< associated fd private data */
+} drm_ctx_list_t;
+
 #if __HAVE_VBL_IRQ
 
 typedef struct drm_vbl_sig {
@@ -711,6 +721,12 @@ typedef struct drm_device {
        drm_map_list_t    *maplist;     /**< Linked list of regions */
        int               map_count;    /**< Number of mappable regions */
 
+       /** \name Context handle management */
+       /*@{*/
+       drm_ctx_list_t    *ctxlist;     /**< Linked list of context handles */
+       int               ctx_count;    /**< Number of context handles */
+       struct semaphore  ctxlist_sem;  /**< For ctxlist */
+
        drm_map_t         **context_sareas; /**< per-context SAREA's */
        int               max_context;
 
index 82e90bc..474b5ba 100644 (file)
@@ -402,6 +402,7 @@ int DRM(addctx)( struct inode *inode, struct file *filp,
 {
        drm_file_t *priv = filp->private_data;
        drm_device_t *dev = priv->dev;
+       drm_ctx_list_t * ctx_entry;
        drm_ctx_t ctx;
 
        if ( copy_from_user( &ctx, (drm_ctx_t *)arg, sizeof(ctx) ) )
@@ -422,6 +423,20 @@ int DRM(addctx)( struct inode *inode, struct file *filp,
        if ( ctx.handle != DRM_KERNEL_CONTEXT )
                DRIVER_CTX_CTOR(ctx.handle); /* XXX: also pass dev ? */
 #endif
+       ctx_entry = DRM(alloc)( sizeof(*ctx_entry), DRM_MEM_CTXLIST );
+       if ( !ctx_entry ) {
+               DRM_DEBUG("out of memory\n");
+               return -ENOMEM;
+       }
+
+       INIT_LIST_HEAD( &ctx_entry->head );
+       ctx_entry->handle = ctx.handle;
+       ctx_entry->tag = priv;
+
+       down( &dev->ctxlist_sem );
+       list_add( &ctx_entry->head, &dev->ctxlist->head );
+       ++dev->ctx_count;
+       up( &dev->ctxlist_sem );
 
        if ( copy_to_user( (drm_ctx_t *)arg, &ctx, sizeof(ctx) ) )
                return -EFAULT;
@@ -544,6 +559,20 @@ int DRM(rmctx)( struct inode *inode, struct file *filp,
                DRM(ctxbitmap_free)( dev, ctx.handle );
        }
 
+       down( &dev->ctxlist_sem );
+       if ( !list_empty( &dev->ctxlist->head ) ) {
+               drm_ctx_list_t *pos, *n;
+
+               list_for_each_entry_safe( pos, n, &dev->ctxlist->head, head ) {
+                       if ( pos->handle == ctx.handle ) {
+                               list_del( &pos->head );
+                               DRM(free)( pos, sizeof(*pos), DRM_MEM_CTXLIST );
+                               --dev->ctx_count;
+                       }
+               }
+       }
+       up( &dev->ctxlist_sem );
+
        return 0;
 }
 
index d0dceaa..3eec29a 100644 (file)
@@ -329,6 +329,12 @@ static int DRM(setup)( drm_device_t *dev )
        memset(dev->maplist, 0, sizeof(*dev->maplist));
        INIT_LIST_HEAD(&dev->maplist->head);
 
+       dev->ctxlist = DRM(alloc)(sizeof(*dev->ctxlist),
+                                 DRM_MEM_CTXLIST);
+       if(dev->ctxlist == NULL) return -ENOMEM;
+       memset(dev->ctxlist, 0, sizeof(*dev->ctxlist));
+       INIT_LIST_HEAD(&dev->ctxlist->head);
+
        dev->vmalist = NULL;
        dev->sigdata.lock = dev->lock.hw_lock = NULL;
        init_waitqueue_head( &dev->lock.lock_queue );
@@ -567,6 +573,7 @@ static int DRM(probe)(struct pci_dev *pdev)
        dev->count_lock = SPIN_LOCK_UNLOCKED;
        init_timer( &dev->timer );
        sema_init( &dev->struct_sem, 1 );
+       sema_init( &dev->ctxlist_sem, 1 );
 
        if ((dev->minor = DRM(stub_register)(DRIVER_NAME, &DRM(fops),dev)) < 0)
                return -EPERM;
@@ -896,6 +903,25 @@ int DRM(release)( struct inode *inode, struct file *filp )
 
        DRM(fasync)( -1, filp, 0 );
 
+       down( &dev->ctxlist_sem );
+       if ( !list_empty( &dev->ctxlist->head ) ) {
+               drm_ctx_list_t *pos, *n;
+
+               list_for_each_entry_safe( pos, n, &dev->ctxlist->head, head ) {
+                       if ( pos->tag == priv &&
+                            pos->handle != DRM_KERNEL_CONTEXT ) {
+#ifdef DRIVER_CTX_DTOR
+                               DRIVER_CTX_DTOR(pos->handle);
+#endif
+                               DRM(ctxbitmap_free)( dev, pos->handle );
+
+                               list_del( &pos->head );
+                               DRM(free)( pos, sizeof(*pos), DRM_MEM_CTXLIST );
+                       }
+               }
+       }
+       up( &dev->ctxlist_sem );
+
        down( &dev->struct_sem );
        if ( priv->remove_auth_on_close == 1 ) {
                drm_file_t *temp = dev->file_first;
index fae419e..2a2e7d7 100644 (file)
@@ -68,6 +68,7 @@ static drm_mem_stats_t          DRM(mem_stats)[]   = {
        [DRM_MEM_TOTALAGP]  = { "totalagp" },
        [DRM_MEM_BOUNDAGP]  = { "boundagp" },
        [DRM_MEM_CTXBITMAP] = { "ctxbitmap"},
+       [DRM_MEM_CTXLIST]   = { "ctxlist"  },
        [DRM_MEM_STUB]      = { "stub"     },
        { NULL, 0, }            /* Last entry must be null */
 };
index b7b346d..742c4ac 100644 (file)
 #define DRM_MEM_CTXBITMAP 18
 #define DRM_MEM_STUB      19
 #define DRM_MEM_SGLISTS   20
+#define DRM_MEM_CTXLIST  21
 
 #define DRM_MAX_CTXBITMAP (PAGE_SIZE * 8)
        
@@ -651,6 +652,15 @@ typedef struct drm_map_list {
 
 typedef drm_map_t drm_local_map_t;
 
+/**
+ * Context handle list
+ */
+typedef struct drm_ctx_list {
+       struct list_head        head;   /**< list head */
+       drm_context_t           handle; /**< context handle */
+       drm_file_t              *tag;   /**< associated fd private data */
+} drm_ctx_list_t;
+
 #if __HAVE_VBL_IRQ
 
 typedef struct drm_vbl_sig {
@@ -711,6 +721,12 @@ typedef struct drm_device {
        drm_map_list_t    *maplist;     /**< Linked list of regions */
        int               map_count;    /**< Number of mappable regions */
 
+       /** \name Context handle management */
+       /*@{*/
+       drm_ctx_list_t    *ctxlist;     /**< Linked list of context handles */
+       int               ctx_count;    /**< Number of context handles */
+       struct semaphore  ctxlist_sem;  /**< For ctxlist */
+
        drm_map_t         **context_sareas; /**< per-context SAREA's */
        int               max_context;
 
index 82e90bc..474b5ba 100644 (file)
@@ -402,6 +402,7 @@ int DRM(addctx)( struct inode *inode, struct file *filp,
 {
        drm_file_t *priv = filp->private_data;
        drm_device_t *dev = priv->dev;
+       drm_ctx_list_t * ctx_entry;
        drm_ctx_t ctx;
 
        if ( copy_from_user( &ctx, (drm_ctx_t *)arg, sizeof(ctx) ) )
@@ -422,6 +423,20 @@ int DRM(addctx)( struct inode *inode, struct file *filp,
        if ( ctx.handle != DRM_KERNEL_CONTEXT )
                DRIVER_CTX_CTOR(ctx.handle); /* XXX: also pass dev ? */
 #endif
+       ctx_entry = DRM(alloc)( sizeof(*ctx_entry), DRM_MEM_CTXLIST );
+       if ( !ctx_entry ) {
+               DRM_DEBUG("out of memory\n");
+               return -ENOMEM;
+       }
+
+       INIT_LIST_HEAD( &ctx_entry->head );
+       ctx_entry->handle = ctx.handle;
+       ctx_entry->tag = priv;
+
+       down( &dev->ctxlist_sem );
+       list_add( &ctx_entry->head, &dev->ctxlist->head );
+       ++dev->ctx_count;
+       up( &dev->ctxlist_sem );
 
        if ( copy_to_user( (drm_ctx_t *)arg, &ctx, sizeof(ctx) ) )
                return -EFAULT;
@@ -544,6 +559,20 @@ int DRM(rmctx)( struct inode *inode, struct file *filp,
                DRM(ctxbitmap_free)( dev, ctx.handle );
        }
 
+       down( &dev->ctxlist_sem );
+       if ( !list_empty( &dev->ctxlist->head ) ) {
+               drm_ctx_list_t *pos, *n;
+
+               list_for_each_entry_safe( pos, n, &dev->ctxlist->head, head ) {
+                       if ( pos->handle == ctx.handle ) {
+                               list_del( &pos->head );
+                               DRM(free)( pos, sizeof(*pos), DRM_MEM_CTXLIST );
+                               --dev->ctx_count;
+                       }
+               }
+       }
+       up( &dev->ctxlist_sem );
+
        return 0;
 }
 
index d0dceaa..3eec29a 100644 (file)
@@ -329,6 +329,12 @@ static int DRM(setup)( drm_device_t *dev )
        memset(dev->maplist, 0, sizeof(*dev->maplist));
        INIT_LIST_HEAD(&dev->maplist->head);
 
+       dev->ctxlist = DRM(alloc)(sizeof(*dev->ctxlist),
+                                 DRM_MEM_CTXLIST);
+       if(dev->ctxlist == NULL) return -ENOMEM;
+       memset(dev->ctxlist, 0, sizeof(*dev->ctxlist));
+       INIT_LIST_HEAD(&dev->ctxlist->head);
+
        dev->vmalist = NULL;
        dev->sigdata.lock = dev->lock.hw_lock = NULL;
        init_waitqueue_head( &dev->lock.lock_queue );
@@ -567,6 +573,7 @@ static int DRM(probe)(struct pci_dev *pdev)
        dev->count_lock = SPIN_LOCK_UNLOCKED;
        init_timer( &dev->timer );
        sema_init( &dev->struct_sem, 1 );
+       sema_init( &dev->ctxlist_sem, 1 );
 
        if ((dev->minor = DRM(stub_register)(DRIVER_NAME, &DRM(fops),dev)) < 0)
                return -EPERM;
@@ -896,6 +903,25 @@ int DRM(release)( struct inode *inode, struct file *filp )
 
        DRM(fasync)( -1, filp, 0 );
 
+       down( &dev->ctxlist_sem );
+       if ( !list_empty( &dev->ctxlist->head ) ) {
+               drm_ctx_list_t *pos, *n;
+
+               list_for_each_entry_safe( pos, n, &dev->ctxlist->head, head ) {
+                       if ( pos->tag == priv &&
+                            pos->handle != DRM_KERNEL_CONTEXT ) {
+#ifdef DRIVER_CTX_DTOR
+                               DRIVER_CTX_DTOR(pos->handle);
+#endif
+                               DRM(ctxbitmap_free)( dev, pos->handle );
+
+                               list_del( &pos->head );
+                               DRM(free)( pos, sizeof(*pos), DRM_MEM_CTXLIST );
+                       }
+               }
+       }
+       up( &dev->ctxlist_sem );
+
        down( &dev->struct_sem );
        if ( priv->remove_auth_on_close == 1 ) {
                drm_file_t *temp = dev->file_first;
index fae419e..2a2e7d7 100644 (file)
@@ -68,6 +68,7 @@ static drm_mem_stats_t          DRM(mem_stats)[]   = {
        [DRM_MEM_TOTALAGP]  = { "totalagp" },
        [DRM_MEM_BOUNDAGP]  = { "boundagp" },
        [DRM_MEM_CTXBITMAP] = { "ctxbitmap"},
+       [DRM_MEM_CTXLIST]   = { "ctxlist"  },
        [DRM_MEM_STUB]      = { "stub"     },
        { NULL, 0, }            /* Last entry must be null */
 };