summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichel Daenzer <michel@daenzer.net>2003-02-02 03:07:43 +0000
committerMichel Daenzer <michel@daenzer.net>2003-02-02 03:07:43 +0000
commit053ea8af9d96842da4aa08f90ce08c2e78efbd49 (patch)
tree3d01e27eb55a7086d99ea21e5a7269b7ceaf25fd
parent4c404e4642aca310681a20b18a8b97ba4834caa0 (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.c66
-rw-r--r--bsd/drm_dma.h66
-rw-r--r--libdrm/xf86drm.c1
-rw-r--r--linux-core/drm_dma.c1
-rw-r--r--linux/drm_dma.h1
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: