diff options
author | Xinyu Chen <b03824@freescale.com> | 2011-10-25 15:43:54 +0800 |
---|---|---|
committer | Xinyu Chen <b03824@freescale.com> | 2011-10-26 10:14:32 +0800 |
commit | f670cbc12d28a642c8b73080684115c57f0cdd98 (patch) | |
tree | 8f9c47db3e4d8a40e809ae449afa596b9d4e026b /drivers | |
parent | bc1aa21f870e3afb3a7444d50b9ad1a8175aa87b (diff) |
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>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/mxc/amd-gpu/common/gsl_memmgr.c | 73 |
1 files changed, 44 insertions, 29 deletions
diff --git a/drivers/mxc/amd-gpu/common/gsl_memmgr.c b/drivers/mxc/amd-gpu/common/gsl_memmgr.c index 75f250ae59b1..f331bb547542 100644 --- a/drivers/mxc/amd-gpu/common/gsl_memmgr.c +++ b/drivers/mxc/amd-gpu/common/gsl_memmgr.c @@ -479,6 +479,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; kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "--> int kgsl_memarena_alloc(gsl_memarena_t *memarena=0x%08x, gsl_flags_t flags=0x%08x, int size=%d, gsl_memdesc_t *memdesc=%M)\n", memarena, flags, size, memdesc ); @@ -542,17 +544,34 @@ 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; @@ -561,50 +580,46 @@ 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; + ptrbest = ptrbest->prev; kgsl_memarena_releasememblknode(memarena, p); } - } - - ptrfree = ptrfree->next; - - } while (!freeblk && ptrfree != memarena->freelist.allocrover); + } GSL_MEMARENA_UNLOCK(); |