Skip to content

Commit 135ffaf

Browse files
cfriedtcarlescufi
authored andcommitted
kernel/k_malloc: add k_aligned_alloc
This change adds z_heap_aligned_alloc() and k_aligned_alloc() and changes z_heap_malloc() and k_malloc() to be small wrappers around the aligned variants. Fixes #29519 Signed-off-by: Christopher Friedt <[email protected]>
1 parent 6788d86 commit 135ffaf

File tree

2 files changed

+62
-16
lines changed

2 files changed

+62
-16
lines changed

include/kernel.h

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4540,7 +4540,27 @@ extern void z_mem_pool_free_id(struct k_mem_block_id *id);
45404540
*/
45414541

45424542
/**
4543-
* @brief Allocate memory from heap.
4543+
* @brief Allocate memory from the heap with a specified alignment.
4544+
*
4545+
* This routine provides semantics similar to aligned_alloc(); memory is
4546+
* allocated from the heap with a specified alignment. However, one minor
4547+
* difference is that k_aligned_alloc() accepts any non-zero @p size,
4548+
* wherase aligned_alloc() only accepts a @p size that is an integral
4549+
* multiple of @p align.
4550+
*
4551+
* Above, aligned_alloc() refers to:
4552+
* C11 standard (ISO/IEC 9899:2011): 7.22.3.1
4553+
* The aligned_alloc function (p: 347-348)
4554+
*
4555+
* @param align Alignment of memory requested (in bytes).
4556+
* @param size Amount of memory requested (in bytes).
4557+
*
4558+
* @return Address of the allocated memory if successful; otherwise NULL.
4559+
*/
4560+
extern void *k_aligned_alloc(size_t align, size_t size);
4561+
4562+
/**
4563+
* @brief Allocate memory from the heap.
45444564
*
45454565
* This routine provides traditional malloc() semantics. Memory is
45464566
* allocated from the heap memory pool.
@@ -4549,7 +4569,10 @@ extern void z_mem_pool_free_id(struct k_mem_block_id *id);
45494569
*
45504570
* @return Address of the allocated memory if successful; otherwise NULL.
45514571
*/
4552-
extern void *k_malloc(size_t size);
4572+
static inline void *k_malloc(size_t size)
4573+
{
4574+
return k_aligned_alloc(sizeof(void *), size);
4575+
}
45534576

45544577
/**
45554578
* @brief Free memory allocated from heap.

kernel/mempool.c

Lines changed: 37 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7,37 +7,53 @@
77
#include <kernel.h>
88
#include <string.h>
99
#include <sys/math_extras.h>
10+
#include <sys/util.h>
1011

11-
void *z_heap_malloc(struct k_heap *heap, size_t size)
12+
static void *z_heap_aligned_alloc(struct k_heap *heap, size_t align, size_t size)
1213
{
14+
uint8_t *mem;
15+
struct k_heap **heap_ref;
16+
size_t excess = MAX(sizeof(struct k_heap *), align);
17+
1318
/*
14-
* get a block large enough to hold an initial (hidden) heap
19+
* get a block large enough to hold an initial (aligned and hidden) heap
1520
* pointer, as well as the space the caller requested
1621
*/
17-
if (size_add_overflow(size, sizeof(struct k_heap *),
18-
&size)) {
22+
if (size_add_overflow(size, excess, &size)) {
1923
return NULL;
2024
}
2125

22-
struct k_heap **blk = k_heap_alloc(heap, size, K_NO_WAIT);
23-
24-
if (blk == NULL) {
26+
mem = k_heap_aligned_alloc(heap, align, size, K_NO_WAIT);
27+
if (mem == NULL) {
2528
return NULL;
2629
}
2730

28-
blk[0] = heap;
31+
/* create (void *) values in the excess equal to (void *) -1 */
32+
memset(mem, 0xff, excess);
33+
heap_ref = (struct k_heap **)mem;
34+
*heap_ref = heap;
2935

3036
/* return address of the user area part of the block to the caller */
31-
return (char *)&blk[1];
37+
return mem + excess;
38+
}
39+
40+
static void *z_heap_malloc(struct k_heap *heap, size_t size)
41+
{
42+
return z_heap_aligned_alloc(heap, sizeof(void *), size);
3243
}
3344

3445
void k_free(void *ptr)
3546
{
47+
struct k_heap **heap_ref;
48+
3649
if (ptr != NULL) {
37-
struct k_heap **blk = &((struct k_heap **)ptr)[-1];
38-
struct k_heap *heap = *blk;
50+
for (heap_ref = &((struct k_heap **)ptr)[-1];
51+
*heap_ref == (struct k_heap *)-1; --heap_ref) {
52+
/* no-op */
53+
}
3954

40-
k_heap_free(heap, blk);
55+
ptr = (uint8_t *)heap_ref;
56+
k_heap_free(*heap_ref, ptr);
4157
}
4258
}
4359

@@ -46,9 +62,16 @@ void k_free(void *ptr)
4662
K_HEAP_DEFINE(_system_heap, CONFIG_HEAP_MEM_POOL_SIZE);
4763
#define _SYSTEM_HEAP (&_system_heap)
4864

49-
void *k_malloc(size_t size)
65+
void *k_aligned_alloc(size_t align, size_t size)
5066
{
51-
return z_heap_malloc(_SYSTEM_HEAP, size);
67+
__ASSERT(align / sizeof(void *) >= 1
68+
&& (align % sizeof(void *)) == 0,
69+
"align must be a multiple of sizeof(void *)");
70+
71+
__ASSERT((align & (align - 1)) == 0,
72+
"align must be a power of 2");
73+
74+
return z_heap_aligned_alloc(_SYSTEM_HEAP, align, size);
5275
}
5376

5477
void *k_calloc(size_t nmemb, size_t size)

0 commit comments

Comments
 (0)