kernel: implement k_realloc

implement k_realloc.

Signed-off-by: Fin Maaß <f.maass@vogl-electronic.com>
This commit is contained in:
Fin Maaß 2024-05-13 09:15:35 +02:00 committed by Alberto Escolar
commit 09eaa8757f
3 changed files with 99 additions and 0 deletions

View file

@ -5381,6 +5381,32 @@ void *k_heap_aligned_alloc(struct k_heap *h, size_t align, size_t bytes,
void *k_heap_alloc(struct k_heap *h, size_t bytes,
k_timeout_t timeout) __attribute_nonnull(1);
/**
* @brief Reallocate memory from a k_heap
*
* Reallocates and returns a memory buffer from the memory region owned
* by the heap. If no memory is available immediately, the call will
* block for the specified timeout (constructed via the standard
* timeout API, or K_NO_WAIT or K_FOREVER) waiting for memory to be
* freed. If the allocation cannot be performed by the expiration of
* the timeout, NULL will be returned.
* Reallocated memory is aligned on a multiple of pointer sizes.
*
* @note @a timeout must be set to K_NO_WAIT if called from ISR.
* @note When CONFIG_MULTITHREADING=n any @a timeout is treated as K_NO_WAIT.
*
* @funcprops \isr_ok
*
* @param h Heap from which to allocate
* @param ptr Original pointer returned from a previous allocation
* @param bytes Desired size of block to allocate
* @param timeout How long to wait, or K_NO_WAIT
*
* @return Pointer to memory the caller can now use, or NULL
*/
void *k_heap_realloc(struct k_heap *h, void *ptr, size_t bytes, k_timeout_t timeout)
__attribute_nonnull(1);
/**
* @brief Free memory allocated by k_heap_alloc()
*
@ -5528,6 +5554,25 @@ void k_free(void *ptr);
*/
void *k_calloc(size_t nmemb, size_t size);
/** @brief Expand the size of an existing allocation
*
* Returns a pointer to a new memory region with the same contents,
* but a different allocated size. If the new allocation can be
* expanded in place, the pointer returned will be identical.
* Otherwise the data will be copies to a new block and the old one
* will be freed as per sys_heap_free(). If the specified size is
* smaller than the original, the block will be truncated in place and
* the remaining memory returned to the heap. If the allocation of a
* new block fails, then NULL will be returned and the old block will
* not be freed or modified.
*
* @param ptr Original pointer returned from a previous allocation
* @param size Amount of memory requested (in bytes).
*
* @return Pointer to memory the caller can now use, or NULL.
*/
void *k_realloc(void *ptr, size_t size);
/** @} */
/* polling API - PRIVATE */

View file

@ -116,6 +116,32 @@ void *k_heap_alloc(struct k_heap *heap, size_t bytes, k_timeout_t timeout)
return ret;
}
void *k_heap_realloc(struct k_heap *heap, void *ptr, size_t bytes, k_timeout_t timeout)
{
k_timepoint_t end = sys_timepoint_calc(timeout);
void *ret = NULL;
k_spinlock_key_t key = k_spin_lock(&heap->lock);
__ASSERT(!arch_is_in_isr() || K_TIMEOUT_EQ(timeout, K_NO_WAIT), "");
while (ret == NULL) {
ret = sys_heap_aligned_realloc(&heap->heap, ptr, sizeof(void *), bytes);
if (!IS_ENABLED(CONFIG_MULTITHREADING) ||
(ret != NULL) || K_TIMEOUT_EQ(timeout, K_NO_WAIT)) {
break;
}
timeout = sys_timepoint_timeout(end);
(void) z_pend_curr(&heap->lock, key, &heap->wait_q, timeout);
key = k_spin_lock(&heap->lock);
}
k_spin_unlock(&heap->lock, key);
return ret;
}
void k_heap_free(struct k_heap *heap, void *mem)
{
k_spinlock_key_t key = k_spin_lock(&heap->lock);

View file

@ -113,6 +113,34 @@ void *k_calloc(size_t nmemb, size_t size)
return ret;
}
void *k_realloc(void *ptr, size_t size)
{
struct k_heap *heap, **heap_ref;
void *ret;
if (size == 0) {
k_free(ptr);
return NULL;
}
if (ptr == NULL) {
return k_malloc(size);
}
heap_ref = ptr;
ptr = --heap_ref;
heap = *heap_ref;
if (size_add_overflow(size, sizeof(heap_ref), &size)) {
return NULL;
}
ret = k_heap_realloc(heap, ptr, size, K_NO_WAIT);
if (ret != NULL) {
heap_ref = ret;
ret = ++heap_ref;
}
return ret;
}
void k_thread_system_pool_assign(struct k_thread *thread)
{
thread->resource_pool = _SYSTEM_HEAP;