[PATCH] present: Don't stash the MSC value when present_get_ust_msc fails

Fredrik Höglund fredrik at kde.org
Mon Sep 28 19:55:43 PDT 2015


On Friday 11 September 2015, Michel Dänzer wrote:
> On 11.09.2015 06:33, Fredrik Höglund wrote:
> > Otherwise we stash an uninitalized value, and later use it to compute
> > the msc_offset for the window.  Also initialize ust and crtc_msc so we
> > never use uninitalized values when present_get_ust_msc fails.
> > 
> > This fixes clients getting stuck waiting indefinitely for an idle
> > event when a CRTC is turned off.
> > 
> > Signed-off-by: Fredrik Höglund <fredrik at kde.org>
> > ---
> >  present/present.c | 14 ++++++++------
> >  1 file changed, 8 insertions(+), 6 deletions(-)
> > 
> > diff --git a/present/present.c b/present/present.c
> > index a634601..7ddffbd 100644
> > --- a/present/present.c
> > +++ b/present/present.c
> > @@ -710,9 +710,9 @@ present_pixmap(WindowPtr window,
> >                 present_notify_ptr notifies,
> >                 int num_notifies)
> >  {
> > -    uint64_t                    ust;
> > +    uint64_t                    ust = 0;
> >      uint64_t                    target_msc;
> > -    uint64_t                    crtc_msc;
> > +    uint64_t                    crtc_msc = 0;
> >      int                         ret;
> >      present_vblank_ptr          vblank, tmp;
> >      ScreenPtr                   screen = window->drawable.pScreen;
> > @@ -734,13 +734,15 @@ present_pixmap(WindowPtr window,
> >              target_crtc = present_get_crtc(window);
> >      }
> >  
> > -    present_get_ust_msc(screen, target_crtc, &ust, &crtc_msc);
> > +    ret = present_get_ust_msc(screen, target_crtc, &ust, &crtc_msc);
> >  
> >      target_msc = present_window_to_crtc_msc(window, target_crtc, window_msc, crtc_msc);
> >  
> > -    /* Stash the current MSC away in case we need it later
> > -     */
> > -    window_priv->msc = crtc_msc;
> > +    if (ret == Success) {
> > +        /* Stash the current MSC away in case we need it later
> > +         */
> > +        window_priv->msc = crtc_msc;
> > +    }
> >  
> >      /* Adjust target_msc to match modulus
> >       */
> > 
> 
> My only doubt is about present_window_to_crtc_msc(). If target_msc
> doesn't match window_priv->crtc, presumably present_get_ust_msc() will
> fail there as well, so window_priv->msc (the last recorded valid MSC
> value for the window) will be added to window_priv->msc_offset. I
> suspect that's not right and might still cause similar trouble down the
> road.

window_priv->msc is updated after the call to present_window_to_crtc_msc(),
so the old MSC value will hopefully be valid in that call.  The bigger
issue is that crtc_msc is not valid, so we still set msc_offset to an
incorrect value.

I'm not sure if it's possible to fully fix this issue while still allowing
present_get_ust_msc() to fail.

The deadlock I'm seeing happens with an application that alternates
between calling GetSyncValuesOML() and SwapBuffersMscOML().  In the
GetSyncValuesOML() call, pixmap is NULL, so present_pixmap() picks the
CRTC stored in window_priv.  It's when that CRTC is off that we end up
storing an uninitialized value in window_priv->msc.  Note that
present_window_to_crtc_msc() doesn't update window_priv->msc_offset
in this case since the CRTC's match.  In the next call to SwapBuffersOML(),
pixmap is not NULL, so present_pixmap() calls present_get_crtc() which
returns NULL.  This causes present_window_to_crtc_msc() to update
window_priv->msc_offset using the now invalid window_priv->msc value.
As a result we compute a target MSC for the vblank that's several weeks
into the future.

> That said, it's probably an unlikely scenario, and your change certainly
> looks like an improvement.
> 
> 
> 

Fredrik



More information about the xorg-devel mailing list