Skip to content
Permalink
Browse files

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>
  • Loading branch information...
Nicolas Pitre authored and nashif committed May 18, 2019
1 parent ea44b05 commit 3d51f7c26603cd65fd032bbde0535c05e9952172
@@ -5,7 +5,7 @@ Stacks

A :dfn:`stack` is a kernel object that implements a traditional
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::
:local:
@@ -19,9 +19,11 @@ by its memory address.

A stack has the following key properties:

* A **queue** of 32-bit data values that have been added but not yet removed.
The queue is implemented using an array of 32-bit integers,
and must be aligned on a 4-byte boundary.
* A **queue** of integer data values that have been added but not yet removed.
The queue is implemented using an array of stack_data_t values
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.

@@ -60,13 +62,13 @@ provided and it is instead allocated from the calling thread's resource
pool.

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

#define MAX_ITEMS 10

u32_t my_stack_array[MAX_ITEMS];
stack_data_t my_stack_array[MAX_ITEMS];
struct k_stack my_stack;

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 */
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
@@ -118,13 +120,13 @@ its address back on the stack to allow the data structure to be reused.

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 = ...
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.

Configuration Options
@@ -2419,10 +2419,12 @@ struct k_lifo {
*/
#define K_STACK_FLAG_ALLOC ((u8_t)1) /* Buffer was allocated */

typedef uintptr_t stack_data_t;

struct k_stack {
_wait_q_t wait_q;
struct k_spinlock lock;
u32_t *base, *next, *top;
stack_data_t *base, *next, *top;

_OBJECT_TRACING_NEXT_PTR(k_stack)
u8_t flags;
@@ -2462,7 +2464,7 @@ struct k_stack {
* @req K-STACK-001
*/
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.
*
* 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.
*
@@ -2508,13 +2510,13 @@ void k_stack_cleanup(struct k_stack *stack);
* @return N/A
* @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.
*
* This routine removes a 32-bit value from @a stack in a "last in, first out"
* manner and stores the value in @a data.
* This routine removes a stack_data_t value from @a stack in a "last in,
* 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.
*
@@ -2528,7 +2530,7 @@ __syscall void k_stack_push(struct k_stack *stack, u32_t data);
* @retval -EAGAIN Waiting period timed out.
* @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
@@ -2542,7 +2544,7 @@ __syscall int k_stack_pop(struct k_stack *stack, u32_t *data, s32_t timeout);
* @req K-STACK-002
*/
#define K_STACK_DEFINE(name, stack_num_entries) \
u32_t __noinit \
stack_data_t __noinit \
_k_stack_buf_##name[stack_num_entries]; \
Z_STRUCT_SECTION_ITERABLE(k_stack, name) = \
_K_STACK_INITIALIZER(name, _k_stack_buf_##name, \
@@ -32,13 +32,13 @@ K_STACK_DEFINE(async_msg_free, CONFIG_NUM_MBOX_ASYNC_MSGS);
/* allocate an asynchronous message descriptor */
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 */
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 */
@@ -77,7 +77,7 @@ static int init_mbox_module(struct device *dev)

for (i = 0; i < CONFIG_NUM_MBOX_ASYNC_MSGS; i++) {
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 */

@@ -49,13 +49,13 @@ K_STACK_DEFINE(pipe_async_msgs, CONFIG_NUM_PIPE_ASYNC_MSGS);
/* Allocate an asynchronous message descriptor */
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 */
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 */
@@ -108,7 +108,7 @@ static int init_pipes_module(struct device *dev)

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 */

@@ -41,7 +41,7 @@ SYS_INIT(init_stack_module, PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_OBJECTS);

#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)
{
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;
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) {
k_stack_init(stack, buffer, num_entries);
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;
k_spinlock_key_t key;
@@ -131,7 +131,7 @@ Z_SYSCALL_HANDLER(k_stack_push, stack_p, data)
}
#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;
int result;
@@ -155,17 +155,17 @@ int z_impl_k_stack_pop(struct k_stack *stack, u32_t *data, s32_t timeout)
return -EAGAIN;
}

*data = (u32_t)_current->base.swap_data;
*data = (stack_data_t)_current->base.swap_data;
return 0;
}

#ifdef CONFIG_USERSPACE
Z_SYSCALL_HANDLER(k_stack_pop, stack, data, timeout)
{
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);
}
#endif
@@ -11,8 +11,8 @@
struct k_stack stack_1;
struct k_stack stack_2;

u32_t stack1[2];
u32_t stack2[2];
stack_data_t stack1[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 i;
u32_t data;
stack_data_t data;

ARG_UNUSED(par1);
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)
{
int i;
u32_t data;
stack_data_t data;
int *pcounter = par1;
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)
{
int i;
u32_t data;
stack_data_t data;
int *pcounter = par1;
int num_loops = POINTER_TO_INT(par2);

@@ -220,7 +220,7 @@ int stack_test(void)
K_PRIO_COOP(3), 0, K_NO_WAIT);

for (i = 0; i < number_of_loops / 2U; i++) {
u32_t data;
stack_data_t data;

data = 2 * i;
k_stack_push(&stack_1, data);
@@ -53,7 +53,7 @@ static struct k_queue queue;
#define NUM_BLOCKS 4

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 data[] = "test";

@@ -16,7 +16,7 @@ struct k_stack stack;

K_THREAD_STACK_DEFINE(threadstack, STACK_SIZE);
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;

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)
{
u32_t rx_data;
stack_data_t rx_data;

for (int i = STACK_LEN - 1; i >= 0; i--) {
/**TESTPOINT: stack pop*/
@@ -10,12 +10,12 @@
#define TIMEOUT 100
#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;

static void stack_pop_fail(struct k_stack *stack)
{
u32_t rx_data;
stack_data_t rx_data;

/**TESTPOINT: stack pop returns -EBUSY*/
zassert_equal(k_stack_pop(stack, &rx_data, K_NO_WAIT), -EBUSY, NULL);
@@ -47,10 +47,10 @@ K_THREAD_STACK_DEFINE(threadstack, TSTACK_SIZE);
struct k_thread thread_data;

/* Data pushed to stack */
static ZTEST_DMEM u32_t data1[STACK_LEN] = { 0xAAAA, 0xBBBB, 0xCCCC, 0xDDDD };
static ZTEST_DMEM u32_t data2[STACK_LEN] = { 0x1111, 0x2222, 0x3333, 0x4444 };
static ZTEST_DMEM u32_t data_isr[STACK_LEN] = { 0xABCD, 0xABCD, 0xABCD,
0xABCD };
static ZTEST_DMEM stack_data_t data1[STACK_LEN] = { 0xAAAA, 0xBBBB, 0xCCCC, 0xDDDD };
static ZTEST_DMEM stack_data_t data2[STACK_LEN] = { 0x1111, 0x2222, 0x3333, 0x4444 };
static ZTEST_DMEM stack_data_t data_isr[STACK_LEN] = { 0xABCD, 0xABCD, 0xABCD,
0xABCD };

/* semaphore to sync threads */
static struct k_sem end_sema;
@@ -82,7 +82,7 @@ static void tIsr_entry_pop(void *p)

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;

/* 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)
{
u32_t tmp[STACK_LEN];
stack_data_t tmp[STACK_LEN];
u32_t 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)
{
u32_t tmp[STACK_LEN];
stack_data_t tmp[STACK_LEN];
u32_t i;

/* Init kernel objects */
@@ -180,7 +180,7 @@ static void test_single_stack_play(void)
*/
static void test_dual_stack_play(void)
{
u32_t tmp[STACK_LEN];
stack_data_t tmp[STACK_LEN];
u32_t i;

k_tid_t tid = k_thread_create(&thread_data, threadstack, TSTACK_SIZE,

0 comments on commit 3d51f7c

Please sign in to comment.
You can’t perform that action at this time.