[X-tt-list:103] Re: (patch seq: 5752) A patch for preventing XAA crash

Back to archive index

David Dawes dawes****@XFree*****
2003年 8月 15日 (金) 10:55:37 JST


On Thu, Aug 14, 2003 at 04:17:41PM -0700, Mark Vojkovich wrote:
>On Thu, 14 Aug 2003, David Dawes wrote:
>
>> >
>> >   XAACacheTile() should have never been called if no slots existed.
>> >MaxCacheableTileWidth and MaxCacheableTileHeight should have been
>> >consulted at some point.
>> 
>> OK, we need to see what those values are at this point.  XAAPaintWindow(),
>> where the crash is apparently happening, does have a test for them, so
>> maybe there's getting set incorrectly somewhere.
>> 
>>         if(infoRec->UsingPixmapCache &&
>>             infoRec->FillCacheBltRects && !NoCache &&
>>             ((what == PW_BORDER) ||
>>                 (pPix->drawable.height != pWin->drawable.height) ||
>>                 (pPix->drawable.width != pWin->drawable.width)) &&
>>             (pPix->drawable.height <= infoRec->MaxCacheableTileHeight) &&
>>             (pPix->drawable.width <= infoRec->MaxCacheableTileWidth)) {
>> 
>>              XAACacheInfoPtr pCache =
>>                         (*infoRec->CacheTile)(infoRec->pScrn, pPix);
>>              (*infoRec->FillCacheBltRects)(infoRec->pScrn, GXcopy, ~0,
>>                                         nBox, pBox, xorg, yorg, pCache);
>>              return;
>>         }
>> 
>> This check assumes that if there are no 256x256 slots there won't
>> be any 512x512 slots.  I'm not 100% sure if it can ever happen that
>> there are 512x512 slots but no 256x256 slots.  If the debugging
>> could be extended to print both infoRec->MaxCacheableTileHeight
>> and Num512, it should clarify if this is the problem or not.
>
>   It's expected that if there are 512x512 slots there will be
>smaller slots.  The logic that sets up the slots in XAAInitPixmapCache
>is supposed to ensure that.

I played around a little with some unusual cases.  If the memory is very
fragmented, I can find a case where there are 4 512x512 slots and no
256x256 slots.  The trick here is to have enough boxes for 4 512 slots
and lots of 128 slots, but none for any 256 slots to get allocated in
the first round.  If there are enough 128x128 slots, the target for
512x512 slots will remain at 4 and none of them get split into 256x256
slots.

A case that gives this result is 4 512x512 boxes and 70 250x250 boxes:

128: 32, 256: 0, 512: 4, partial: 288
max cacheable: 512x512

I've attached the test program I used to look at various cases.

David
-------------- next part --------------
#define MAX_128             32
#define MAX_256             32
#define MAX_512             16

void 
XAAInitPixmapCache(int *xin, int *yin, int nBox)
{
   int Num512, Num256, Num128, NumPartial, NumColor, NumMono;
   int Target512, Target256;
   int x, y, w, h, ntotal, granularity, width, height, i;
   int MaxPartialWidth, MaxPartialHeight;
   int MaxCacheableTileWidth, MaxCacheableTileHeight;
   int x1 = 0, y1 = 0;
   int x2, y2;

   MaxCacheableTileWidth = 0;
   MaxCacheableTileHeight = 0;

   Num512 = Num256 = Num128 = NumPartial = NumMono = NumColor = 0;
   granularity = 0;

   /* go through the boxes and break it into as many pieces as we can fit */

   printf("nBox: %d\n");

   while(nBox--) {
	x2 = xin[nBox];
	y2 = yin[nBox];

	x = x1;
	if(granularity) {
	    int tmp = x % granularity;
	    if(tmp) x += (granularity - tmp);
	}
	width = x2 - x;
        if(width <= 0) {continue;}

	y = y1;
        height = y2 - y;

        for(h = 0; h <= (height - 512); h += 512) {
	    for(w = 0; w <= (width - 512); w += 512) {
		Num512++;	
		printf("Num512 -> %d\n", Num512);
	    }
	    for(; w <= (width - 256); w += 256) {
		Num256 += 2;
		printf("Num256 -> %d\n", Num256);
	    }
	    for(; w <= (width - 128); w += 128) {
		Num128 += 4;
		printf("Num128 -> %d\n", Num128);
	    }
	    if(w < width) {
		int d = width - w;
		NumPartial += 4;
            }
	}
        for(; h <= (height - 256); h += 256) {
	    for(w = 0; w <= (width - 256); w += 256) {
		Num256++;
		printf("Num256 -> %d\n", Num256);
	    }
	    for(; w <= (width - 128); w += 128) {
		Num128 += 2;
		printf("Num128 -> %d\n", Num128);
	    }
	    if(w < width) {
		int d = width - w;
		NumPartial += 2;
            }
        }
        for(; h <= (height - 128); h += 128) {
	    for(w = 0; w <= (width - 128); w += 128) {
		Num128++;
		printf("Num128 -> %d\n", Num128);
	    }
	    if(w < width) {
		NumPartial++;
            }
        }
        if(h < height) {
	    int d = height - h;
	    for(w = 0; w <= (width - 128); w += 128) {
		NumPartial++;
	    }
	    if(w < width) {
		NumPartial++;
            }
        }
   }


/* 
   by this point we've carved the space into as many 512x512, 256x256
	and 128x128 blocks as we could fit.  We will then break larger
	blocks into smaller ones if we need to.  The rules are as follows:

     512x512 -
	1) Don't take up more than half the memory.
	2) Don't bother if you can't get at least four.
	3) Don't make more than MAX_512.

     256x256 -
	1) Don't take up more than a quarter of the memory enless there
		aren't any 512x512s.  Then we can take up to half.
	2) Don't bother if you can't get at least four.
	3) Don't make more than MAX_256.

     128x128 -
	1) Don't make more than MAX_128.

     We don't bother with the partial blocks unless we can use them
     for 8x8 pattern fills or we are short on larger blocks.

*/

    ntotal = Num128 + (Num256<<2) + (Num512<<4);   
	
    Target512 = ntotal >> 5;
    if(Target512 < 4) Target512 = 0;
    if(!Target512) Target256 = ntotal >> 3;
    else Target256 = ntotal >> 4;
    if(Target256 < 4) Target256 = 0;

    printf("Targets: 512: %d, 256: %d\n", Target512, Target256);

    if(!Num512) { /* no room */
    } else if((Num512 < 4) || (!Target512)) {
	while(Num512) {
	   Num256 += 4; Num512--;
		printf("Num512 -> %d\n", Num512);
		printf("Num256 -> %d\n", Num256);
	}
    } else if((Num512 > MAX_512) || (Num512 > Target512)){
	while(Num512 > MAX_512) {
	   Num256 += 4; Num512--;
		printf("Num512 -> %d\n", Num512);
		printf("Num256 -> %d\n", Num256);
	}
	while(Num512 > Target512) {
	    if(Num256 < MAX_256) {
		Num256 += 4; Num512--;
		printf("Num512 -> %d\n", Num512);
		printf("Num256 -> %d\n", Num256);
	    } else break;
	}
    }

    if(!Num256) { /* no room */
    } else if((Num256 < 4) || (!Target256)) {
	while(Num256) {
	   Num128 += 4; Num256--;
		printf("Num256 -> %d\n", Num256);
		printf("Num128 -> %d\n", Num128);
	}
    } else if((Num256 > MAX_256) || (Num256 > Target256)) {
	while(Num256 > MAX_256) {
	   Num128 += 4; Num256--;
		printf("Num256 -> %d\n", Num256);
		printf("Num128 -> %d\n", Num128);
	}
	while(Num256 > Target256) {
	    if(Num128 < MAX_128) {
		Num128 += 4; Num256--;
		printf("Num256 -> %d\n", Num256);
		printf("Num128 -> %d\n", Num128);
	    } else break;
	}
    } 

    if(Num128 && ((Num128 < 4) || (Num128 > MAX_128))) {
	int max = (Num128 > MAX_128) ? MAX_128 : 0;

	/*
	 * Note: next is set in this way to work around a code generation
	 * bug in gcc 2.7.2.3.
	 */
	while(Num128 > max) {
	   NumPartial++; Num128--;
		printf("Num128 -> %d\n", Num128);
	}
    }

    MaxPartialHeight = MaxPartialWidth = 0;

    if(Num128) 
	MaxCacheableTileWidth = MaxCacheableTileHeight = 128;
    if(Num256) 
	MaxCacheableTileWidth = MaxCacheableTileHeight = 256;
    if(Num512) 
	MaxCacheableTileWidth = MaxCacheableTileHeight = 512;

    printf("128: %d, 256: %d, 512: %d, partial: %d\n", Num128, Num256, Num512,
	   NumPartial);
    printf("max cacheable: %dx%d\n", MaxCacheableTileWidth,
	   MaxCacheableTileHeight);
}

main()
{
#define MAX_I 100

	int x[MAX_I], y[MAX_I], i, n;

	while (1) {
		i = 0;
		do {
			printf("Enter width, height, num: (0 0 0 to end)\n");
			scanf("%d %d %d", &(x[i]), &(y[i]), &n);
			i++;
			if (n) {
				while (--n && i < MAX_I) {
					x[i] = x[i - 1];
					y[i] = y[i - 1];
					i++;
				}
			}
		} while (x[i - 1] != 0 && i < MAX_I);

		XAAInitPixmapCache(x, y, i);
	}
}


X-tt-list メーリングリストの案内
Back to archive index