kernel: implement k_realloc
implement k_realloc. Signed-off-by: Fin Maaß <f.maass@vogl-electronic.com>
This commit is contained in:
parent
0a677ec31b
commit
09eaa8757f
3 changed files with 99 additions and 0 deletions
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue