k_stack: make it 64-bit compatible

The k_stack data type cannot be u32_t on a 64-bit system as it is
often used to store pointers. Let's define a dedicated type for stack
data values, namely stack_data_t, which can be adjusted accordingly.
For now it is defined to uintptr_t which is the integer type large
enough to hold a pointer, meaning it is equivalent to u32_t on 32-bit
systems and u64_t on 64-bit systems.

Signed-off-by: Nicolas Pitre <npitre@baylibre.com>
This commit is contained in:
Nicolas Pitre 2019-05-17 22:48:26 -04:00 committed by Anas Nashif
commit 3d51f7c266
10 changed files with 53 additions and 49 deletions

View file

@ -5,7 +5,7 @@ Stacks
A :dfn:`stack` is a kernel object that implements a traditional A :dfn:`stack` is a kernel object that implements a traditional
last in, first out (LIFO) queue, allowing threads and ISRs last in, first out (LIFO) queue, allowing threads and ISRs
to add and remove a limited number of 32-bit data values. to add and remove a limited number of integer data values.
.. contents:: .. contents::
:local: :local:
@ -19,9 +19,11 @@ by its memory address.
A stack has the following key properties: A stack has the following key properties:
* A **queue** of 32-bit data values that have been added but not yet removed. * A **queue** of integer data values that have been added but not yet removed.
The queue is implemented using an array of 32-bit integers, The queue is implemented using an array of stack_data_t values
and must be aligned on a 4-byte boundary. and must be aligned on a native word boundary.
The stack_data_t type corresponds to the native word size i.e. 32 bits or
64 bits depending on the CPU architecture and compilation mode.
* A **maximum quantity** of data values that can be queued in the array. * A **maximum quantity** of data values that can be queued in the array.
@ -60,13 +62,13 @@ provided and it is instead allocated from the calling thread's resource
pool. pool.
The following code defines and initializes an empty stack capable of holding The following code defines and initializes an empty stack capable of holding
up to ten 32-bit data values. up to ten word-sized data values.
.. code-block:: c .. code-block:: c
#define MAX_ITEMS 10 #define MAX_ITEMS 10
u32_t my_stack_array[MAX_ITEMS]; stack_data_t my_stack_array[MAX_ITEMS];
struct k_stack my_stack; struct k_stack my_stack;
k_stack_init(&my_stack, my_stack_array, MAX_ITEMS); k_stack_init(&my_stack, my_stack_array, MAX_ITEMS);
@ -101,7 +103,7 @@ in a stack.
/* save address of each data structure in a stack */ /* save address of each data structure in a stack */
for (int i = 0; i < MAX_ITEMS; i++) { for (int i = 0; i < MAX_ITEMS; i++) {
k_stack_push(&my_stack, (u32_t)&my_buffers[i]); k_stack_push(&my_stack, (stack_data_t)&my_buffers[i]);
} }
Popping from a Stack Popping from a Stack
@ -118,13 +120,13 @@ its address back on the stack to allow the data structure to be reused.
struct my_buffer_type *new_buffer; struct my_buffer_type *new_buffer;
k_stack_pop(&buffer_stack, (u32_t *)&new_buffer, K_FOREVER); k_stack_pop(&buffer_stack, (stack_data_t *)&new_buffer, K_FOREVER);
new_buffer->field1 = ... new_buffer->field1 = ...
Suggested Uses Suggested Uses
************** **************
Use a stack to store and retrieve 32-bit data values in a "last in, Use a stack to store and retrieve integer data values in a "last in,
first out" manner, when the maximum number of stored items is known. first out" manner, when the maximum number of stored items is known.
Configuration Options Configuration Options

View file

@ -2419,10 +2419,12 @@ struct k_lifo {
*/ */
#define K_STACK_FLAG_ALLOC ((u8_t)1) /* Buffer was allocated */ #define K_STACK_FLAG_ALLOC ((u8_t)1) /* Buffer was allocated */
typedef uintptr_t stack_data_t;
struct k_stack { struct k_stack {
_wait_q_t wait_q; _wait_q_t wait_q;
struct k_spinlock lock; struct k_spinlock lock;
u32_t *base, *next, *top; stack_data_t *base, *next, *top;
_OBJECT_TRACING_NEXT_PTR(k_stack) _OBJECT_TRACING_NEXT_PTR(k_stack)
u8_t flags; u8_t flags;
@ -2462,7 +2464,7 @@ struct k_stack {
* @req K-STACK-001 * @req K-STACK-001
*/ */
void k_stack_init(struct k_stack *stack, void k_stack_init(struct k_stack *stack,
u32_t *buffer, u32_t num_entries); stack_data_t *buffer, u32_t num_entries);
/** /**
@ -2498,7 +2500,7 @@ void k_stack_cleanup(struct k_stack *stack);
/** /**
* @brief Push an element onto a stack. * @brief Push an element onto a stack.
* *
* This routine adds a 32-bit value @a data to @a stack. * This routine adds a stack_data_t value @a data to @a stack.
* *
* @note Can be called by ISRs. * @note Can be called by ISRs.
* *
@ -2508,13 +2510,13 @@ void k_stack_cleanup(struct k_stack *stack);
* @return N/A * @return N/A
* @req K-STACK-001 * @req K-STACK-001
*/ */
__syscall void k_stack_push(struct k_stack *stack, u32_t data); __syscall void k_stack_push(struct k_stack *stack, stack_data_t data);
/** /**
* @brief Pop an element from a stack. * @brief Pop an element from a stack.
* *
* This routine removes a 32-bit value from @a stack in a "last in, first out" * This routine removes a stack_data_t value from @a stack in a "last in,
* manner and stores the value in @a data. * first out" manner and stores the value in @a data.
* *
* @note Can be called by ISRs, but @a timeout must be set to K_NO_WAIT. * @note Can be called by ISRs, but @a timeout must be set to K_NO_WAIT.
* *
@ -2528,7 +2530,7 @@ __syscall void k_stack_push(struct k_stack *stack, u32_t data);
* @retval -EAGAIN Waiting period timed out. * @retval -EAGAIN Waiting period timed out.
* @req K-STACK-001 * @req K-STACK-001
*/ */
__syscall int k_stack_pop(struct k_stack *stack, u32_t *data, s32_t timeout); __syscall int k_stack_pop(struct k_stack *stack, stack_data_t *data, s32_t timeout);
/** /**
* @brief Statically define and initialize a stack * @brief Statically define and initialize a stack
@ -2542,7 +2544,7 @@ __syscall int k_stack_pop(struct k_stack *stack, u32_t *data, s32_t timeout);
* @req K-STACK-002 * @req K-STACK-002
*/ */
#define K_STACK_DEFINE(name, stack_num_entries) \ #define K_STACK_DEFINE(name, stack_num_entries) \
u32_t __noinit \ stack_data_t __noinit \
_k_stack_buf_##name[stack_num_entries]; \ _k_stack_buf_##name[stack_num_entries]; \
Z_STRUCT_SECTION_ITERABLE(k_stack, name) = \ Z_STRUCT_SECTION_ITERABLE(k_stack, name) = \
_K_STACK_INITIALIZER(name, _k_stack_buf_##name, \ _K_STACK_INITIALIZER(name, _k_stack_buf_##name, \

View file

@ -32,13 +32,13 @@ K_STACK_DEFINE(async_msg_free, CONFIG_NUM_MBOX_ASYNC_MSGS);
/* allocate an asynchronous message descriptor */ /* allocate an asynchronous message descriptor */
static inline void mbox_async_alloc(struct k_mbox_async **async) static inline void mbox_async_alloc(struct k_mbox_async **async)
{ {
(void)k_stack_pop(&async_msg_free, (u32_t *)async, K_FOREVER); (void)k_stack_pop(&async_msg_free, (stack_data_t *)async, K_FOREVER);
} }
/* free an asynchronous message descriptor */ /* free an asynchronous message descriptor */
static inline void mbox_async_free(struct k_mbox_async *async) static inline void mbox_async_free(struct k_mbox_async *async)
{ {
k_stack_push(&async_msg_free, (u32_t)async); k_stack_push(&async_msg_free, (stack_data_t)async);
} }
#endif /* CONFIG_NUM_MBOX_ASYNC_MSGS > 0 */ #endif /* CONFIG_NUM_MBOX_ASYNC_MSGS > 0 */
@ -77,7 +77,7 @@ static int init_mbox_module(struct device *dev)
for (i = 0; i < CONFIG_NUM_MBOX_ASYNC_MSGS; i++) { for (i = 0; i < CONFIG_NUM_MBOX_ASYNC_MSGS; i++) {
z_init_thread_base(&async_msg[i].thread, 0, _THREAD_DUMMY, 0); z_init_thread_base(&async_msg[i].thread, 0, _THREAD_DUMMY, 0);
k_stack_push(&async_msg_free, (u32_t)&async_msg[i]); k_stack_push(&async_msg_free, (stack_data_t)&async_msg[i]);
} }
#endif /* CONFIG_NUM_MBOX_ASYNC_MSGS > 0 */ #endif /* CONFIG_NUM_MBOX_ASYNC_MSGS > 0 */

View file

@ -49,13 +49,13 @@ K_STACK_DEFINE(pipe_async_msgs, CONFIG_NUM_PIPE_ASYNC_MSGS);
/* Allocate an asynchronous message descriptor */ /* Allocate an asynchronous message descriptor */
static void pipe_async_alloc(struct k_pipe_async **async) static void pipe_async_alloc(struct k_pipe_async **async)
{ {
(void)k_stack_pop(&pipe_async_msgs, (u32_t *)async, K_FOREVER); (void)k_stack_pop(&pipe_async_msgs, (stack_data_t *)async, K_FOREVER);
} }
/* Free an asynchronous message descriptor */ /* Free an asynchronous message descriptor */
static void pipe_async_free(struct k_pipe_async *async) static void pipe_async_free(struct k_pipe_async *async)
{ {
k_stack_push(&pipe_async_msgs, (u32_t)async); k_stack_push(&pipe_async_msgs, (stack_data_t)async);
} }
/* Finish an asynchronous operation */ /* Finish an asynchronous operation */
@ -108,7 +108,7 @@ static int init_pipes_module(struct device *dev)
z_init_thread_timeout(&async_msg[i].thread); z_init_thread_timeout(&async_msg[i].thread);
k_stack_push(&pipe_async_msgs, (u32_t)&async_msg[i]); k_stack_push(&pipe_async_msgs, (stack_data_t)&async_msg[i]);
} }
#endif /* CONFIG_NUM_PIPE_ASYNC_MSGS > 0 */ #endif /* CONFIG_NUM_PIPE_ASYNC_MSGS > 0 */

View file

@ -41,7 +41,7 @@ SYS_INIT(init_stack_module, PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_OBJECTS);
#endif /* CONFIG_OBJECT_TRACING */ #endif /* CONFIG_OBJECT_TRACING */
void k_stack_init(struct k_stack *stack, u32_t *buffer, void k_stack_init(struct k_stack *stack, stack_data_t *buffer,
u32_t num_entries) u32_t num_entries)
{ {
z_waitq_init(&stack->wait_q); z_waitq_init(&stack->wait_q);
@ -58,7 +58,7 @@ s32_t z_impl_k_stack_alloc_init(struct k_stack *stack, u32_t num_entries)
void *buffer; void *buffer;
s32_t ret; s32_t ret;
buffer = z_thread_malloc(num_entries * sizeof(u32_t)); buffer = z_thread_malloc(num_entries * sizeof(stack_data_t));
if (buffer != NULL) { if (buffer != NULL) {
k_stack_init(stack, buffer, num_entries); k_stack_init(stack, buffer, num_entries);
stack->flags = K_STACK_FLAG_ALLOC; stack->flags = K_STACK_FLAG_ALLOC;
@ -91,7 +91,7 @@ void k_stack_cleanup(struct k_stack *stack)
} }
} }
void z_impl_k_stack_push(struct k_stack *stack, u32_t data) void z_impl_k_stack_push(struct k_stack *stack, stack_data_t data)
{ {
struct k_thread *first_pending_thread; struct k_thread *first_pending_thread;
k_spinlock_key_t key; k_spinlock_key_t key;
@ -131,7 +131,7 @@ Z_SYSCALL_HANDLER(k_stack_push, stack_p, data)
} }
#endif #endif
int z_impl_k_stack_pop(struct k_stack *stack, u32_t *data, s32_t timeout) int z_impl_k_stack_pop(struct k_stack *stack, stack_data_t *data, s32_t timeout)
{ {
k_spinlock_key_t key; k_spinlock_key_t key;
int result; int result;
@ -155,7 +155,7 @@ int z_impl_k_stack_pop(struct k_stack *stack, u32_t *data, s32_t timeout)
return -EAGAIN; return -EAGAIN;
} }
*data = (u32_t)_current->base.swap_data; *data = (stack_data_t)_current->base.swap_data;
return 0; return 0;
} }
@ -163,9 +163,9 @@ int z_impl_k_stack_pop(struct k_stack *stack, u32_t *data, s32_t timeout)
Z_SYSCALL_HANDLER(k_stack_pop, stack, data, timeout) Z_SYSCALL_HANDLER(k_stack_pop, stack, data, timeout)
{ {
Z_OOPS(Z_SYSCALL_OBJ(stack, K_OBJ_STACK)); Z_OOPS(Z_SYSCALL_OBJ(stack, K_OBJ_STACK));
Z_OOPS(Z_SYSCALL_MEMORY_WRITE(data, sizeof(u32_t))); Z_OOPS(Z_SYSCALL_MEMORY_WRITE(data, sizeof(stack_data_t)));
return z_impl_k_stack_pop((struct k_stack *)stack, (u32_t *)data, return z_impl_k_stack_pop((struct k_stack *)stack, (stack_data_t *)data,
timeout); timeout);
} }
#endif #endif

View file

@ -11,8 +11,8 @@
struct k_stack stack_1; struct k_stack stack_1;
struct k_stack stack_2; struct k_stack stack_2;
u32_t stack1[2]; stack_data_t stack1[2];
u32_t stack2[2]; stack_data_t stack2[2];
/** /**
* *
@ -43,7 +43,7 @@ void stack_thread1(void *par1, void *par2, void *par3)
{ {
int num_loops = POINTER_TO_INT(par2) / 2; int num_loops = POINTER_TO_INT(par2) / 2;
int i; int i;
u32_t data; stack_data_t data;
ARG_UNUSED(par1); ARG_UNUSED(par1);
ARG_UNUSED(par3); ARG_UNUSED(par3);
@ -79,7 +79,7 @@ void stack_thread1(void *par1, void *par2, void *par3)
void stack_thread2(void *par1, void *par2, void *par3) void stack_thread2(void *par1, void *par2, void *par3)
{ {
int i; int i;
u32_t data; stack_data_t data;
int *pcounter = par1; int *pcounter = par1;
int num_loops = POINTER_TO_INT(par2); int num_loops = POINTER_TO_INT(par2);
@ -111,7 +111,7 @@ void stack_thread2(void *par1, void *par2, void *par3)
void stack_thread3(void *par1, void *par2, void *par3) void stack_thread3(void *par1, void *par2, void *par3)
{ {
int i; int i;
u32_t data; stack_data_t data;
int *pcounter = par1; int *pcounter = par1;
int num_loops = POINTER_TO_INT(par2); int num_loops = POINTER_TO_INT(par2);
@ -220,7 +220,7 @@ int stack_test(void)
K_PRIO_COOP(3), 0, K_NO_WAIT); K_PRIO_COOP(3), 0, K_NO_WAIT);
for (i = 0; i < number_of_loops / 2U; i++) { for (i = 0; i < number_of_loops / 2U; i++) {
u32_t data; stack_data_t data;
data = 2 * i; data = 2 * i;
k_stack_push(&stack_1, data); k_stack_push(&stack_1, data);

View file

@ -53,7 +53,7 @@ static struct k_queue queue;
#define NUM_BLOCKS 4 #define NUM_BLOCKS 4
static char __aligned(8) slab[BLOCK_SIZE * NUM_BLOCKS]; static char __aligned(8) slab[BLOCK_SIZE * NUM_BLOCKS];
static u32_t sdata[BLOCK_SIZE * NUM_BLOCKS]; static stack_data_t sdata[BLOCK_SIZE * NUM_BLOCKS];
static char buffer[BLOCK_SIZE * NUM_BLOCKS]; static char buffer[BLOCK_SIZE * NUM_BLOCKS];
static char data[] = "test"; static char data[] = "test";

View file

@ -16,7 +16,7 @@ struct k_stack stack;
K_THREAD_STACK_DEFINE(threadstack, STACK_SIZE); K_THREAD_STACK_DEFINE(threadstack, STACK_SIZE);
struct k_thread thread_data; struct k_thread thread_data;
static ZTEST_DMEM u32_t data[STACK_LEN] = { 0xABCD, 0x1234 }; static ZTEST_DMEM stack_data_t data[STACK_LEN] = { 0xABCD, 0x1234 };
struct k_sem end_sema; struct k_sem end_sema;
static void tstack_push(struct k_stack *pstack) static void tstack_push(struct k_stack *pstack)
@ -29,7 +29,7 @@ static void tstack_push(struct k_stack *pstack)
static void tstack_pop(struct k_stack *pstack) static void tstack_pop(struct k_stack *pstack)
{ {
u32_t rx_data; stack_data_t rx_data;
for (int i = STACK_LEN - 1; i >= 0; i--) { for (int i = STACK_LEN - 1; i >= 0; i--) {
/**TESTPOINT: stack pop*/ /**TESTPOINT: stack pop*/

View file

@ -10,12 +10,12 @@
#define TIMEOUT 100 #define TIMEOUT 100
#define STACK_LEN 2 #define STACK_LEN 2
static ZTEST_BMEM u32_t data[STACK_LEN]; static ZTEST_BMEM stack_data_t data[STACK_LEN];
extern struct k_stack stack; extern struct k_stack stack;
static void stack_pop_fail(struct k_stack *stack) static void stack_pop_fail(struct k_stack *stack)
{ {
u32_t rx_data; stack_data_t rx_data;
/**TESTPOINT: stack pop returns -EBUSY*/ /**TESTPOINT: stack pop returns -EBUSY*/
zassert_equal(k_stack_pop(stack, &rx_data, K_NO_WAIT), -EBUSY, NULL); zassert_equal(k_stack_pop(stack, &rx_data, K_NO_WAIT), -EBUSY, NULL);

View file

@ -47,9 +47,9 @@ K_THREAD_STACK_DEFINE(threadstack, TSTACK_SIZE);
struct k_thread thread_data; struct k_thread thread_data;
/* Data pushed to stack */ /* Data pushed to stack */
static ZTEST_DMEM u32_t data1[STACK_LEN] = { 0xAAAA, 0xBBBB, 0xCCCC, 0xDDDD }; static ZTEST_DMEM stack_data_t data1[STACK_LEN] = { 0xAAAA, 0xBBBB, 0xCCCC, 0xDDDD };
static ZTEST_DMEM u32_t data2[STACK_LEN] = { 0x1111, 0x2222, 0x3333, 0x4444 }; static ZTEST_DMEM stack_data_t data2[STACK_LEN] = { 0x1111, 0x2222, 0x3333, 0x4444 };
static ZTEST_DMEM u32_t data_isr[STACK_LEN] = { 0xABCD, 0xABCD, 0xABCD, static ZTEST_DMEM stack_data_t data_isr[STACK_LEN] = { 0xABCD, 0xABCD, 0xABCD,
0xABCD }; 0xABCD };
/* semaphore to sync threads */ /* semaphore to sync threads */
@ -82,7 +82,7 @@ static void tIsr_entry_pop(void *p)
static void thread_entry_fn_single(void *p1, void *p2, void *p3) static void thread_entry_fn_single(void *p1, void *p2, void *p3)
{ {
u32_t tmp[STACK_LEN]; stack_data_t tmp[STACK_LEN];
u32_t i; u32_t i;
/* Pop items from stack */ /* Pop items from stack */
@ -103,7 +103,7 @@ static void thread_entry_fn_single(void *p1, void *p2, void *p3)
static void thread_entry_fn_dual(void *p1, void *p2, void *p3) static void thread_entry_fn_dual(void *p1, void *p2, void *p3)
{ {
u32_t tmp[STACK_LEN]; stack_data_t tmp[STACK_LEN];
u32_t i; u32_t i;
for (i = 0U; i < STACK_LEN; i++) { for (i = 0U; i < STACK_LEN; i++) {
@ -143,7 +143,7 @@ static void thread_entry_fn_isr(void *p1, void *p2, void *p3)
*/ */
static void test_single_stack_play(void) static void test_single_stack_play(void)
{ {
u32_t tmp[STACK_LEN]; stack_data_t tmp[STACK_LEN];
u32_t i; u32_t i;
/* Init kernel objects */ /* Init kernel objects */
@ -180,7 +180,7 @@ static void test_single_stack_play(void)
*/ */
static void test_dual_stack_play(void) static void test_dual_stack_play(void)
{ {
u32_t tmp[STACK_LEN]; stack_data_t tmp[STACK_LEN];
u32_t i; u32_t i;
k_tid_t tid = k_thread_create(&thread_data, threadstack, TSTACK_SIZE, k_tid_t tid = k_thread_create(&thread_data, threadstack, TSTACK_SIZE,