From 6f07e1ff6bec8f306e8aa1d59b8bcaa93ffa776e Mon Sep 17 00:00:00 2001 From: Rik Faith Date: Sat, 26 Aug 2000 10:36:44 +0000 Subject: [PATCH] Sync with Linux 2.4.0-test7 Add signal blocking support to all drivers (using control-z on a running direct-rendering client should work now) --- linux-core/drmP.h | 10 +++++++++- linux-core/i810_dma.c | 10 ++++++++++ linux-core/i810_drv.c | 3 +++ linux-core/mga_drv.c | 3 +++ linux-core/r128_drv.c | 13 +++++++++++++ linux-core/sis_drv.c | 15 ++++++++++++++- linux-core/tdfx_drv.c | 13 +++++++++++++ linux/drmP.h | 10 +++++++++- linux/gamma_dma.c | 10 ++++++++++ linux/gamma_drv.c | 3 +++ linux/i810_dma.c | 10 ++++++++++ linux/i810_drv.c | 3 +++ linux/lock.c | 32 ++++++++++++++++++++++++++++++++ linux/mga_dma.c | 10 ++++++++++ linux/mga_drv.c | 3 +++ linux/r128_drv.c | 13 +++++++++++++ linux/sis_drv.c | 15 ++++++++++++++- linux/tdfx_drv.c | 13 +++++++++++++ 18 files changed, 185 insertions(+), 4 deletions(-) diff --git a/linux-core/drmP.h b/linux-core/drmP.h index aa9bc01a..b9a4dab4 100644 --- a/linux-core/drmP.h +++ b/linux-core/drmP.h @@ -57,7 +57,7 @@ #include #include #endif -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,0) +#if LINUX_VERSION_CODE >= 0x020100 /* KERNEL_VERSION(2,1,0) */ #include #include #endif @@ -451,6 +451,11 @@ typedef struct { extern drm_agp_func_t drm_agp; #endif +typedef struct drm_sigdata { + int context; + drm_hw_lock_t *lock; +} drm_sigdata_t; + typedef struct drm_device { const char *name; /* Simple driver name */ char *unique; /* Unique identifier: e.g., busid */ @@ -535,6 +540,8 @@ typedef struct drm_device { #endif unsigned long *ctx_bitmap; void *dev_private; + drm_sigdata_t sigdata; /* For block_all_signals */ + sigset_t sigmask; } drm_device_t; @@ -729,6 +736,7 @@ extern int drm_flush_unblock(drm_device_t *dev, int context, drm_lock_flags_t flags); extern int drm_flush_block_and_flush(drm_device_t *dev, int context, drm_lock_flags_t flags); +extern int drm_notifier(void *priv); /* Context Bitmap support (ctxbitmap.c) */ extern int drm_ctxbitmap_init(drm_device_t *dev); diff --git a/linux-core/i810_dma.c b/linux-core/i810_dma.c index 19b7bd92..5792bf39 100644 --- a/linux-core/i810_dma.c +++ b/linux-core/i810_dma.c @@ -1227,6 +1227,16 @@ int i810_lock(struct inode *inode, struct file *filp, unsigned int cmd, } if (!ret) { +#if LINUX_VERSION_CODE >= 0x020400 /* KERNEL_VERSION(2,4,0) */ + sigemptyset(&dev->sigmask); + sigaddset(&dev->sigmask, SIGSTOP); + sigaddset(&dev->sigmask, SIGTSTP); + sigaddset(&dev->sigmask, SIGTTIN); + sigaddset(&dev->sigmask, SIGTTOU); + dev->sigdata.context = lock.context; + dev->sigdata.lock = dev->lock.hw_lock; + block_all_signals(drm_notifier, &dev->sigdata, &dev->sigmask); +#endif if (lock.flags & _DRM_LOCK_QUIESCENT) { DRM_DEBUG("_DRM_LOCK_QUIESCENT\n"); DRM_DEBUG("fred\n"); diff --git a/linux-core/i810_drv.c b/linux-core/i810_drv.c index 275663a1..18168605 100644 --- a/linux-core/i810_drv.c +++ b/linux-core/i810_drv.c @@ -642,5 +642,8 @@ int i810_unlock(struct inode *inode, struct file *filp, unsigned int cmd, - dev->lck_start)]); #endif +#if LINUX_VERSION_CODE >= 0x020400 /* KERNEL_VERSION(2,4,0) */ + unblock_all_signals(); +#endif return 0; } diff --git a/linux-core/mga_drv.c b/linux-core/mga_drv.c index acc42b83..a4a8fe55 100644 --- a/linux-core/mga_drv.c +++ b/linux-core/mga_drv.c @@ -655,5 +655,8 @@ int mga_unlock(struct inode *inode, struct file *filp, unsigned int cmd, DRM_ERROR("\n"); } +#if LINUX_VERSION_CODE >= 0x020400 /* KERNEL_VERSION(2,4,0) */ + unblock_all_signals(); +#endif return 0; } diff --git a/linux-core/r128_drv.c b/linux-core/r128_drv.c index fac88247..c4eb634d 100644 --- a/linux-core/r128_drv.c +++ b/linux-core/r128_drv.c @@ -656,6 +656,16 @@ int r128_lock(struct inode *inode, struct file *filp, unsigned int cmd, #endif if (!ret) { +#if LINUX_VERSION_CODE >= 0x020400 /* KERNEL_VERSION(2,4,0) */ + sigemptyset(&dev->sigmask); + sigaddset(&dev->sigmask, SIGSTOP); + sigaddset(&dev->sigmask, SIGTSTP); + sigaddset(&dev->sigmask, SIGTTIN); + sigaddset(&dev->sigmask, SIGTTOU); + dev->sigdata.context = lock.context; + dev->sigdata.lock = dev->lock.hw_lock; + block_all_signals(drm_notifier, &dev->sigdata, &dev->sigmask); +#endif if (lock.flags & _DRM_LOCK_READY) { /* Wait for space in DMA/FIFO */ } @@ -720,5 +730,8 @@ int r128_unlock(struct inode *inode, struct file *filp, unsigned int cmd, } #endif +#if LINUX_VERSION_CODE >= 0x020400 /* KERNEL_VERSION(2,4,0) */ + unblock_all_signals(); +#endif return 0; } diff --git a/linux-core/sis_drv.c b/linux-core/sis_drv.c index 5dda149a..434a1ccd 100644 --- a/linux-core/sis_drv.c +++ b/linux-core/sis_drv.c @@ -626,6 +626,16 @@ int sis_lock(struct inode *inode, struct file *filp, unsigned int cmd, #endif if (!ret) { +#if LINUX_VERSION_CODE >= 0x020400 /* KERNEL_VERSION(2,4,0) */ + sigemptyset(&dev->sigmask); + sigaddset(&dev->sigmask, SIGSTOP); + sigaddset(&dev->sigmask, SIGTSTP); + sigaddset(&dev->sigmask, SIGTTIN); + sigaddset(&dev->sigmask, SIGTTOU); + dev->sigdata.context = lock.context; + dev->sigdata.lock = dev->lock.hw_lock; + block_all_signals(drm_notifier, &dev->sigdata, &dev->sigmask); +#endif if (lock.flags & _DRM_LOCK_READY) { /* Wait for space in DMA/FIFO */ } @@ -676,7 +686,10 @@ int sis_unlock(struct inode *inode, struct file *filp, unsigned int cmd, DRM_ERROR("\n"); } } - + +#if LINUX_VERSION_CODE >= 0x020400 /* KERNEL_VERSION(2,4,0) */ + unblock_all_signals(); +#endif return 0; } diff --git a/linux-core/tdfx_drv.c b/linux-core/tdfx_drv.c index 59f10197..07febea1 100644 --- a/linux-core/tdfx_drv.c +++ b/linux-core/tdfx_drv.c @@ -615,6 +615,16 @@ int tdfx_lock(struct inode *inode, struct file *filp, unsigned int cmd, #endif if (!ret) { +#if LINUX_VERSION_CODE >= 0x020400 /* KERNEL_VERSION(2,4,0) */ + sigemptyset(&dev->sigmask); + sigaddset(&dev->sigmask, SIGSTOP); + sigaddset(&dev->sigmask, SIGTSTP); + sigaddset(&dev->sigmask, SIGTTIN); + sigaddset(&dev->sigmask, SIGTTOU); + dev->sigdata.context = lock.context; + dev->sigdata.lock = dev->lock.hw_lock; + block_all_signals(drm_notifier, &dev->sigdata, &dev->sigmask); +#endif if (lock.flags & _DRM_LOCK_READY) { /* Wait for space in DMA/FIFO */ } @@ -679,5 +689,8 @@ int tdfx_unlock(struct inode *inode, struct file *filp, unsigned int cmd, } #endif +#if LINUX_VERSION_CODE >= 0x020400 /* KERNEL_VERSION(2,4,0) */ + unblock_all_signals(); +#endif return 0; } diff --git a/linux/drmP.h b/linux/drmP.h index aa9bc01a..b9a4dab4 100644 --- a/linux/drmP.h +++ b/linux/drmP.h @@ -57,7 +57,7 @@ #include #include #endif -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,0) +#if LINUX_VERSION_CODE >= 0x020100 /* KERNEL_VERSION(2,1,0) */ #include #include #endif @@ -451,6 +451,11 @@ typedef struct { extern drm_agp_func_t drm_agp; #endif +typedef struct drm_sigdata { + int context; + drm_hw_lock_t *lock; +} drm_sigdata_t; + typedef struct drm_device { const char *name; /* Simple driver name */ char *unique; /* Unique identifier: e.g., busid */ @@ -535,6 +540,8 @@ typedef struct drm_device { #endif unsigned long *ctx_bitmap; void *dev_private; + drm_sigdata_t sigdata; /* For block_all_signals */ + sigset_t sigmask; } drm_device_t; @@ -729,6 +736,7 @@ extern int drm_flush_unblock(drm_device_t *dev, int context, drm_lock_flags_t flags); extern int drm_flush_block_and_flush(drm_device_t *dev, int context, drm_lock_flags_t flags); +extern int drm_notifier(void *priv); /* Context Bitmap support (ctxbitmap.c) */ extern int drm_ctxbitmap_init(drm_device_t *dev); diff --git a/linux/gamma_dma.c b/linux/gamma_dma.c index a99f24ca..4a2acfb3 100644 --- a/linux/gamma_dma.c +++ b/linux/gamma_dma.c @@ -804,6 +804,16 @@ int gamma_lock(struct inode *inode, struct file *filp, unsigned int cmd, drm_flush_unblock(dev, lock.context, lock.flags); /* cleanup phase */ if (!ret) { +#if LINUX_VERSION_CODE >= 0x020400 /* KERNEL_VERSION(2,4,0) */ + sigemptyset(&dev->sigmask); + sigaddset(&dev->sigmask, SIGSTOP); + sigaddset(&dev->sigmask, SIGTSTP); + sigaddset(&dev->sigmask, SIGTTIN); + sigaddset(&dev->sigmask, SIGTTOU); + dev->sigdata.context = lock.context; + dev->sigdata.lock = dev->lock.hw_lock; + block_all_signals(drm_notifier, &dev->sigdata, &dev->sigmask); +#endif if (lock.flags & _DRM_LOCK_READY) gamma_dma_ready(dev); if (lock.flags & _DRM_LOCK_QUIESCENT) { diff --git a/linux/gamma_drv.c b/linux/gamma_drv.c index 13d37c24..1fcd1933 100644 --- a/linux/gamma_drv.c +++ b/linux/gamma_drv.c @@ -564,5 +564,8 @@ int gamma_unlock(struct inode *inode, struct file *filp, unsigned int cmd, - dev->lck_start)]); #endif +#if LINUX_VERSION_CODE >= 0x020400 /* KERNEL_VERSION(2,4,0) */ + unblock_all_signals(); +#endif return 0; } diff --git a/linux/i810_dma.c b/linux/i810_dma.c index 19b7bd92..5792bf39 100644 --- a/linux/i810_dma.c +++ b/linux/i810_dma.c @@ -1227,6 +1227,16 @@ int i810_lock(struct inode *inode, struct file *filp, unsigned int cmd, } if (!ret) { +#if LINUX_VERSION_CODE >= 0x020400 /* KERNEL_VERSION(2,4,0) */ + sigemptyset(&dev->sigmask); + sigaddset(&dev->sigmask, SIGSTOP); + sigaddset(&dev->sigmask, SIGTSTP); + sigaddset(&dev->sigmask, SIGTTIN); + sigaddset(&dev->sigmask, SIGTTOU); + dev->sigdata.context = lock.context; + dev->sigdata.lock = dev->lock.hw_lock; + block_all_signals(drm_notifier, &dev->sigdata, &dev->sigmask); +#endif if (lock.flags & _DRM_LOCK_QUIESCENT) { DRM_DEBUG("_DRM_LOCK_QUIESCENT\n"); DRM_DEBUG("fred\n"); diff --git a/linux/i810_drv.c b/linux/i810_drv.c index 275663a1..18168605 100644 --- a/linux/i810_drv.c +++ b/linux/i810_drv.c @@ -642,5 +642,8 @@ int i810_unlock(struct inode *inode, struct file *filp, unsigned int cmd, - dev->lck_start)]); #endif +#if LINUX_VERSION_CODE >= 0x020400 /* KERNEL_VERSION(2,4,0) */ + unblock_all_signals(); +#endif return 0; } 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; +} diff --git a/linux/mga_dma.c b/linux/mga_dma.c index 9ca72296..d315954d 100644 --- a/linux/mga_dma.c +++ b/linux/mga_dma.c @@ -1074,6 +1074,16 @@ int mga_lock(struct inode *inode, struct file *filp, unsigned int cmd, } if (!ret) { +#if LINUX_VERSION_CODE >= 0x020400 /* KERNEL_VERSION(2,4,0) */ + sigemptyset(&dev->sigmask); + sigaddset(&dev->sigmask, SIGSTOP); + sigaddset(&dev->sigmask, SIGTSTP); + sigaddset(&dev->sigmask, SIGTTIN); + sigaddset(&dev->sigmask, SIGTTOU); + dev->sigdata.context = lock.context; + dev->sigdata.lock = dev->lock.hw_lock; + block_all_signals(drm_notifier, &dev->sigdata, &dev->sigmask); +#endif if (lock.flags & _DRM_LOCK_QUIESCENT) { DRM_DEBUG("_DRM_LOCK_QUIESCENT\n"); mga_flush_queue(dev); diff --git a/linux/mga_drv.c b/linux/mga_drv.c index acc42b83..a4a8fe55 100644 --- a/linux/mga_drv.c +++ b/linux/mga_drv.c @@ -655,5 +655,8 @@ int mga_unlock(struct inode *inode, struct file *filp, unsigned int cmd, DRM_ERROR("\n"); } +#if LINUX_VERSION_CODE >= 0x020400 /* KERNEL_VERSION(2,4,0) */ + unblock_all_signals(); +#endif return 0; } diff --git a/linux/r128_drv.c b/linux/r128_drv.c index fac88247..c4eb634d 100644 --- a/linux/r128_drv.c +++ b/linux/r128_drv.c @@ -656,6 +656,16 @@ int r128_lock(struct inode *inode, struct file *filp, unsigned int cmd, #endif if (!ret) { +#if LINUX_VERSION_CODE >= 0x020400 /* KERNEL_VERSION(2,4,0) */ + sigemptyset(&dev->sigmask); + sigaddset(&dev->sigmask, SIGSTOP); + sigaddset(&dev->sigmask, SIGTSTP); + sigaddset(&dev->sigmask, SIGTTIN); + sigaddset(&dev->sigmask, SIGTTOU); + dev->sigdata.context = lock.context; + dev->sigdata.lock = dev->lock.hw_lock; + block_all_signals(drm_notifier, &dev->sigdata, &dev->sigmask); +#endif if (lock.flags & _DRM_LOCK_READY) { /* Wait for space in DMA/FIFO */ } @@ -720,5 +730,8 @@ int r128_unlock(struct inode *inode, struct file *filp, unsigned int cmd, } #endif +#if LINUX_VERSION_CODE >= 0x020400 /* KERNEL_VERSION(2,4,0) */ + unblock_all_signals(); +#endif return 0; } diff --git a/linux/sis_drv.c b/linux/sis_drv.c index 5dda149a..434a1ccd 100644 --- a/linux/sis_drv.c +++ b/linux/sis_drv.c @@ -626,6 +626,16 @@ int sis_lock(struct inode *inode, struct file *filp, unsigned int cmd, #endif if (!ret) { +#if LINUX_VERSION_CODE >= 0x020400 /* KERNEL_VERSION(2,4,0) */ + sigemptyset(&dev->sigmask); + sigaddset(&dev->sigmask, SIGSTOP); + sigaddset(&dev->sigmask, SIGTSTP); + sigaddset(&dev->sigmask, SIGTTIN); + sigaddset(&dev->sigmask, SIGTTOU); + dev->sigdata.context = lock.context; + dev->sigdata.lock = dev->lock.hw_lock; + block_all_signals(drm_notifier, &dev->sigdata, &dev->sigmask); +#endif if (lock.flags & _DRM_LOCK_READY) { /* Wait for space in DMA/FIFO */ } @@ -676,7 +686,10 @@ int sis_unlock(struct inode *inode, struct file *filp, unsigned int cmd, DRM_ERROR("\n"); } } - + +#if LINUX_VERSION_CODE >= 0x020400 /* KERNEL_VERSION(2,4,0) */ + unblock_all_signals(); +#endif return 0; } diff --git a/linux/tdfx_drv.c b/linux/tdfx_drv.c index 59f10197..07febea1 100644 --- a/linux/tdfx_drv.c +++ b/linux/tdfx_drv.c @@ -615,6 +615,16 @@ int tdfx_lock(struct inode *inode, struct file *filp, unsigned int cmd, #endif if (!ret) { +#if LINUX_VERSION_CODE >= 0x020400 /* KERNEL_VERSION(2,4,0) */ + sigemptyset(&dev->sigmask); + sigaddset(&dev->sigmask, SIGSTOP); + sigaddset(&dev->sigmask, SIGTSTP); + sigaddset(&dev->sigmask, SIGTTIN); + sigaddset(&dev->sigmask, SIGTTOU); + dev->sigdata.context = lock.context; + dev->sigdata.lock = dev->lock.hw_lock; + block_all_signals(drm_notifier, &dev->sigdata, &dev->sigmask); +#endif if (lock.flags & _DRM_LOCK_READY) { /* Wait for space in DMA/FIFO */ } @@ -679,5 +689,8 @@ int tdfx_unlock(struct inode *inode, struct file *filp, unsigned int cmd, } #endif +#if LINUX_VERSION_CODE >= 0x020400 /* KERNEL_VERSION(2,4,0) */ + unblock_all_signals(); +#endif return 0; }