Fix a couple of bugs in the offscreen allocator. One mostly harmless was
causing our search loop for evictable blocks to possibly skip a good candiate, and another was the allocator would occasionally use area->offset as if it was the base of the pixmap, while for a pixmap that is not in available state, it is not. This caused some funny miscalculation leading to overlapping pixmaps and accesses beyond the end of the framebuffer. To make things cleared, I renamed save_offset to base_offset, made sure it's the one used everywhere in the allocator, and only align "offset" for the client at the end of exaOffscreenAlloc().
This commit is contained in:
parent
8444a1f391
commit
12994b9afb
|
@ -47,9 +47,9 @@ typedef enum _ExaOffscreenState {
|
||||||
} ExaOffscreenState;
|
} ExaOffscreenState;
|
||||||
|
|
||||||
struct _ExaOffscreenArea {
|
struct _ExaOffscreenArea {
|
||||||
int offset;
|
int base_offset; /* allocation base */
|
||||||
int save_offset;
|
int offset; /* aligned offset */
|
||||||
int size;
|
int size; /* total allocation size */
|
||||||
int score;
|
int score;
|
||||||
pointer privData;
|
pointer privData;
|
||||||
|
|
||||||
|
|
|
@ -35,15 +35,17 @@ ExaOffscreenValidate (ScreenPtr pScreen)
|
||||||
ExaScreenPriv (pScreen);
|
ExaScreenPriv (pScreen);
|
||||||
ExaOffscreenArea *prev = 0, *area;
|
ExaOffscreenArea *prev = 0, *area;
|
||||||
|
|
||||||
assert (pExaScr->info->card.offScreenAreas->area.offset == 0);
|
assert (pExaScr->info->card.offScreenAreas->base_offset ==
|
||||||
|
pExaScr->info->card.offScreenBase);
|
||||||
for (area = pExaScr->info->card.offScreenAreas; area; area = area->next)
|
for (area = pExaScr->info->card.offScreenAreas; area; area = area->next)
|
||||||
{
|
{
|
||||||
|
assert (area->offset >= area->base_offset &&
|
||||||
|
area->offset < (area->base_offset -> area->size));
|
||||||
if (prev)
|
if (prev)
|
||||||
assert (prev->area.offset + prev->area.size == area->area.offset);
|
assert (prev->base_offset + prev->area.size == area->base_offset);
|
||||||
|
|
||||||
prev = area;
|
prev = area;
|
||||||
}
|
}
|
||||||
assert (prev->area.offset + prev->area.size == pExaScr->info->card.memorySize);
|
assert (prev->base_offset + prev->size == pExaScr->info->card.memorySize);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
#define ExaOffscreenValidate(s)
|
#define ExaOffscreenValidate(s)
|
||||||
|
@ -99,7 +101,7 @@ exaOffscreenAlloc (ScreenPtr pScreen, int size, int align,
|
||||||
|
|
||||||
/* adjust size to match alignment requirement */
|
/* adjust size to match alignment requirement */
|
||||||
real_size = size;
|
real_size = size;
|
||||||
tmp = area->offset % align;
|
tmp = area->base_offset % align;
|
||||||
if (tmp)
|
if (tmp)
|
||||||
real_size += (align - tmp);
|
real_size += (align - tmp);
|
||||||
|
|
||||||
|
@ -130,7 +132,7 @@ exaOffscreenAlloc (ScreenPtr pScreen, int size, int align,
|
||||||
|
|
||||||
/* adjust size needed to account for alignment loss for this area */
|
/* adjust size needed to account for alignment loss for this area */
|
||||||
real_size = size;
|
real_size = size;
|
||||||
tmp = begin->offset % align;
|
tmp = begin->base_offset % align;
|
||||||
if (tmp)
|
if (tmp)
|
||||||
real_size += (align - tmp);
|
real_size += (align - tmp);
|
||||||
|
|
||||||
|
@ -141,7 +143,7 @@ exaOffscreenAlloc (ScreenPtr pScreen, int size, int align,
|
||||||
{
|
{
|
||||||
if (scan->state == ExaOffscreenLocked) {
|
if (scan->state == ExaOffscreenLocked) {
|
||||||
/* Can't make room here, start after this locked area. */
|
/* Can't make room here, start after this locked area. */
|
||||||
begin = scan->next;
|
begin = scan;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
/* Score should only be non-zero for ExaOffscreenRemovable */
|
/* Score should only be non-zero for ExaOffscreenRemovable */
|
||||||
|
@ -167,7 +169,7 @@ exaOffscreenAlloc (ScreenPtr pScreen, int size, int align,
|
||||||
|
|
||||||
/* adjust size needed to account for alignment loss for this area */
|
/* adjust size needed to account for alignment loss for this area */
|
||||||
real_size = size;
|
real_size = size;
|
||||||
tmp = area->offset % align;
|
tmp = area->base_offset % align;
|
||||||
if (tmp)
|
if (tmp)
|
||||||
real_size += (align - tmp);
|
real_size += (align - tmp);
|
||||||
|
|
||||||
|
@ -192,7 +194,8 @@ exaOffscreenAlloc (ScreenPtr pScreen, int size, int align,
|
||||||
ExaOffscreenArea *new_area = xalloc (sizeof (ExaOffscreenArea));
|
ExaOffscreenArea *new_area = xalloc (sizeof (ExaOffscreenArea));
|
||||||
if (!new_area)
|
if (!new_area)
|
||||||
return NULL;
|
return NULL;
|
||||||
new_area->offset = area->offset + real_size;
|
new_area->base_offset = area->base_offset + real_size;
|
||||||
|
new_area->offset = new_area->base_offset;
|
||||||
new_area->size = area->size - real_size;
|
new_area->size = area->size - real_size;
|
||||||
new_area->state = ExaOffscreenAvail;
|
new_area->state = ExaOffscreenAvail;
|
||||||
new_area->save = NULL;
|
new_area->save = NULL;
|
||||||
|
@ -211,14 +214,13 @@ exaOffscreenAlloc (ScreenPtr pScreen, int size, int align,
|
||||||
area->privData = privData;
|
area->privData = privData;
|
||||||
area->save = save;
|
area->save = save;
|
||||||
area->score = 0;
|
area->score = 0;
|
||||||
|
area->offset = (area->base_offset + align - 1);
|
||||||
area->save_offset = area->offset;
|
|
||||||
area->offset = (area->offset + align - 1);
|
|
||||||
area->offset -= area->offset % align;
|
area->offset -= area->offset % align;
|
||||||
|
|
||||||
ExaOffscreenValidate (pScreen);
|
ExaOffscreenValidate (pScreen);
|
||||||
|
|
||||||
DBG_OFFSCREEN (("Alloc 0x%x -> 0x%x\n", size, area->offset));
|
DBG_OFFSCREEN (("Alloc 0x%x -> 0x%x (0x%x)\n", size,
|
||||||
|
area->base_offset, area->offset));
|
||||||
return area;
|
return area;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -295,12 +297,12 @@ exaOffscreenFree (ScreenPtr pScreen, ExaOffscreenArea *area)
|
||||||
ExaOffscreenArea *next = area->next;
|
ExaOffscreenArea *next = area->next;
|
||||||
ExaOffscreenArea *prev;
|
ExaOffscreenArea *prev;
|
||||||
|
|
||||||
DBG_OFFSCREEN (("Free 0x%x -> 0x%x\n", area->size, area->offset));
|
DBG_OFFSCREEN (("Free 0x%x -> 0x%x (0x%x)\n", area->size,
|
||||||
|
area->base_offset, area->offset));
|
||||||
ExaOffscreenValidate (pScreen);
|
ExaOffscreenValidate (pScreen);
|
||||||
|
|
||||||
area->state = ExaOffscreenAvail;
|
area->state = ExaOffscreenAvail;
|
||||||
area->save = NULL;
|
area->save = NULL;
|
||||||
area->offset = area->save_offset;
|
|
||||||
area->score = 0;
|
area->score = 0;
|
||||||
/*
|
/*
|
||||||
* Find previous area
|
* Find previous area
|
||||||
|
@ -365,7 +367,7 @@ exaOffscreenInit (ScreenPtr pScreen)
|
||||||
|
|
||||||
|
|
||||||
area->state = ExaOffscreenAvail;
|
area->state = ExaOffscreenAvail;
|
||||||
area->offset = pExaScr->info->card.offScreenBase;
|
area->base_offset = pExaScr->info->card.offScreenBase;
|
||||||
area->size = pExaScr->info->card.memorySize - area->offset;
|
area->size = pExaScr->info->card.memorySize - area->offset;
|
||||||
area->save = NULL;
|
area->save = NULL;
|
||||||
area->next = NULL;
|
area->next = NULL;
|
||||||
|
|
|
@ -47,9 +47,9 @@ typedef enum _ExaOffscreenState {
|
||||||
} ExaOffscreenState;
|
} ExaOffscreenState;
|
||||||
|
|
||||||
struct _ExaOffscreenArea {
|
struct _ExaOffscreenArea {
|
||||||
int offset;
|
int base_offset; /* allocation base */
|
||||||
int save_offset;
|
int offset; /* aligned offset */
|
||||||
int size;
|
int size; /* total allocation size */
|
||||||
int score;
|
int score;
|
||||||
pointer privData;
|
pointer privData;
|
||||||
|
|
||||||
|
|
|
@ -35,15 +35,17 @@ ExaOffscreenValidate (ScreenPtr pScreen)
|
||||||
ExaScreenPriv (pScreen);
|
ExaScreenPriv (pScreen);
|
||||||
ExaOffscreenArea *prev = 0, *area;
|
ExaOffscreenArea *prev = 0, *area;
|
||||||
|
|
||||||
assert (pExaScr->info->card.offScreenAreas->area.offset == 0);
|
assert (pExaScr->info->card.offScreenAreas->base_offset ==
|
||||||
|
pExaScr->info->card.offScreenBase);
|
||||||
for (area = pExaScr->info->card.offScreenAreas; area; area = area->next)
|
for (area = pExaScr->info->card.offScreenAreas; area; area = area->next)
|
||||||
{
|
{
|
||||||
|
assert (area->offset >= area->base_offset &&
|
||||||
|
area->offset < (area->base_offset -> area->size));
|
||||||
if (prev)
|
if (prev)
|
||||||
assert (prev->area.offset + prev->area.size == area->area.offset);
|
assert (prev->base_offset + prev->area.size == area->base_offset);
|
||||||
|
|
||||||
prev = area;
|
prev = area;
|
||||||
}
|
}
|
||||||
assert (prev->area.offset + prev->area.size == pExaScr->info->card.memorySize);
|
assert (prev->base_offset + prev->size == pExaScr->info->card.memorySize);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
#define ExaOffscreenValidate(s)
|
#define ExaOffscreenValidate(s)
|
||||||
|
@ -99,7 +101,7 @@ exaOffscreenAlloc (ScreenPtr pScreen, int size, int align,
|
||||||
|
|
||||||
/* adjust size to match alignment requirement */
|
/* adjust size to match alignment requirement */
|
||||||
real_size = size;
|
real_size = size;
|
||||||
tmp = area->offset % align;
|
tmp = area->base_offset % align;
|
||||||
if (tmp)
|
if (tmp)
|
||||||
real_size += (align - tmp);
|
real_size += (align - tmp);
|
||||||
|
|
||||||
|
@ -130,7 +132,7 @@ exaOffscreenAlloc (ScreenPtr pScreen, int size, int align,
|
||||||
|
|
||||||
/* adjust size needed to account for alignment loss for this area */
|
/* adjust size needed to account for alignment loss for this area */
|
||||||
real_size = size;
|
real_size = size;
|
||||||
tmp = begin->offset % align;
|
tmp = begin->base_offset % align;
|
||||||
if (tmp)
|
if (tmp)
|
||||||
real_size += (align - tmp);
|
real_size += (align - tmp);
|
||||||
|
|
||||||
|
@ -141,7 +143,7 @@ exaOffscreenAlloc (ScreenPtr pScreen, int size, int align,
|
||||||
{
|
{
|
||||||
if (scan->state == ExaOffscreenLocked) {
|
if (scan->state == ExaOffscreenLocked) {
|
||||||
/* Can't make room here, start after this locked area. */
|
/* Can't make room here, start after this locked area. */
|
||||||
begin = scan->next;
|
begin = scan;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
/* Score should only be non-zero for ExaOffscreenRemovable */
|
/* Score should only be non-zero for ExaOffscreenRemovable */
|
||||||
|
@ -167,7 +169,7 @@ exaOffscreenAlloc (ScreenPtr pScreen, int size, int align,
|
||||||
|
|
||||||
/* adjust size needed to account for alignment loss for this area */
|
/* adjust size needed to account for alignment loss for this area */
|
||||||
real_size = size;
|
real_size = size;
|
||||||
tmp = area->offset % align;
|
tmp = area->base_offset % align;
|
||||||
if (tmp)
|
if (tmp)
|
||||||
real_size += (align - tmp);
|
real_size += (align - tmp);
|
||||||
|
|
||||||
|
@ -192,7 +194,8 @@ exaOffscreenAlloc (ScreenPtr pScreen, int size, int align,
|
||||||
ExaOffscreenArea *new_area = xalloc (sizeof (ExaOffscreenArea));
|
ExaOffscreenArea *new_area = xalloc (sizeof (ExaOffscreenArea));
|
||||||
if (!new_area)
|
if (!new_area)
|
||||||
return NULL;
|
return NULL;
|
||||||
new_area->offset = area->offset + real_size;
|
new_area->base_offset = area->base_offset + real_size;
|
||||||
|
new_area->offset = new_area->base_offset;
|
||||||
new_area->size = area->size - real_size;
|
new_area->size = area->size - real_size;
|
||||||
new_area->state = ExaOffscreenAvail;
|
new_area->state = ExaOffscreenAvail;
|
||||||
new_area->save = NULL;
|
new_area->save = NULL;
|
||||||
|
@ -211,14 +214,13 @@ exaOffscreenAlloc (ScreenPtr pScreen, int size, int align,
|
||||||
area->privData = privData;
|
area->privData = privData;
|
||||||
area->save = save;
|
area->save = save;
|
||||||
area->score = 0;
|
area->score = 0;
|
||||||
|
area->offset = (area->base_offset + align - 1);
|
||||||
area->save_offset = area->offset;
|
|
||||||
area->offset = (area->offset + align - 1);
|
|
||||||
area->offset -= area->offset % align;
|
area->offset -= area->offset % align;
|
||||||
|
|
||||||
ExaOffscreenValidate (pScreen);
|
ExaOffscreenValidate (pScreen);
|
||||||
|
|
||||||
DBG_OFFSCREEN (("Alloc 0x%x -> 0x%x\n", size, area->offset));
|
DBG_OFFSCREEN (("Alloc 0x%x -> 0x%x (0x%x)\n", size,
|
||||||
|
area->base_offset, area->offset));
|
||||||
return area;
|
return area;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -295,12 +297,12 @@ exaOffscreenFree (ScreenPtr pScreen, ExaOffscreenArea *area)
|
||||||
ExaOffscreenArea *next = area->next;
|
ExaOffscreenArea *next = area->next;
|
||||||
ExaOffscreenArea *prev;
|
ExaOffscreenArea *prev;
|
||||||
|
|
||||||
DBG_OFFSCREEN (("Free 0x%x -> 0x%x\n", area->size, area->offset));
|
DBG_OFFSCREEN (("Free 0x%x -> 0x%x (0x%x)\n", area->size,
|
||||||
|
area->base_offset, area->offset));
|
||||||
ExaOffscreenValidate (pScreen);
|
ExaOffscreenValidate (pScreen);
|
||||||
|
|
||||||
area->state = ExaOffscreenAvail;
|
area->state = ExaOffscreenAvail;
|
||||||
area->save = NULL;
|
area->save = NULL;
|
||||||
area->offset = area->save_offset;
|
|
||||||
area->score = 0;
|
area->score = 0;
|
||||||
/*
|
/*
|
||||||
* Find previous area
|
* Find previous area
|
||||||
|
@ -365,7 +367,7 @@ exaOffscreenInit (ScreenPtr pScreen)
|
||||||
|
|
||||||
|
|
||||||
area->state = ExaOffscreenAvail;
|
area->state = ExaOffscreenAvail;
|
||||||
area->offset = pExaScr->info->card.offScreenBase;
|
area->base_offset = pExaScr->info->card.offScreenBase;
|
||||||
area->size = pExaScr->info->card.memorySize - area->offset;
|
area->size = pExaScr->info->card.memorySize - area->offset;
|
||||||
area->save = NULL;
|
area->save = NULL;
|
||||||
area->next = NULL;
|
area->next = NULL;
|
||||||
|
|
|
@ -35,15 +35,17 @@ ExaOffscreenValidate (ScreenPtr pScreen)
|
||||||
ExaScreenPriv (pScreen);
|
ExaScreenPriv (pScreen);
|
||||||
ExaOffscreenArea *prev = 0, *area;
|
ExaOffscreenArea *prev = 0, *area;
|
||||||
|
|
||||||
assert (pExaScr->info->card.offScreenAreas->area.offset == 0);
|
assert (pExaScr->info->card.offScreenAreas->base_offset ==
|
||||||
|
pExaScr->info->card.offScreenBase);
|
||||||
for (area = pExaScr->info->card.offScreenAreas; area; area = area->next)
|
for (area = pExaScr->info->card.offScreenAreas; area; area = area->next)
|
||||||
{
|
{
|
||||||
|
assert (area->offset >= area->base_offset &&
|
||||||
|
area->offset < (area->base_offset -> area->size));
|
||||||
if (prev)
|
if (prev)
|
||||||
assert (prev->area.offset + prev->area.size == area->area.offset);
|
assert (prev->base_offset + prev->area.size == area->base_offset);
|
||||||
|
|
||||||
prev = area;
|
prev = area;
|
||||||
}
|
}
|
||||||
assert (prev->area.offset + prev->area.size == pExaScr->info->card.memorySize);
|
assert (prev->base_offset + prev->size == pExaScr->info->card.memorySize);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
#define ExaOffscreenValidate(s)
|
#define ExaOffscreenValidate(s)
|
||||||
|
@ -99,7 +101,7 @@ exaOffscreenAlloc (ScreenPtr pScreen, int size, int align,
|
||||||
|
|
||||||
/* adjust size to match alignment requirement */
|
/* adjust size to match alignment requirement */
|
||||||
real_size = size;
|
real_size = size;
|
||||||
tmp = area->offset % align;
|
tmp = area->base_offset % align;
|
||||||
if (tmp)
|
if (tmp)
|
||||||
real_size += (align - tmp);
|
real_size += (align - tmp);
|
||||||
|
|
||||||
|
@ -130,7 +132,7 @@ exaOffscreenAlloc (ScreenPtr pScreen, int size, int align,
|
||||||
|
|
||||||
/* adjust size needed to account for alignment loss for this area */
|
/* adjust size needed to account for alignment loss for this area */
|
||||||
real_size = size;
|
real_size = size;
|
||||||
tmp = begin->offset % align;
|
tmp = begin->base_offset % align;
|
||||||
if (tmp)
|
if (tmp)
|
||||||
real_size += (align - tmp);
|
real_size += (align - tmp);
|
||||||
|
|
||||||
|
@ -141,7 +143,7 @@ exaOffscreenAlloc (ScreenPtr pScreen, int size, int align,
|
||||||
{
|
{
|
||||||
if (scan->state == ExaOffscreenLocked) {
|
if (scan->state == ExaOffscreenLocked) {
|
||||||
/* Can't make room here, start after this locked area. */
|
/* Can't make room here, start after this locked area. */
|
||||||
begin = scan->next;
|
begin = scan;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
/* Score should only be non-zero for ExaOffscreenRemovable */
|
/* Score should only be non-zero for ExaOffscreenRemovable */
|
||||||
|
@ -167,7 +169,7 @@ exaOffscreenAlloc (ScreenPtr pScreen, int size, int align,
|
||||||
|
|
||||||
/* adjust size needed to account for alignment loss for this area */
|
/* adjust size needed to account for alignment loss for this area */
|
||||||
real_size = size;
|
real_size = size;
|
||||||
tmp = area->offset % align;
|
tmp = area->base_offset % align;
|
||||||
if (tmp)
|
if (tmp)
|
||||||
real_size += (align - tmp);
|
real_size += (align - tmp);
|
||||||
|
|
||||||
|
@ -192,7 +194,8 @@ exaOffscreenAlloc (ScreenPtr pScreen, int size, int align,
|
||||||
ExaOffscreenArea *new_area = xalloc (sizeof (ExaOffscreenArea));
|
ExaOffscreenArea *new_area = xalloc (sizeof (ExaOffscreenArea));
|
||||||
if (!new_area)
|
if (!new_area)
|
||||||
return NULL;
|
return NULL;
|
||||||
new_area->offset = area->offset + real_size;
|
new_area->base_offset = area->base_offset + real_size;
|
||||||
|
new_area->offset = new_area->base_offset;
|
||||||
new_area->size = area->size - real_size;
|
new_area->size = area->size - real_size;
|
||||||
new_area->state = ExaOffscreenAvail;
|
new_area->state = ExaOffscreenAvail;
|
||||||
new_area->save = NULL;
|
new_area->save = NULL;
|
||||||
|
@ -211,14 +214,13 @@ exaOffscreenAlloc (ScreenPtr pScreen, int size, int align,
|
||||||
area->privData = privData;
|
area->privData = privData;
|
||||||
area->save = save;
|
area->save = save;
|
||||||
area->score = 0;
|
area->score = 0;
|
||||||
|
area->offset = (area->base_offset + align - 1);
|
||||||
area->save_offset = area->offset;
|
|
||||||
area->offset = (area->offset + align - 1);
|
|
||||||
area->offset -= area->offset % align;
|
area->offset -= area->offset % align;
|
||||||
|
|
||||||
ExaOffscreenValidate (pScreen);
|
ExaOffscreenValidate (pScreen);
|
||||||
|
|
||||||
DBG_OFFSCREEN (("Alloc 0x%x -> 0x%x\n", size, area->offset));
|
DBG_OFFSCREEN (("Alloc 0x%x -> 0x%x (0x%x)\n", size,
|
||||||
|
area->base_offset, area->offset));
|
||||||
return area;
|
return area;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -295,12 +297,12 @@ exaOffscreenFree (ScreenPtr pScreen, ExaOffscreenArea *area)
|
||||||
ExaOffscreenArea *next = area->next;
|
ExaOffscreenArea *next = area->next;
|
||||||
ExaOffscreenArea *prev;
|
ExaOffscreenArea *prev;
|
||||||
|
|
||||||
DBG_OFFSCREEN (("Free 0x%x -> 0x%x\n", area->size, area->offset));
|
DBG_OFFSCREEN (("Free 0x%x -> 0x%x (0x%x)\n", area->size,
|
||||||
|
area->base_offset, area->offset));
|
||||||
ExaOffscreenValidate (pScreen);
|
ExaOffscreenValidate (pScreen);
|
||||||
|
|
||||||
area->state = ExaOffscreenAvail;
|
area->state = ExaOffscreenAvail;
|
||||||
area->save = NULL;
|
area->save = NULL;
|
||||||
area->offset = area->save_offset;
|
|
||||||
area->score = 0;
|
area->score = 0;
|
||||||
/*
|
/*
|
||||||
* Find previous area
|
* Find previous area
|
||||||
|
@ -365,7 +367,7 @@ exaOffscreenInit (ScreenPtr pScreen)
|
||||||
|
|
||||||
|
|
||||||
area->state = ExaOffscreenAvail;
|
area->state = ExaOffscreenAvail;
|
||||||
area->offset = pExaScr->info->card.offScreenBase;
|
area->base_offset = pExaScr->info->card.offScreenBase;
|
||||||
area->size = pExaScr->info->card.memorySize - area->offset;
|
area->size = pExaScr->info->card.memorySize - area->offset;
|
||||||
area->save = NULL;
|
area->save = NULL;
|
||||||
area->next = NULL;
|
area->next = NULL;
|
||||||
|
|
Loading…
Reference in New Issue