diff options
author | Michel Daenzer <michel@daenzer.net> | 2003-02-02 03:07:43 +0000 |
---|---|---|
committer | Michel Daenzer <michel@daenzer.net> | 2003-02-02 03:07:43 +0000 |
commit | 053ea8af9d96842da4aa08f90ce08c2e78efbd49 (patch) | |
tree | 3d01e27eb55a7086d99ea21e5a7269b7ceaf25fd | |
parent | 4c404e4642aca310681a20b18a8b97ba4834caa0 (diff) |
don't inflate relative vblank sequence numbers on repeated calls (e.g. when
interrupted by a signal)
-rw-r--r-- | bsd-core/drm_dma.c | 66 | ||||
-rw-r--r-- | bsd/drm_dma.h | 66 | ||||
-rw-r--r-- | libdrm/xf86drm.c | 1 | ||||
-rw-r--r-- | linux-core/drm_dma.c | 1 | ||||
-rw-r--r-- | linux/drm_dma.h | 1 |
5 files changed, 121 insertions, 14 deletions
diff --git a/bsd-core/drm_dma.c b/bsd-core/drm_dma.c index 5632b5a2..0f0dd4fd 100644 --- a/bsd-core/drm_dma.c +++ b/bsd-core/drm_dma.c @@ -524,6 +524,11 @@ int DRM(irq_install)( drm_device_t *dev, int irq ) TASK_INIT(&dev->task, 0, DRM(dma_immediate_bh), dev); #endif +#if __HAVE_VBL_IRQ + DRM_SPININIT( dev->vbl_lock, "vblsig" ); + TAILQ_INIT( &dev->vbl_sig_list ); +#endif + /* Before installing handler */ DRM(driver_irq_preinstall)( dev ); @@ -612,21 +617,68 @@ int DRM(wait_vblank)( DRM_IOCTL_ARGS ) DRM_COPY_FROM_USER_IOCTL( vblwait, (drm_wait_vblank_t *)data, sizeof(vblwait) ); - if ( vblwait.type == _DRM_VBLANK_RELATIVE ) { - vblwait.sequence += atomic_read( &dev->vbl_received ); + if (vblwait.request.type & _DRM_VBLANK_RELATIVE) { + vblwait.request.sequence += atomic_read(&dev->vbl_received); + vblwait.request.type &= ~_DRM_VBLANK_RELATIVE; } - ret = DRM(vblank_wait)( dev, &vblwait.sequence ); - - microtime( &now ); - vblwait.tval_sec = now.tv_sec; - vblwait.tval_usec = now.tv_usec; + flags = vblwait.request.type & _DRM_VBLANK_FLAGS_MASK; + if (flags & _DRM_VBLANK_SIGNAL) { + drm_vbl_sig_t *vbl_sig = DRM_MALLOC(sizeof(drm_vbl_sig_t)); + if (vbl_sig == NULL) + return ENOMEM; + bzero(vbl_sig, sizeof(*vbl_sig)); + + vbl_sig->sequence = vblwait.request.sequence; + vbl_sig->signo = vblwait.request.signal; + vbl_sig->pid = DRM_CURRENTPID; + + vblwait.reply.sequence = atomic_read(&dev->vbl_received); + + DRM_SPINLOCK(&dev->vbl_lock); + TAILQ_INSERT_HEAD(&dev->vbl_sig_list, vbl_sig, link); + DRM_SPINUNLOCK(&dev->vbl_lock); + ret = 0; + } else { + ret = DRM(vblank_wait)(dev, &vblwait.request.sequence); + + microtime(&now); + vblwait.reply.tval_sec = now.tv_sec; + vblwait.reply.tval_usec = now.tv_usec; + } DRM_COPY_TO_USER_IOCTL( (drm_wait_vblank_t *)data, vblwait, sizeof(vblwait) ); return ret; } + +void DRM(vbl_send_signals)( drm_device_t *dev ) +{ + drm_vbl_sig_t *vbl_sig; + unsigned int vbl_seq = atomic_read( &dev->vbl_received ); + struct proc *p; + + DRM_SPINLOCK(&dev->vbl_lock); + + vbl_sig = TAILQ_FIRST(&dev->vbl_sig_list); + while (vbl_sig != NULL) { + drm_vbl_sig_t *next = TAILQ_NEXT(vbl_sig, link); + + if ( ( vbl_seq - vbl_sig->sequence ) <= (1<<23) ) { + p = pfind(vbl_sig->pid); + if (p != NULL) + psignal(p, vbl_sig->signo); + + TAILQ_REMOVE(&dev->vbl_sig_list, vbl_sig, link); + DRM_FREE(vbl_sig); + } + vbl_sig = next; + } + + DRM_SPINUNLOCK(&dev->vbl_lock); +} + #endif /* __HAVE_VBL_IRQ */ #else diff --git a/bsd/drm_dma.h b/bsd/drm_dma.h index 5632b5a2..0f0dd4fd 100644 --- a/bsd/drm_dma.h +++ b/bsd/drm_dma.h @@ -524,6 +524,11 @@ int DRM(irq_install)( drm_device_t *dev, int irq ) TASK_INIT(&dev->task, 0, DRM(dma_immediate_bh), dev); #endif +#if __HAVE_VBL_IRQ + DRM_SPININIT( dev->vbl_lock, "vblsig" ); + TAILQ_INIT( &dev->vbl_sig_list ); +#endif + /* Before installing handler */ DRM(driver_irq_preinstall)( dev ); @@ -612,21 +617,68 @@ int DRM(wait_vblank)( DRM_IOCTL_ARGS ) DRM_COPY_FROM_USER_IOCTL( vblwait, (drm_wait_vblank_t *)data, sizeof(vblwait) ); - if ( vblwait.type == _DRM_VBLANK_RELATIVE ) { - vblwait.sequence += atomic_read( &dev->vbl_received ); + if (vblwait.request.type & _DRM_VBLANK_RELATIVE) { + vblwait.request.sequence += atomic_read(&dev->vbl_received); + vblwait.request.type &= ~_DRM_VBLANK_RELATIVE; } - ret = DRM(vblank_wait)( dev, &vblwait.sequence ); - - microtime( &now ); - vblwait.tval_sec = now.tv_sec; - vblwait.tval_usec = now.tv_usec; + flags = vblwait.request.type & _DRM_VBLANK_FLAGS_MASK; + if (flags & _DRM_VBLANK_SIGNAL) { + drm_vbl_sig_t *vbl_sig = DRM_MALLOC(sizeof(drm_vbl_sig_t)); + if (vbl_sig == NULL) + return ENOMEM; + bzero(vbl_sig, sizeof(*vbl_sig)); + + vbl_sig->sequence = vblwait.request.sequence; + vbl_sig->signo = vblwait.request.signal; + vbl_sig->pid = DRM_CURRENTPID; + + vblwait.reply.sequence = atomic_read(&dev->vbl_received); + + DRM_SPINLOCK(&dev->vbl_lock); + TAILQ_INSERT_HEAD(&dev->vbl_sig_list, vbl_sig, link); + DRM_SPINUNLOCK(&dev->vbl_lock); + ret = 0; + } else { + ret = DRM(vblank_wait)(dev, &vblwait.request.sequence); + + microtime(&now); + vblwait.reply.tval_sec = now.tv_sec; + vblwait.reply.tval_usec = now.tv_usec; + } DRM_COPY_TO_USER_IOCTL( (drm_wait_vblank_t *)data, vblwait, sizeof(vblwait) ); return ret; } + +void DRM(vbl_send_signals)( drm_device_t *dev ) +{ + drm_vbl_sig_t *vbl_sig; + unsigned int vbl_seq = atomic_read( &dev->vbl_received ); + struct proc *p; + + DRM_SPINLOCK(&dev->vbl_lock); + + vbl_sig = TAILQ_FIRST(&dev->vbl_sig_list); + while (vbl_sig != NULL) { + drm_vbl_sig_t *next = TAILQ_NEXT(vbl_sig, link); + + if ( ( vbl_seq - vbl_sig->sequence ) <= (1<<23) ) { + p = pfind(vbl_sig->pid); + if (p != NULL) + psignal(p, vbl_sig->signo); + + TAILQ_REMOVE(&dev->vbl_sig_list, vbl_sig, link); + DRM_FREE(vbl_sig); + } + vbl_sig = next; + } + + DRM_SPINUNLOCK(&dev->vbl_lock); +} + #endif /* __HAVE_VBL_IRQ */ #else diff --git a/libdrm/xf86drm.c b/libdrm/xf86drm.c index 465bb55d..a814747c 100644 --- a/libdrm/xf86drm.c +++ b/libdrm/xf86drm.c @@ -1105,6 +1105,7 @@ int drmWaitVBlank(int fd, drmVBlankPtr vbl) do { ret = ioctl(fd, DRM_IOCTL_WAIT_VBLANK, vbl); + vbl->request.type &= ~DRM_VBLANK_RELATIVE; } while (ret && errno == EINTR); return ret; diff --git a/linux-core/drm_dma.c b/linux-core/drm_dma.c index 33af34be..df4ed809 100644 --- a/linux-core/drm_dma.c +++ b/linux-core/drm_dma.c @@ -628,6 +628,7 @@ int DRM(wait_vblank)( DRM_IOCTL_ARGS ) switch ( vblwait.request.type & ~_DRM_VBLANK_FLAGS_MASK ) { case _DRM_VBLANK_RELATIVE: vblwait.request.sequence += atomic_read( &dev->vbl_received ); + vblwait.request.type &= ~_DRM_VBLANK_RELATIVE; case _DRM_VBLANK_ABSOLUTE: break; default: diff --git a/linux/drm_dma.h b/linux/drm_dma.h index 33af34be..df4ed809 100644 --- a/linux/drm_dma.h +++ b/linux/drm_dma.h @@ -628,6 +628,7 @@ int DRM(wait_vblank)( DRM_IOCTL_ARGS ) switch ( vblwait.request.type & ~_DRM_VBLANK_FLAGS_MASK ) { case _DRM_VBLANK_RELATIVE: vblwait.request.sequence += atomic_read( &dev->vbl_received ); + vblwait.request.type &= ~_DRM_VBLANK_RELATIVE; case _DRM_VBLANK_ABSOLUTE: break; default: |