diff options
author | Oleg Nesterov <oleg@redhat.com> | 2015-11-06 19:32:19 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-11-06 20:50:42 -0500 |
commit | 2e01fabe67ccaff1d59bda01e60a61f5fb0aa7b6 (patch) | |
tree | 4db02540f4e0f4f3981965b86ee43cbd88ae517e /drivers/gpu/drm/drm_lock.c | |
parent | 4f05028f8d1af782cfd03d09e0a052e9745dc5ad (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.c | 41 |
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 | ||
41 | static int drm_notifier(void *priv); | ||
42 | |||
43 | static int drm_lock_take(struct drm_lock_data *lock_data, unsigned int context); | 41 | static 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 | */ | ||
301 | static 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. |