From 8bb1f2a947074a17afef979b9b67c29353a163a9 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Sat, 25 May 2019 22:53:37 -0400 Subject: [PATCH] linker generated list: explicit alignment on data definitions The alignment fix on struct device definitions should be done to all such linker list tricks. Let's abstract the declaration plus alignment with a macro and apply it to all concerned cases. Signed-off-by: Nicolas Pitre --- include/device.h | 10 ++++------ include/kernel.h | 29 +++++++++++++++-------------- include/toolchain/common.h | 19 +++++++++++++++++++ subsys/bluetooth/host/settings.h | 2 +- 4 files changed, 39 insertions(+), 21 deletions(-) diff --git a/include/device.h b/include/device.h index 19a091eecaf6a0..272be8159c240a 100644 --- a/include/device.h +++ b/include/device.h @@ -107,9 +107,8 @@ extern "C" { .name = drv_name, .init = (init_fn), \ .config_info = (cfg_info) \ }; \ - static struct device _CONCAT(__device_, dev_name) __used \ - __attribute__((__section__(".init_" #level STRINGIFY(prio)), \ - aligned(__alignof(struct device)))) = { \ + static Z_DECL_ALIGN(struct device) _CONCAT(__device_, dev_name) __used \ + __attribute__((__section__(".init_" #level STRINGIFY(prio)))) = { \ .config = &_CONCAT(__config_, dev_name), \ .driver_api = api, \ .driver_data = data \ @@ -165,9 +164,8 @@ extern "C" { .pm = &_CONCAT(__pm_, dev_name), \ .config_info = (cfg_info) \ }; \ - static struct device _CONCAT(__device_, dev_name) __used \ - __attribute__((__section__(".init_" #level STRINGIFY(prio)), \ - aligned(__alignof(struct device)))) = { \ + static Z_DECL_ALIGN(struct device) _CONCAT(__device_, dev_name) __used \ + __attribute__((__section__(".init_" #level STRINGIFY(prio)))) = { \ .config = &_CONCAT(__config_, dev_name), \ .driver_api = api, \ .driver_data = data, \ diff --git a/include/kernel.h b/include/kernel.h index e2b446b822f8f6..714d36a3289728 100644 --- a/include/kernel.h +++ b/include/kernel.h @@ -187,7 +187,7 @@ struct _k_object_assignment { static void * const _CONCAT(_object_list_, name_)[] = \ { __VA_ARGS__, NULL }; \ static __used __in_section_unique(object_access) \ - const struct _k_object_assignment \ + const Z_DECL_ALIGN(struct _k_object_assignment) \ _CONCAT(_object_access_, name_) = \ { (&_k_thread_obj_ ## name_), \ (_CONCAT(_object_list_, name_)) } @@ -969,7 +969,7 @@ struct _static_thread_data { prio, options, delay) \ K_THREAD_STACK_DEFINE(_k_thread_stack_##name, stack_size); \ struct k_thread _k_thread_obj_##name; \ - struct _static_thread_data _k_thread_data_##name __aligned(4) \ + Z_DECL_ALIGN(struct _static_thread_data) _k_thread_data_##name \ __in_section(_static_thread_data, static, name) = \ _THREAD_INITIALIZER(&_k_thread_obj_##name, \ _k_thread_stack_##name, stack_size, \ @@ -1468,7 +1468,7 @@ typedef void (*k_timer_stop_t)(struct k_timer *timer); * @param stop_fn Function to invoke if the timer is stopped while running. */ #define K_TIMER_DEFINE(name, expiry_fn, stop_fn) \ - struct k_timer name \ + Z_DECL_ALIGN(struct k_timer) name \ __in_section(_k_timer, static, name) = \ Z_TIMER_INITIALIZER(name, expiry_fn, stop_fn) @@ -2050,7 +2050,7 @@ static inline void *z_impl_k_queue_peek_tail(struct k_queue *queue) * @param name Name of the queue. */ #define K_QUEUE_DEFINE(name) \ - struct k_queue name \ + Z_DECL_ALIGN(struct k_queue) name \ __in_section(_k_queue, static, name) = \ _K_QUEUE_INITIALIZER(name) @@ -2266,7 +2266,7 @@ struct k_fifo { * @req K-FIFO-002 */ #define K_FIFO_DEFINE(name) \ - struct k_fifo name \ + Z_DECL_ALIGN(struct k_fifo) name \ __in_section(_k_queue, static, name) = \ Z_FIFO_INITIALIZER(name) @@ -2378,7 +2378,7 @@ struct k_lifo { * @req K-LIFO-002 */ #define K_LIFO_DEFINE(name) \ - struct k_lifo name \ + Z_DECL_ALIGN(struct k_lifo) name \ __in_section(_k_queue, static, name) = \ _K_LIFO_INITIALIZER(name) @@ -2514,7 +2514,7 @@ __syscall int k_stack_pop(struct k_stack *stack, u32_t *data, s32_t timeout); #define K_STACK_DEFINE(name, stack_num_entries) \ u32_t __noinit \ _k_stack_buf_##name[stack_num_entries]; \ - struct k_stack name \ + Z_DECL_ALIGN(struct k_stack) name \ __in_section(_k_stack, static, name) = \ _K_STACK_INITIALIZER(name, _k_stack_buf_##name, \ stack_num_entries) @@ -2949,7 +2949,7 @@ struct k_mutex { * @req K-MUTEX-001 */ #define K_MUTEX_DEFINE(name) \ - struct k_mutex name \ + Z_DECL_ALIGN(struct k_mutex) name \ __in_section(_k_mutex, static, name) = \ _K_MUTEX_INITIALIZER(name) @@ -3150,7 +3150,7 @@ static inline unsigned int z_impl_k_sem_count_get(struct k_sem *sem) * @req K-SEM-002 */ #define K_SEM_DEFINE(name, initial_count, count_limit) \ - struct k_sem name \ + Z_DECL_ALIGN(struct k_sem) name \ __in_section(_k_sem, static, name) = \ Z_SEM_INITIALIZER(name, initial_count, count_limit); \ BUILD_ASSERT(((count_limit) != 0) && \ @@ -3240,7 +3240,7 @@ struct k_msgq_attrs { #define K_MSGQ_DEFINE(q_name, q_msg_size, q_max_msgs, q_align) \ static char __noinit __aligned(q_align) \ _k_fifo_buf_##q_name[(q_max_msgs) * (q_msg_size)]; \ - struct k_msgq q_name \ + Z_DECL_ALIGN(struct k_msgq) q_name \ __in_section(_k_msgq, static, q_name) = \ _K_MSGQ_INITIALIZER(q_name, _k_fifo_buf_##q_name, \ q_msg_size, q_max_msgs) @@ -3504,7 +3504,7 @@ struct k_mbox { * @req K-MBOX-001 */ #define K_MBOX_DEFINE(name) \ - struct k_mbox name \ + Z_DECL_ALIGN(struct k_mbox) name \ __in_section(_k_mbox, static, name) = \ _K_MBOX_INITIALIZER(name) \ @@ -3707,7 +3707,7 @@ struct k_pipe { #define K_PIPE_DEFINE(name, pipe_buffer_size, pipe_align) \ static unsigned char __noinit __aligned(pipe_align) \ _k_pipe_buf_##name[pipe_buffer_size]; \ - struct k_pipe name \ + Z_DECL_ALIGN(struct k_pipe) name \ __in_section(_k_pipe, static, name) = \ _K_PIPE_INITIALIZER(name, _k_pipe_buf_##name, pipe_buffer_size) @@ -3888,7 +3888,7 @@ struct k_mem_slab { #define K_MEM_SLAB_DEFINE(name, slab_block_size, slab_num_blocks, slab_align) \ char __noinit __aligned(slab_align) \ _k_mem_slab_buf_##name[(slab_num_blocks) * (slab_block_size)]; \ - struct k_mem_slab name \ + Z_DECL_ALIGN(struct k_mem_slab) name \ __in_section(_k_mem_slab, static, name) = \ _K_MEM_SLAB_INITIALIZER(name, _k_mem_slab_buf_##name, \ slab_block_size, slab_num_blocks) @@ -4025,7 +4025,8 @@ struct k_mem_pool { char __aligned(align) _mpool_buf_##name[_ALIGN4(maxsz * nmax) \ + _MPOOL_BITS_SIZE(maxsz, minsz, nmax)]; \ struct sys_mem_pool_lvl _mpool_lvls_##name[Z_MPOOL_LVLS(maxsz, minsz)]; \ - struct k_mem_pool name __in_section(_k_mem_pool, static, name) = { \ + Z_DECL_ALIGN(struct k_mem_pool) name \ + __in_section(_k_mem_pool, static, name) = { \ .base = { \ .buf = _mpool_buf_##name, \ .max_sz = maxsz, \ diff --git a/include/toolchain/common.h b/include/toolchain/common.h index 79a1e0bb7b6bed..143eaa13ca6ea7 100644 --- a/include/toolchain/common.h +++ b/include/toolchain/common.h @@ -144,4 +144,23 @@ #define BUILD_ASSERT_MSG(EXPR, MSG) BUILD_ASSERT(EXPR) #endif +/* + * This is meant to be used in conjonction with __in_section() and similar + * where scattered structure instances are concatened together by the linker + * and walked by the code at run time just like a contiguous array of such + * structures. + * + * Assemblers and linkers may insert alignment padding by default whose + * size is larger than the natural alignment for those structures when + * gathering various section segments together, messing up the array walk. + * To prevent this, we need to provide an explicit alignment not to rely + * on the default that might just work by luck. + * + * Alignment statements in linker scripts are not sufficient as + * the assembler may add padding by itself to each segment when switching + * between sections within the same file even if it merges many such segments + * into a single section in the end. + */ +#define Z_DECL_ALIGN(type) __aligned(__alignof(type)) type + #endif /* ZEPHYR_INCLUDE_TOOLCHAIN_COMMON_H_ */ diff --git a/subsys/bluetooth/host/settings.h b/subsys/bluetooth/host/settings.h index 0f79afe2af72b0..81b75c9aa912c0 100644 --- a/subsys/bluetooth/host/settings.h +++ b/subsys/bluetooth/host/settings.h @@ -14,7 +14,7 @@ struct bt_settings_handler { }; #define BT_SETTINGS_DEFINE(_name, _set, _commit, _export) \ - const struct bt_settings_handler _name __aligned(4) \ + const Z_DECL_ALIGN(struct bt_settings_handler) _name \ __in_section(_bt_settings, static, _name) = { \ .name = STRINGIFY(_name), \ .set = _set, \