diff options
Diffstat (limited to 'linux/lock.c')
-rw-r--r-- | linux/lock.c | 32 |
1 files changed, 32 insertions, 0 deletions
diff --git a/linux/lock.c b/linux/lock.c index 55082727..33b2cc03 100644 --- a/linux/lock.c +++ b/linux/lock.c @@ -223,3 +223,35 @@ int drm_finish(struct inode *inode, struct file *filp, unsigned int cmd, drm_flush_unblock(dev, lock.context, lock.flags); return ret; } + +/* If we get here, it means that the process has called DRM_IOCTL_LOCK + without calling DRM_IOCTL_UNLOCK. + + If the lock is not held, then let the signal proceed as usual. + + If the lock is held, then set the contended flag and keep the signal + blocked. + + + Return 1 if the signal should be delivered normally. + Return 0 if the signal should be blocked. */ + +int drm_notifier(void *priv) +{ + drm_sigdata_t *s = (drm_sigdata_t *)priv; + unsigned int old, new, prev; + + + /* Allow signal delivery if lock isn't held */ + if (!_DRM_LOCK_IS_HELD(s->lock->lock) + || _DRM_LOCKING_CONTEXT(s->lock->lock) != s->context) return 1; + + /* Otherwise, set flag to force call to + drmUnlock */ + do { + old = s->lock->lock; + new = old | _DRM_LOCK_CONT; + prev = cmpxchg(&s->lock->lock, old, new); + } while (prev != old); + return 0; +} |