On 2012-11-10 00:59 +0100, amarao wrote: >>>> Fatal server error: >>>> [ 90638.275] Caught signal 11 (Segmentation fault). Server aborting >>>> [ 90638.275] >>>> [ 90638.276] >>>> >>>> After that there is constant flood of messages from 'EQ overflow >>>> continuing' >> >> This is essentially the same backtrace that you already reported in >> #686474, sorry for not having followed up on that. It seems that this >> is triggered by enabling the "GLXVBlank" option in xorg.conf, and that >> there is a fix in version 1.0.3¹. I'll see to include this in the >> Debian package. >> > > OK, I'll disable it and try to play for some time to see if problems > stops.
It would be even better if you could apply the attached patch or build the package from git¹. I don't have time this weekend, but I intend to upload in a few days after asking what other fixes might be suitable for wheezy. Cheers, Sven ¹ http://anonscm.debian.org/gitweb/?p=pkg-xorg/driver/xserver-xorg-video-nouveau.git
diff --git a/src/nouveau_dri2.c b/src/nouveau_dri2.c index 0b3cc38..44fa255 100644 --- a/src/nouveau_dri2.c +++ b/src/nouveau_dri2.c @@ -412,6 +412,7 @@ nouveau_dri2_schedule_swap(ClientPtr client, DrawablePtr draw, { struct nouveau_dri2_vblank_state *s; CARD64 current_msc, expect_msc; + CARD64 current_ust; int ret; /* Initialize a swap structure */ @@ -423,9 +424,9 @@ nouveau_dri2_schedule_swap(ClientPtr client, DrawablePtr draw, { SWAP, client, draw->id, dst, src, func, data, 0 }; if (can_sync_to_vblank(draw)) { - /* Get current sequence */ + /* Get current sequence and vblank time*/ ret = nouveau_wait_vblank(draw, DRM_VBLANK_RELATIVE, 0, - ¤t_msc, NULL, NULL); + ¤t_msc, ¤t_ust, NULL); if (ret) goto fail; @@ -445,24 +446,48 @@ nouveau_dri2_schedule_swap(ClientPtr client, DrawablePtr draw, if (*target_msc == 0) *target_msc = 1; + /* Swap at next possible vblank requested? */ + if (current_msc >= *target_msc - 1) { + /* Special case: Need to swap at next vblank. + * Schedule swap immediately, bypassing the kernel + * vblank event mechanism to avoid a dangerous race + * between the client and the x-server vblank event + * dispatch in the main x-server dispatch loop when + * the swap_limit is set to 2 for triple-buffering. + * + * This also optimizes for the common case of swap + * at next vblank, avoiding vblank dispatch delay. + */ + s->frame = 1 + ((unsigned int) current_msc & 0xffffffff); + *target_msc = 1 + current_msc; + nouveau_dri2_finish_swap(draw, current_msc, + (unsigned int) (current_ust / 1000000), + (unsigned int) (current_ust % 1000000), + s); + return TRUE; + } + + /* This is a swap in the future, ie. the vblank event will + * only get dispatched at least 2 vblanks into the future. + */ + #if DRI2INFOREC_VERSION >= 6 - /* Is this a swap in the future, ie. the vblank event will - * not be immediately dispatched, but only at a future vblank? - * If so, we need to temporarily lower the swaplimit to 1, so - * that DRI2GetBuffersWithFormat() requests from the client get + /* On XOrg 1.12+ we need to temporarily lower the swaplimit to 1, + * so that DRI2GetBuffersWithFormat() requests from the client get * deferred in the x-server until the vblank event has been * dispatched to us and nouveau_dri2_finish_swap() is done. If * we wouldn't do this, DRI2GetBuffersWithFormat() would operate * on wrong (pre-swap) buffers, and cause a segfault later on in - * nouveau_dri2_finish_swap(). Our vblank event handler restores + * nouveau_dri2_finish_swap(). Our vblank event handler will restore * the old swaplimit immediately after nouveau_dri2_finish_swap() - * is done, so we still get 1 video refresh cycle worth of - * triple-buffering. For a swap at next vblank, dispatch of the - * vblank event happens immediately, so there isn't any need - * for this lowered swaplimit. + * is done, so we still get 1 video refresh cycle worth of triple- + * buffering, because the client can start rendering again 1 cycle + * before the pending swap is completed. + * + * The same race would happen for the "swap at next vblank" case, + * but the special case "swap immediately" code above prevents this. */ - if (current_msc < *target_msc - 1) - DRI2SwapLimit(draw, 1); + DRI2SwapLimit(draw, 1); #endif /* Request a vblank event one frame before the target */