On Wed, 2009-01-07 at 10:15 -0800, Jesse Barnes wrote:
> On Wednesday, January 7, 2009 9:49 am Michel Dänzer wrote:
> > On Tue, 2009-01-06 at 22:49 -0800, Keith Packard wrote:
> > > On Tue, 2009-01-06 at 10:41 -0800, Jesse Barnes wrote:
> > > > This patch adds a sanity check to drmWaitVBlank to prevent hangs. 
> > > > Since the server interrupts syscalls pretty frequently with SIGALM, we
> > > > tend to restart syscalls when EINTR is returned.  That means when a
> > > > vblank timeout happens, we probably won't catch it (it happens after
> > > > 3s, and SIGALM happens every few ms), so we can fairly easily get stuck
> > > > restarting the vblank wait ioctl if something fishy is going on (like
> > > > vblank interrupts are disabled for some reason).
> > > >
> > > > So this patch removes the top level restart code, pushing it into the
> > > > vblank wait ioctl wrapper, while adding a timeout.  If there are cases
> > > > where more than 1s waits are desirable, we'd probably need to check the
> > > > sequence numbers and come up with a more reasonable value, or add a new
> > > > call that takes a timeout parameter.
> > >
> > > Uh, changing drmIoctl to return on EINTR seems like a bad plan. I'd hack
> > > up drmWaitVBlank to do the ioctl directly instead.
> >
> > Agreed - ignore the comment on this in my previous post, I got that
> > backwards of course. :)
> 
> Ok; I messed with drmIoctl because I thought I remembered you saying we 
> shouldn't put the retry code there but rather in the individual ioctls that 
> needed it.

I don't remember saying that, but maybe I just lost my recollection of
it over the holidays or something. :)


> +       /* Timeout after 1s */
> +       if (cur.tv_sec > timeout.tv_sec + 1 ||
> +        cur.tv_sec == timeout.tv_sec && cur.tv_nsec >= timeout.tv_nsec) {
> +        errno = EBUSY;
> +        ret = -1;
> +        break;
> +       }

Only just noticed this now: This should have additional tests to avoid
clobbering different error conditions or even success, something like

    do {
        ret = ioctl(fd, DRM_IOCTL_WAIT_VBLANK, vbl);
        vbl->request.type &= ~DRM_VBLANK_RELATIVE;

        if (ret && errno == EINTR) {
            clock_gettime(CLOCK_MONOTONIC, &cur);
            /* Timeout after 1s */
            if (cur.tv_sec > timeout.tv_sec + 1 ||
                cur.tv_sec == timeout.tv_sec && cur.tv_nsec >= timeout.tv_nsec) 
{
                errno = EBUSY;
                ret = -1;
                break;
            }
        }
    } while (ret && errno == EINTR);


-- 
Earthling Michel Dänzer           |                http://www.vmware.com
Libre software enthusiast         |          Debian, X and DRI developer

------------------------------------------------------------------------------
Check out the new SourceForge.net Marketplace.
It is the best place to buy or sell services for
just about anything Open Source.
http://p.sf.net/sfu/Xq1LFB
--
_______________________________________________
Dri-devel mailing list
Dri-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/dri-devel

Reply via email to