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++) {
|
for (i = 0; i < heap->blocks; i++) {
|
||||||
map = &heap->map[i];
|
map = &heap->map[i];
|
||||||
|
|
||||||
/* is block big enough */
|
/* Check if blocks are big enough and at least one is free */
|
||||||
if (map->block_size < bytes)
|
if (map->block_size >= bytes && map->free_count) {
|
||||||
continue;
|
/* found: grab a block */
|
||||||
|
|
||||||
/* does block have free space */
|
|
||||||
if (map->free_count == 0)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
/* allocate block */
|
|
||||||
ptr = alloc_block(heap, i, caps);
|
ptr = alloc_block(heap, i, caps);
|
||||||
goto out;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* request spans > 1 block */
|
/* request spans > 1 block */
|
||||||
|
if (!ptr) {
|
||||||
/* only 1 choice for block size */
|
/*
|
||||||
if (heap->blocks == 1) {
|
* Find the best block size for request. We know, that we failed
|
||||||
ptr = alloc_cont_blocks(heap, 0, caps, bytes);
|
* to find a single large enough block, so, skip those.
|
||||||
goto out;
|
*/
|
||||||
} else {
|
for (i = heap->blocks - 1; i >= 0; i--) {
|
||||||
|
|
||||||
/* find best block size for request */
|
|
||||||
for (i = 0; i < heap->blocks; i++) {
|
|
||||||
map = &heap->map[i];
|
map = &heap->map[i];
|
||||||
|
|
||||||
/* allocate is block size smaller than request */
|
/* allocate if block size is smaller than request */
|
||||||
if (map->block_size < bytes)
|
if (heap->size >= bytes && map->block_size < bytes) {
|
||||||
alloc_cont_blocks(heap, i, caps, bytes);
|
ptr = alloc_cont_blocks(heap, i, caps, bytes);
|
||||||
|
if (ptr)
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ptr = alloc_cont_blocks(heap, heap->blocks - 1, caps, bytes);
|
|
||||||
|
|
||||||
out:
|
|
||||||
if (ptr && ((zone & RZONE_FLAG_MASK) == RZONE_FLAG_UNCACHED))
|
if (ptr && ((zone & RZONE_FLAG_MASK) == RZONE_FLAG_UNCACHED))
|
||||||
ptr = cache_to_uncache(ptr);
|
ptr = cache_to_uncache(ptr);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue