aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/drm_lock.c
diff options
context:
space:
mode:
authorOleg Nesterov <oleg@redhat.com>2015-11-06 19:32:19 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2015-11-06 20:50:42 -0500
commit2e01fabe67ccaff1d59bda01e60a61f5fb0aa7b6 (patch)
tree4db02540f4e0f4f3981965b86ee43cbd88ae517e /drivers/gpu/drm/drm_lock.c
parent4f05028f8d1af782cfd03d09e0a052e9745dc5ad (diff)
signals: kill block_all_signals() and unblock_all_signals()
It is hardly possible to enumerate all problems with block_all_signals() and unblock_all_signals(). Just for example, 1. block_all_signals(SIGSTOP/etc) simply can't help if the caller is multithreaded. Another thread can dequeue the signal and force the group stop. 2. Even is the caller is single-threaded, it will "stop" anyway. It will not sleep, but it will spin in kernel space until SIGCONT or SIGKILL. And a lot more. In short, this interface doesn't work at all, at least the last 10+ years. Daniel said: Yeah the only times I played around with the DRM_LOCK stuff was when old drivers accidentally deadlocked - my impression is that the entire DRM_LOCK thing was never really tested properly ;-) Hence I'm all for purging where this leaks out of the drm subsystem. Signed-off-by: Oleg Nesterov <oleg@redhat.com> Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch> Acked-by: Dave Airlie <airlied@redhat.com> Cc: Richard Weinberger <richard@nod.at> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/gpu/drm/drm_lock.c')
-rw-r--r--drivers/gpu/drm/drm_lock.c41
1 files changed, 0 insertions, 41 deletions
diff --git a/drivers/gpu/drm/drm_lock.c b/drivers/gpu/drm/drm_lock.c
index 4924d381b664..daa2ff12101b 100644
--- a/drivers/gpu/drm/drm_lock.c
+++ b/drivers/gpu/drm/drm_lock.c
@@ -38,8 +38,6 @@
38#include "drm_legacy.h" 38#include "drm_legacy.h"
39#include "drm_internal.h" 39#include "drm_internal.h"
40 40
41static int drm_notifier(void *priv);
42
43static int drm_lock_take(struct drm_lock_data *lock_data, unsigned int context); 41static int drm_lock_take(struct drm_lock_data *lock_data, unsigned int context);
44 42
45/** 43/**
@@ -118,14 +116,8 @@ int drm_legacy_lock(struct drm_device *dev, void *data,
118 * really probably not the correct answer but lets us debug xkb 116 * really probably not the correct answer but lets us debug xkb
119 * xserver for now */ 117 * xserver for now */
120 if (!file_priv->is_master) { 118 if (!file_priv->is_master) {
121 sigemptyset(&dev->sigmask);
122 sigaddset(&dev->sigmask, SIGSTOP);
123 sigaddset(&dev->sigmask, SIGTSTP);
124 sigaddset(&dev->sigmask, SIGTTIN);
125 sigaddset(&dev->sigmask, SIGTTOU);
126 dev->sigdata.context = lock->context; 119 dev->sigdata.context = lock->context;
127 dev->sigdata.lock = master->lock.hw_lock; 120 dev->sigdata.lock = master->lock.hw_lock;
128 block_all_signals(drm_notifier, dev, &dev->sigmask);
129 } 121 }
130 122
131 if (dev->driver->dma_quiescent && (lock->flags & _DRM_LOCK_QUIESCENT)) 123 if (dev->driver->dma_quiescent && (lock->flags & _DRM_LOCK_QUIESCENT))
@@ -169,7 +161,6 @@ int drm_legacy_unlock(struct drm_device *dev, void *data, struct drm_file *file_
169 /* FIXME: Should really bail out here. */ 161 /* FIXME: Should really bail out here. */
170 } 162 }
171 163
172 unblock_all_signals();
173 return 0; 164 return 0;
174} 165}
175 166
@@ -288,38 +279,6 @@ int drm_legacy_lock_free(struct drm_lock_data *lock_data, unsigned int context)
288} 279}
289 280
290/** 281/**
291 * If we get here, it means that the process has called DRM_IOCTL_LOCK
292 * without calling DRM_IOCTL_UNLOCK.
293 *
294 * If the lock is not held, then let the signal proceed as usual. If the lock
295 * is held, then set the contended flag and keep the signal blocked.
296 *
297 * \param priv pointer to a drm_device structure.
298 * \return one if the signal should be delivered normally, or zero if the
299 * signal should be blocked.
300 */
301static int drm_notifier(void *priv)
302{
303 struct drm_device *dev = priv;
304 struct drm_hw_lock *lock = dev->sigdata.lock;
305 unsigned int old, new, prev;
306
307 /* Allow signal delivery if lock isn't held */
308 if (!lock || !_DRM_LOCK_IS_HELD(lock->lock)
309 || _DRM_LOCKING_CONTEXT(lock->lock) != dev->sigdata.context)
310 return 1;
311
312 /* Otherwise, set flag to force call to
313 drmUnlock */
314 do {
315 old = lock->lock;
316 new = old | _DRM_LOCK_CONT;
317 prev = cmpxchg(&lock->lock, old, new);
318 } while (prev != old);
319 return 0;
320}
321
322/**
323 * This function returns immediately and takes the hw lock 282 * This function returns immediately and takes the hw lock
324 * with the kernel context if it is free, otherwise it gets the highest priority when and if 283 * with the kernel context if it is free, otherwise it gets the highest priority when and if
325 * it is eventually released. 284 * it is eventually released.