blob: 68148314778b71de1769951bcca7551fc20ad59a [file] [log] [blame]
Benjamin Walsh456c6da2016-09-02 18:55:39 -04001/*
2 * Copyright (c) 2010-2016 Wind River Systems, Inc.
3 *
David B. Kinderac74d8b2017-01-18 17:01:01 -08004 * SPDX-License-Identifier: Apache-2.0
Benjamin Walsh456c6da2016-09-02 18:55:39 -04005 */
6
7/**
8 * @brief fixed-size stack object
9 */
10
11#include <kernel.h>
Benjamin Walshf6ca7de2016-11-08 10:36:50 -050012#include <kernel_structs.h>
Anas Nashif4d994af2021-04-18 23:24:40 -040013
Benjamin Walsh456c6da2016-09-02 18:55:39 -040014#include <toolchain.h>
Benjamin Walshb4b108d2016-10-13 10:31:48 -040015#include <ksched.h>
Benjamin Walsh456c6da2016-09-02 18:55:39 -040016#include <wait_q.h>
Anas Nashif1ed67d12019-06-16 08:58:10 -040017#include <sys/check.h>
Allan Stephense7d2cc22016-10-19 16:10:46 -050018#include <init.h>
Andrew Boiee8734462017-09-29 16:42:07 -070019#include <syscall_handler.h>
Andy Ross4f911e12018-09-05 10:13:38 -070020#include <kernel_internal.h>
Allan Stephense7d2cc22016-10-19 16:10:46 -050021
Nicolas Pitre3d51f7c2019-05-17 22:48:26 -040022void k_stack_init(struct k_stack *stack, stack_data_t *buffer,
Kumar Galaa1b77fd2020-05-27 11:26:57 -050023 uint32_t num_entries)
Benjamin Walsh456c6da2016-09-02 18:55:39 -040024{
Patrik Flykt4344e272019-03-08 14:19:05 -070025 z_waitq_init(&stack->wait_q);
Andy Rossf0933d02018-07-26 10:23:02 -070026 stack->lock = (struct k_spinlock) {};
27 stack->next = stack->base = buffer;
Benjamin Walsh456c6da2016-09-02 18:55:39 -040028 stack->top = stack->base + num_entries;
29
Torbjörn Leksell69e88692021-03-26 12:31:43 +010030 SYS_PORT_TRACING_OBJ_INIT(k_stack, stack);
Patrik Flykt4344e272019-03-08 14:19:05 -070031 z_object_init(stack);
Benjamin Walsh456c6da2016-09-02 18:55:39 -040032}
33
Kumar Galaa1b77fd2020-05-27 11:26:57 -050034int32_t z_impl_k_stack_alloc_init(struct k_stack *stack, uint32_t num_entries)
Andrew Boiee8734462017-09-29 16:42:07 -070035{
Andrew Boief3bee952018-05-02 17:44:39 -070036 void *buffer;
Kumar Galaa1b77fd2020-05-27 11:26:57 -050037 int32_t ret;
Andrew Boiee8734462017-09-29 16:42:07 -070038
Torbjörn Leksell69e88692021-03-26 12:31:43 +010039 SYS_PORT_TRACING_OBJ_FUNC_ENTER(k_stack, alloc_init, stack);
40
Nicolas Pitre3d51f7c2019-05-17 22:48:26 -040041 buffer = z_thread_malloc(num_entries * sizeof(stack_data_t));
Flavio Ceolinea716bf2018-09-20 16:30:45 -070042 if (buffer != NULL) {
Andrew Boief3bee952018-05-02 17:44:39 -070043 k_stack_init(stack, buffer, num_entries);
44 stack->flags = K_STACK_FLAG_ALLOC;
Kumar Galaa1b77fd2020-05-27 11:26:57 -050045 ret = (int32_t)0;
Andrew Boief3bee952018-05-02 17:44:39 -070046 } else {
47 ret = -ENOMEM;
48 }
49
Torbjörn Leksell69e88692021-03-26 12:31:43 +010050 SYS_PORT_TRACING_OBJ_FUNC_EXIT(k_stack, alloc_init, stack, ret);
51
Andrew Boief3bee952018-05-02 17:44:39 -070052 return ret;
53}
54
55#ifdef CONFIG_USERSPACE
Kumar Galaa1b77fd2020-05-27 11:26:57 -050056static inline int32_t z_vrfy_k_stack_alloc_init(struct k_stack *stack,
57 uint32_t num_entries)
Andrew Boief3bee952018-05-02 17:44:39 -070058{
Andrew Boie8345e5e2018-05-04 15:57:57 -070059 Z_OOPS(Z_SYSCALL_OBJ_NEVER_INIT(stack, K_OBJ_STACK));
60 Z_OOPS(Z_SYSCALL_VERIFY(num_entries > 0));
Andy Ross65649742019-08-06 13:34:31 -070061 return z_impl_k_stack_alloc_init(stack, num_entries);
Andrew Boiee8734462017-09-29 16:42:07 -070062}
Andy Ross65649742019-08-06 13:34:31 -070063#include <syscalls/k_stack_alloc_init_mrsh.c>
Andrew Boiee8734462017-09-29 16:42:07 -070064#endif
65
Anas Nashif1ed67d12019-06-16 08:58:10 -040066int k_stack_cleanup(struct k_stack *stack)
Andrew Boief3bee952018-05-02 17:44:39 -070067{
Torbjörn Leksell69e88692021-03-26 12:31:43 +010068 SYS_PORT_TRACING_OBJ_FUNC_ENTER(k_stack, cleanup, stack);
69
Anas Nashif1ed67d12019-06-16 08:58:10 -040070 CHECKIF(z_waitq_head(&stack->wait_q) != NULL) {
Torbjörn Leksell69e88692021-03-26 12:31:43 +010071 SYS_PORT_TRACING_OBJ_FUNC_EXIT(k_stack, cleanup, stack, -EAGAIN);
72
Anas Nashif1ed67d12019-06-16 08:58:10 -040073 return -EAGAIN;
74 }
Andrew Boief3bee952018-05-02 17:44:39 -070075
Kumar Galaa1b77fd2020-05-27 11:26:57 -050076 if ((stack->flags & K_STACK_FLAG_ALLOC) != (uint8_t)0) {
Andrew Boief3bee952018-05-02 17:44:39 -070077 k_free(stack->base);
78 stack->base = NULL;
79 stack->flags &= ~K_STACK_FLAG_ALLOC;
80 }
Torbjörn Leksell69e88692021-03-26 12:31:43 +010081
82 SYS_PORT_TRACING_OBJ_FUNC_EXIT(k_stack, cleanup, stack, 0);
83
Anas Nashif1ed67d12019-06-16 08:58:10 -040084 return 0;
Andrew Boief3bee952018-05-02 17:44:39 -070085}
86
Anas Nashif1ed67d12019-06-16 08:58:10 -040087int z_impl_k_stack_push(struct k_stack *stack, stack_data_t data)
Benjamin Walsh456c6da2016-09-02 18:55:39 -040088{
89 struct k_thread *first_pending_thread;
Jennifer Williams4d330072020-09-29 15:16:39 -070090 int ret = 0;
91 k_spinlock_key_t key = k_spin_lock(&stack->lock);
Benjamin Walsh456c6da2016-09-02 18:55:39 -040092
Torbjörn Leksell69e88692021-03-26 12:31:43 +010093 SYS_PORT_TRACING_OBJ_FUNC_ENTER(k_stack, push, stack);
94
Anas Nashif1ed67d12019-06-16 08:58:10 -040095 CHECKIF(stack->next == stack->top) {
Jennifer Williams4d330072020-09-29 15:16:39 -070096 ret = -ENOMEM;
97 goto out;
Anas Nashif1ed67d12019-06-16 08:58:10 -040098 }
Benjamin Walsh456c6da2016-09-02 18:55:39 -040099
Patrik Flykt4344e272019-03-08 14:19:05 -0700100 first_pending_thread = z_unpend_first_thread(&stack->wait_q);
Benjamin Walsh456c6da2016-09-02 18:55:39 -0400101
Flavio Ceolinea716bf2018-09-20 16:30:45 -0700102 if (first_pending_thread != NULL) {
Andrew Boie4ad9f682019-09-21 16:25:56 -0700103 z_thread_return_value_set_with_data(first_pending_thread,
Benjamin Walsh456c6da2016-09-02 18:55:39 -0400104 0, (void *)data);
James Harrisc7bb4232021-03-02 13:22:52 -0800105
106 z_ready_thread(first_pending_thread);
Patrik Flykt4344e272019-03-08 14:19:05 -0700107 z_reschedule(&stack->lock, key);
Jennifer Williams4d330072020-09-29 15:16:39 -0700108 goto end;
Benjamin Walsh456c6da2016-09-02 18:55:39 -0400109 } else {
110 *(stack->next) = data;
111 stack->next++;
Jennifer Williams4d330072020-09-29 15:16:39 -0700112 goto out;
Benjamin Walsh456c6da2016-09-02 18:55:39 -0400113 }
114
Jennifer Williams4d330072020-09-29 15:16:39 -0700115out:
116 k_spin_unlock(&stack->lock, key);
117
118end:
Torbjörn Leksell69e88692021-03-26 12:31:43 +0100119 SYS_PORT_TRACING_OBJ_FUNC_EXIT(k_stack, push, stack, ret);
120
Jennifer Williams4d330072020-09-29 15:16:39 -0700121 return ret;
Benjamin Walsh456c6da2016-09-02 18:55:39 -0400122}
123
Andrew Boiee8734462017-09-29 16:42:07 -0700124#ifdef CONFIG_USERSPACE
Anas Nashif1ed67d12019-06-16 08:58:10 -0400125static inline int z_vrfy_k_stack_push(struct k_stack *stack, stack_data_t data)
Andrew Boiee8734462017-09-29 16:42:07 -0700126{
Andrew Boie8345e5e2018-05-04 15:57:57 -0700127 Z_OOPS(Z_SYSCALL_OBJ(stack, K_OBJ_STACK));
Anas Nashif1ed67d12019-06-16 08:58:10 -0400128
129 return z_impl_k_stack_push(stack, data);
Andrew Boiee8734462017-09-29 16:42:07 -0700130}
Andy Ross65649742019-08-06 13:34:31 -0700131#include <syscalls/k_stack_push_mrsh.c>
Andrew Boiee8734462017-09-29 16:42:07 -0700132#endif
133
Andy Ross78327382020-03-05 15:18:14 -0800134int z_impl_k_stack_pop(struct k_stack *stack, stack_data_t *data,
135 k_timeout_t timeout)
Benjamin Walsh456c6da2016-09-02 18:55:39 -0400136{
Andy Rossf0933d02018-07-26 10:23:02 -0700137 k_spinlock_key_t key;
Benjamin Walsh456c6da2016-09-02 18:55:39 -0400138 int result;
139
Andy Rossf0933d02018-07-26 10:23:02 -0700140 key = k_spin_lock(&stack->lock);
Benjamin Walsh456c6da2016-09-02 18:55:39 -0400141
Torbjörn Leksell69e88692021-03-26 12:31:43 +0100142 SYS_PORT_TRACING_OBJ_FUNC_ENTER(k_stack, pop, stack, timeout);
143
Benjamin Walsh456c6da2016-09-02 18:55:39 -0400144 if (likely(stack->next > stack->base)) {
145 stack->next--;
146 *data = *(stack->next);
Andy Rossf0933d02018-07-26 10:23:02 -0700147 k_spin_unlock(&stack->lock, key);
Torbjörn Leksell69e88692021-03-26 12:31:43 +0100148
149 SYS_PORT_TRACING_OBJ_FUNC_EXIT(k_stack, pop, stack, timeout, 0);
150
Benjamin Walsh456c6da2016-09-02 18:55:39 -0400151 return 0;
152 }
153
Torbjörn Leksell69e88692021-03-26 12:31:43 +0100154 SYS_PORT_TRACING_OBJ_FUNC_BLOCKING(k_stack, pop, stack, timeout);
155
Andy Ross78327382020-03-05 15:18:14 -0800156 if (K_TIMEOUT_EQ(timeout, K_NO_WAIT)) {
Andy Rossf0933d02018-07-26 10:23:02 -0700157 k_spin_unlock(&stack->lock, key);
Torbjörn Leksell69e88692021-03-26 12:31:43 +0100158
159 SYS_PORT_TRACING_OBJ_FUNC_EXIT(k_stack, pop, stack, timeout, -EBUSY);
160
Benjamin Walsh456c6da2016-09-02 18:55:39 -0400161 return -EBUSY;
162 }
163
Patrik Flykt4344e272019-03-08 14:19:05 -0700164 result = z_pend_curr(&stack->lock, key, &stack->wait_q, timeout);
Flavio Ceolindfbe0322018-11-01 20:50:25 -0700165 if (result == -EAGAIN) {
Torbjörn Leksell69e88692021-03-26 12:31:43 +0100166 SYS_PORT_TRACING_OBJ_FUNC_EXIT(k_stack, pop, stack, timeout, -EAGAIN);
167
Flavio Ceolin8f488ff2018-09-13 11:43:59 -0700168 return -EAGAIN;
Flavio Ceolindfbe0322018-11-01 20:50:25 -0700169 }
Benjamin Walsh456c6da2016-09-02 18:55:39 -0400170
Nicolas Pitre3d51f7c2019-05-17 22:48:26 -0400171 *data = (stack_data_t)_current->base.swap_data;
Torbjörn Leksell69e88692021-03-26 12:31:43 +0100172
173 SYS_PORT_TRACING_OBJ_FUNC_EXIT(k_stack, pop, stack, timeout, 0);
174
Flavio Ceolin8f488ff2018-09-13 11:43:59 -0700175 return 0;
Benjamin Walsh456c6da2016-09-02 18:55:39 -0400176}
Andrew Boiee8734462017-09-29 16:42:07 -0700177
178#ifdef CONFIG_USERSPACE
Andy Ross643701a2019-08-13 12:58:38 -0700179static inline int z_vrfy_k_stack_pop(struct k_stack *stack,
Andy Ross78327382020-03-05 15:18:14 -0800180 stack_data_t *data, k_timeout_t timeout)
Andrew Boiee8734462017-09-29 16:42:07 -0700181{
Andrew Boie8345e5e2018-05-04 15:57:57 -0700182 Z_OOPS(Z_SYSCALL_OBJ(stack, K_OBJ_STACK));
Nicolas Pitre3d51f7c2019-05-17 22:48:26 -0400183 Z_OOPS(Z_SYSCALL_MEMORY_WRITE(data, sizeof(stack_data_t)));
Andy Ross65649742019-08-06 13:34:31 -0700184 return z_impl_k_stack_pop(stack, data, timeout);
Andrew Boiee8734462017-09-29 16:42:07 -0700185}
Andy Ross65649742019-08-06 13:34:31 -0700186#include <syscalls/k_stack_pop_mrsh.c>
Andrew Boiee8734462017-09-29 16:42:07 -0700187#endif