malloc: make sure returned memory is properly aligned

The accounting data stored at the beginning of a memory block used by
malloc must push the returned memory address to a word boundary. This
is already the case on 32-bit systems, but not on 64-bit systems where
e.g. struct k_mem_block_id still has a size of 4.

Signed-off-by: Nicolas Pitre <npitre@baylibre.com>
This commit is contained in:
Nicolas Pitre 2019-05-23 13:42:32 -04:00 committed by Andrew Boie
commit 39cd2ebef7
3 changed files with 10 additions and 8 deletions

View file

@ -141,7 +141,8 @@ void *k_mem_pool_malloc(struct k_mem_pool *pool, size_t size)
* get a block large enough to hold an initial (hidden) block * get a block large enough to hold an initial (hidden) block
* descriptor, as well as the space the caller requested * descriptor, as well as the space the caller requested
*/ */
if (size_add_overflow(size, sizeof(struct k_mem_block_id), &size)) { if (size_add_overflow(size, WB_UP(sizeof(struct k_mem_block_id)),
&size)) {
return NULL; return NULL;
} }
if (k_mem_pool_alloc(pool, &block, size, K_NO_WAIT) != 0) { if (k_mem_pool_alloc(pool, &block, size, K_NO_WAIT) != 0) {
@ -152,14 +153,14 @@ void *k_mem_pool_malloc(struct k_mem_pool *pool, size_t size)
(void)memcpy(block.data, &block.id, sizeof(struct k_mem_block_id)); (void)memcpy(block.data, &block.id, sizeof(struct k_mem_block_id));
/* return address of the user area part of the block to the caller */ /* return address of the user area part of the block to the caller */
return (char *)block.data + sizeof(struct k_mem_block_id); return (char *)block.data + WB_UP(sizeof(struct k_mem_block_id));
} }
void k_free(void *ptr) void k_free(void *ptr)
{ {
if (ptr != NULL) { if (ptr != NULL) {
/* point to hidden block descriptor at start of block */ /* point to hidden block descriptor at start of block */
ptr = (char *)ptr - sizeof(struct k_mem_block_id); ptr = (char *)ptr - WB_UP(sizeof(struct k_mem_block_id));
/* return block to the heap memory pool */ /* return block to the heap memory pool */
k_mem_pool_free_id(ptr); k_mem_pool_free_id(ptr);

View file

@ -349,7 +349,7 @@ void *sys_mem_pool_alloc(struct sys_mem_pool *p, size_t size)
sys_mutex_lock(&p->mutex, K_FOREVER); sys_mutex_lock(&p->mutex, K_FOREVER);
size += sizeof(struct sys_mem_pool_block); size += WB_UP(sizeof(struct sys_mem_pool_block));
if (z_sys_mem_pool_block_alloc(&p->base, size, &level, &block, if (z_sys_mem_pool_block_alloc(&p->base, size, &level, &block,
(void **)&ret)) { (void **)&ret)) {
ret = NULL; ret = NULL;
@ -360,7 +360,7 @@ void *sys_mem_pool_alloc(struct sys_mem_pool *p, size_t size)
blk->level = level; blk->level = level;
blk->block = block; blk->block = block;
blk->pool = p; blk->pool = p;
ret += sizeof(*blk); ret += WB_UP(sizeof(struct sys_mem_pool_block));
out: out:
sys_mutex_unlock(&p->mutex); sys_mutex_unlock(&p->mutex);
return ret; return ret;
@ -375,7 +375,8 @@ void sys_mem_pool_free(void *ptr)
return; return;
} }
blk = (struct sys_mem_pool_block *)((char *)ptr - sizeof(*blk)); ptr = (char *)ptr - WB_UP(sizeof(struct sys_mem_pool_block));
blk = (struct sys_mem_pool_block *)ptr;
p = blk->pool; p = blk->pool;
sys_mutex_lock(&p->mutex, K_FOREVER); sys_mutex_lock(&p->mutex, K_FOREVER);

View file

@ -31,12 +31,12 @@ void test_mheap_malloc_align4(void)
/** /**
* TESTPOINT: The address of the allocated chunk is guaranteed to be * TESTPOINT: The address of the allocated chunk is guaranteed to be
* aligned on a multiple of 4 bytes. * aligned on a word boundary (4 or 8 bytes).
*/ */
for (int i = 0; i < BLK_NUM_MAX; i++) { for (int i = 0; i < BLK_NUM_MAX; i++) {
block[i] = k_malloc(i); block[i] = k_malloc(i);
zassert_not_null(block[i], NULL); zassert_not_null(block[i], NULL);
zassert_false((int)block[i] % 4, NULL); zassert_false((uintptr_t)block[i] % sizeof(void *), NULL);
} }
/* test case tear down*/ /* test case tear down*/