sys: heap: add support for heap listener

This adds notification in the heap code to emit events for
heap listeners.

Signed-off-by: Daniel Leung <daniel.leung@intel.com>
This commit is contained in:
Daniel Leung 2022-01-05 14:06:12 -08:00 committed by Anas Nashif
commit f6e2705719
2 changed files with 63 additions and 2 deletions

View file

@ -51,6 +51,13 @@ config SYS_HEAP_RUNTIME_STATS
help
Gather system heap runtime statistics.
config SYS_HEAP_LISTENER
bool "Enable sys_heap event notifications"
select HEAP_LISTENER
help
This allows application to listen for sys_heap events,
such as memory allocation and de-allocation.
config HEAP_LISTENER
bool
help

View file

@ -5,6 +5,7 @@
*/
#include <sys/sys_heap.h>
#include <sys/util.h>
#include <sys/heap_listener.h>
#include <kernel.h>
#include <string.h>
#include "heap.h"
@ -176,6 +177,12 @@ void sys_heap_free(struct sys_heap *heap, void *mem)
#ifdef CONFIG_SYS_HEAP_RUNTIME_STATS
h->allocated_bytes -= chunksz_to_bytes(h, chunk_size(h, c));
#endif
#ifdef CONFIG_SYS_HEAP_LISTENER
heap_listener_notify_free(HEAP_ID_FROM_POINTER(heap), mem,
chunksz_to_bytes(h, chunk_size(h, c)));
#endif
free_chunk(h, c);
}
@ -245,6 +252,7 @@ static chunkid_t alloc_chunk(struct z_heap *h, chunksz_t sz)
void *sys_heap_alloc(struct sys_heap *heap, size_t bytes)
{
struct z_heap *h = heap->heap;
void *mem;
if (bytes == 0U || size_too_big(h, bytes)) {
return NULL;
@ -263,10 +271,19 @@ void *sys_heap_alloc(struct sys_heap *heap, size_t bytes)
}
set_chunk_used(h, c, true);
mem = chunk_mem(h, c);
#ifdef CONFIG_SYS_HEAP_RUNTIME_STATS
h->allocated_bytes += chunksz_to_bytes(h, chunk_size(h, c));
#endif
return chunk_mem(h, c);
#ifdef CONFIG_SYS_HEAP_LISTENER
heap_listener_notify_alloc(HEAP_ID_FROM_POINTER(heap), mem,
chunksz_to_bytes(h, chunk_size(h, c)));
#endif
return mem;
}
void *sys_heap_aligned_alloc(struct sys_heap *heap, size_t align, size_t bytes)
@ -336,6 +353,12 @@ void *sys_heap_aligned_alloc(struct sys_heap *heap, size_t align, size_t bytes)
#ifdef CONFIG_SYS_HEAP_RUNTIME_STATS
h->allocated_bytes += chunksz_to_bytes(h, chunk_size(h, c));
#endif
#ifdef CONFIG_SYS_HEAP_LISTENER
heap_listener_notify_alloc(HEAP_ID_FROM_POINTER(heap), mem,
chunksz_to_bytes(h, chunk_size(h, c)));
#endif
return mem;
}
@ -371,19 +394,36 @@ void *sys_heap_aligned_realloc(struct sys_heap *heap, void *ptr,
return ptr;
} else if (chunk_size(h, c) > chunks_need) {
/* Shrink in place, split off and free unused suffix */
#ifdef CONFIG_SYS_HEAP_LISTENER
size_t bytes_freed = chunksz_to_bytes(h, c);
#endif
#ifdef CONFIG_SYS_HEAP_RUNTIME_STATS
h->allocated_bytes -=
(chunk_size(h, c) - chunks_need) * CHUNK_UNIT;
#endif
split_chunks(h, c, c + chunks_need);
set_chunk_used(h, c, true);
free_chunk(h, c + chunks_need);
#ifdef CONFIG_SYS_HEAP_LISTENER
heap_listener_notify_alloc(HEAP_ID_FROM_POINTER(heap), ptr,
chunksz_to_bytes(h, chunk_size(h, c)));
heap_listener_notify_free(HEAP_ID_FROM_POINTER(heap), ptr,
bytes_freed);
#endif
return ptr;
} else if (!chunk_used(h, rc) &&
(chunk_size(h, c) + chunk_size(h, rc) >= chunks_need)) {
/* Expand: split the right chunk and append */
chunksz_t split_size = chunks_need - chunk_size(h, c);
#ifdef CONFIG_SYS_HEAP_LISTENER
size_t bytes_freed = chunksz_to_bytes(h, c);
#endif
#ifdef CONFIG_SYS_HEAP_RUNTIME_STATS
h->allocated_bytes += split_size * CHUNK_UNIT;
#endif
@ -397,12 +437,26 @@ void *sys_heap_aligned_realloc(struct sys_heap *heap, void *ptr,
merge_chunks(h, c, rc);
set_chunk_used(h, c, true);
#ifdef CONFIG_SYS_HEAP_LISTENER
heap_listener_notify_alloc(HEAP_ID_FROM_POINTER(heap), ptr,
chunksz_to_bytes(h, chunk_size(h, c)));
heap_listener_notify_free(HEAP_ID_FROM_POINTER(heap), ptr,
bytes_freed);
#endif
return ptr;
} else {
;
}
/* Fallback: allocate and copy */
/*
* Fallback: allocate and copy
*
* Note for heap listener notification:
* The calls to allocation and free functions generate
* notification already, so there is no need to those here.
*/
void *ptr2 = sys_heap_aligned_alloc(heap, align, bytes);
if (ptr2 != NULL) {