ENGR00160722 amd gpu: add best fit algorithm to memory manager

The AMD gpu driver memory manager is stupid to allocating
a memory block from the first free block. Neither check the
best fit free block. Here just add a little codes to
let allocation to find a best size fitted free block.
To avoid memory fragement.

Signed-off-by: Xinyu Chen <xinyu.chen@freescale.com>
This commit is contained in:
Xinyu Chen
2012-11-19 11:52:31 -06:00
committed by Matt Sealey
parent f7501b49b9
commit 4c741b2e31

View File

@@ -486,6 +486,8 @@ kgsl_memarena_alloc(gsl_memarena_t *memarena, gsl_flags_t flags, int size, gsl_m
unsigned int blksize;
unsigned int baseaddr, alignedbaseaddr, alignfragment;
int freeblk, alignmentshift;
memblk_t *ptrbest = NULL;
unsigned int fitsize = ~0UL;
int err;
kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE,
@@ -554,17 +556,33 @@ kgsl_memarena_alloc(gsl_memarena_t *memarena, gsl_flags_t flags, int size, gsl_m
do
{
int aba;
// align base address
baseaddr = ptrfree->blkaddr + memarena->gpubaseaddr;
alignedbaseaddr = gsl_memarena_alignaddr(baseaddr, alignmentshift);
aba = gsl_memarena_alignaddr(baseaddr, alignmentshift);
alignfragment = alignedbaseaddr - baseaddr;
if (((aba - baseaddr) == 0) && (ptrfree->blksize == blksize)) {
ptrbest = ptrfree;
alignfragment = aba - baseaddr;
alignedbaseaddr = aba;
result = GSL_SUCCESS;
break;
}
if (ptrfree->blksize >= blksize + alignfragment)
if ((ptrfree->blksize >= (blksize + aba - baseaddr)) &&
(fitsize > ptrfree->blksize))
{
fitsize = ptrfree->blksize;
alignfragment = aba - baseaddr;
alignedbaseaddr = aba;
result = GSL_SUCCESS;
freeblk = 1;
ptrbest = ptrfree;
}
ptrfree = ptrfree->next;
} while (ptrfree != memarena->freelist.allocrover);
if (ptrbest) {
memdesc->gpuaddr = alignedbaseaddr;
memdesc->hostptr = kgsl_memarena_gethostptr(memarena, memdesc->gpuaddr);
memdesc->size = blksize;
@@ -573,52 +591,47 @@ kgsl_memarena_alloc(gsl_memarena_t *memarena, gsl_flags_t flags, int size, gsl_m
{
// insert new node to handle newly created (small) fragment
p = kgsl_memarena_getmemblknode(memarena);
p->blkaddr = ptrfree->blkaddr;
p->blkaddr = ptrbest->blkaddr;
p->blksize = alignfragment;
p->next = ptrfree;
p->prev = ptrfree->prev;
ptrfree->prev->next = p;
ptrfree->prev = p;
p->next = ptrbest;
p->prev = ptrbest->prev;
ptrbest->prev->next = p;
ptrbest->prev = p;
if (ptrfree == memarena->freelist.head)
if (ptrbest == memarena->freelist.head)
{
memarena->freelist.head = p;
}
}
ptrfree->blkaddr += alignfragment + blksize;
ptrfree->blksize -= alignfragment + blksize;
ptrbest->blkaddr += alignfragment + blksize;
ptrbest->blksize -= alignfragment + blksize;
memarena->freelist.allocrover = ptrfree;
memarena->freelist.allocrover = ptrbest;
if (ptrfree->blksize == 0 && ptrfree != ptrlast)
if ((ptrbest->blksize == 0) && (ptrbest != ptrlast))
{
ptrfree->prev->next = ptrfree->next;
ptrfree->next->prev = ptrfree->prev;
if (ptrfree == memarena->freelist.head)
ptrbest->prev->next = ptrbest->next;
ptrbest->next->prev = ptrbest->prev;
if (ptrbest == memarena->freelist.head)
{
memarena->freelist.head = ptrfree->next;
memarena->freelist.head = ptrbest->next;
}
if (ptrfree == memarena->freelist.allocrover)
if (ptrbest == memarena->freelist.allocrover)
{
memarena->freelist.allocrover = ptrfree->next;
memarena->freelist.allocrover = ptrbest->next;
}
if (ptrfree == memarena->freelist.freerover)
if (ptrbest == memarena->freelist.freerover)
{
memarena->freelist.freerover = ptrfree->prev;
memarena->freelist.freerover = ptrbest->prev;
}
p = ptrfree;
ptrfree = ptrfree->prev;
p = ptrbest;
ptrfree = ptrbest->prev;
kgsl_memarena_releasememblknode(memarena, p);
}
}
ptrfree = ptrfree->next;
} while (!freeblk && ptrfree != memarena->freelist.allocrover);
mutex_unlock(&memarena->lock);
if (result == GSL_SUCCESS)