mirror of https://github.com/thesofproject/sof.git
alloc: fix and improve the block allocation algorithm
The block allocation algorithm, as implemented in _balloc(), is first trying to find a single free memory block to satisfy the request. If that fails it is then trying to allocate several blocks in a sequence. That part is implemented wrongly. It can end up allocating multiple such block sequences, and not using but leaking them instead. This patch first simplifies the search for a single suitable buffer, then fixes the leakage. Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
This commit is contained in:
parent
8c62c4457c
commit
c8f1edfaa4
|
@ -656,40 +656,32 @@ void *_balloc(int zone, uint32_t caps, size_t bytes)
|
|||
for (i = 0; i < heap->blocks; i++) {
|
||||
map = &heap->map[i];
|
||||
|
||||
/* is block big enough */
|
||||
if (map->block_size < bytes)
|
||||
continue;
|
||||
|
||||
/* does block have free space */
|
||||
if (map->free_count == 0)
|
||||
continue;
|
||||
|
||||
/* allocate block */
|
||||
ptr = alloc_block(heap, i, caps);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* request spans > 1 block */
|
||||
|
||||
/* only 1 choice for block size */
|
||||
if (heap->blocks == 1) {
|
||||
ptr = alloc_cont_blocks(heap, 0, caps, bytes);
|
||||
goto out;
|
||||
} else {
|
||||
|
||||
/* find best block size for request */
|
||||
for (i = 0; i < heap->blocks; i++) {
|
||||
map = &heap->map[i];
|
||||
|
||||
/* allocate is block size smaller than request */
|
||||
if (map->block_size < bytes)
|
||||
alloc_cont_blocks(heap, i, caps, bytes);
|
||||
/* Check if blocks are big enough and at least one is free */
|
||||
if (map->block_size >= bytes && map->free_count) {
|
||||
/* found: grab a block */
|
||||
ptr = alloc_block(heap, i, caps);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ptr = alloc_cont_blocks(heap, heap->blocks - 1, caps, bytes);
|
||||
/* request spans > 1 block */
|
||||
if (!ptr) {
|
||||
/*
|
||||
* Find the best block size for request. We know, that we failed
|
||||
* to find a single large enough block, so, skip those.
|
||||
*/
|
||||
for (i = heap->blocks - 1; i >= 0; i--) {
|
||||
map = &heap->map[i];
|
||||
|
||||
/* allocate if block size is smaller than request */
|
||||
if (heap->size >= bytes && map->block_size < bytes) {
|
||||
ptr = alloc_cont_blocks(heap, i, caps, bytes);
|
||||
if (ptr)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
if (ptr && ((zone & RZONE_FLAG_MASK) == RZONE_FLAG_UNCACHED))
|
||||
ptr = cache_to_uncache(ptr);
|
||||
|
||||
|
|
Loading…
Reference in New Issue