Trap and be verbose about a deadlock that occurs with AIGLX and drivers that
authorThomas Hellstrom <thomas-at-tungstengraphics-dot-com>
Mon, 2 Oct 2006 11:34:30 +0000 (13:34 +0200)
committerThomas Hellstrom <thomas-at-tungstengraphics-dot-com>
Mon, 2 Oct 2006 11:34:30 +0000 (13:34 +0200)
use drm_reclaim_buffers_locked().

linux-core/drm_fops.c
linux-core/drm_lock.c

index dcc05a0..e4385cf 100644 (file)
@@ -421,14 +421,26 @@ int drm_release(struct inode *inode, struct file *filp)
                  dev->open_count);
 
        if (dev->driver->reclaim_buffers_locked) {
-               retcode = drm_kernel_take_hw_lock(filp);
+               unsigned long _end = jiffies + DRM_HZ*3;
+
+               do {
+                       retcode = drm_kernel_take_hw_lock(filp);
+               } while(retcode && !time_after_eq(jiffies,_end));
+
                if (!retcode) {
                        dev->driver->reclaim_buffers_locked(dev, filp);
 
                        drm_lock_free(dev, &dev->lock.hw_lock->lock,
                                      _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock));
+               } else {
+                       DRM_ERROR("Reclaim buffers locked deadlock.\n");
+                       DRM_ERROR("This is probably a single thread having multiple\n");
+                       DRM_ERROR("DRM file descriptors open either dying or "
+                                 "closing file descriptors\n");
+                       DRM_ERROR("while having the lock. I will not reclaim buffers.\n");
+                       DRM_ERROR("Locking context is 0x%08x\n",
+                                 _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock));
                }
-
        } else if (drm_i_have_hw_lock(filp)) {
                DRM_DEBUG("File %p released, freeing lock for context %d\n",
                          filp, _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock));
index 04c145a..0cf183a 100644 (file)
@@ -343,6 +343,7 @@ int drm_kernel_take_hw_lock(struct file *filp)
        DRM_DEVICE;
 
        int ret = 0; 
+       unsigned long _end = jiffies + 3*DRM_HZ;
        
        if (!drm_i_have_hw_lock(filp)) {
        
@@ -364,7 +365,12 @@ int drm_kernel_take_hw_lock(struct file *filp)
                                break;  /* Got lock */
                        }
                        /* Contention */
-                       schedule();
+                       if (time_after_eq(jiffies,_end)) {
+                               ret = -EBUSY;
+                               break;
+                       }
+
+                       schedule_timeout(1);
                        if (signal_pending(current)) {
                                ret = -ERESTARTSYS;
                                break;