blob: 75f15026c15516cc34af0a2d0276ca47e155e34f [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 Nashif569f0b42016-12-17 13:18:45 -050013#include <debug/object_tracing_common.h>
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
Anas Nashif2f203c22016-12-18 06:57:45 -050022#ifdef CONFIG_OBJECT_TRACING
Allan Stephense7d2cc22016-10-19 16:10:46 -050023
Maciek Borzecki059544d2017-05-18 12:16:45 +020024struct k_stack *_trace_list_k_stack;
25
Allan Stephense7d2cc22016-10-19 16:10:46 -050026/*
27 * Complete initialization of statically defined stacks.
28 */
Tomasz Bursztykae18fcbb2020-04-30 20:33:38 +020029static int init_stack_module(const struct device *dev)
Allan Stephense7d2cc22016-10-19 16:10:46 -050030{
31 ARG_UNUSED(dev);
32
Nicolas Pitreaa9228852019-06-03 13:01:43 -040033 Z_STRUCT_SECTION_FOREACH(k_stack, stack) {
Allan Stephense7d2cc22016-10-19 16:10:46 -050034 SYS_TRACING_OBJ_INIT(k_stack, stack);
35 }
36 return 0;
37}
38
Andrew Boie0b474ee2016-11-08 11:06:55 -080039SYS_INIT(init_stack_module, PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_OBJECTS);
Allan Stephense7d2cc22016-10-19 16:10:46 -050040
Anas Nashif2f203c22016-12-18 06:57:45 -050041#endif /* CONFIG_OBJECT_TRACING */
Benjamin Walsh456c6da2016-09-02 18:55:39 -040042
Nicolas Pitre3d51f7c2019-05-17 22:48:26 -040043void k_stack_init(struct k_stack *stack, stack_data_t *buffer,
Kumar Galaa1b77fd2020-05-27 11:26:57 -050044 uint32_t num_entries)
Benjamin Walsh456c6da2016-09-02 18:55:39 -040045{
Patrik Flykt4344e272019-03-08 14:19:05 -070046 z_waitq_init(&stack->wait_q);
Andy Rossf0933d02018-07-26 10:23:02 -070047 stack->lock = (struct k_spinlock) {};
48 stack->next = stack->base = buffer;
Benjamin Walsh456c6da2016-09-02 18:55:39 -040049 stack->top = stack->base + num_entries;
50
51 SYS_TRACING_OBJ_INIT(k_stack, stack);
Patrik Flykt4344e272019-03-08 14:19:05 -070052 z_object_init(stack);
Benjamin Walsh456c6da2016-09-02 18:55:39 -040053}
54
Kumar Galaa1b77fd2020-05-27 11:26:57 -050055int32_t z_impl_k_stack_alloc_init(struct k_stack *stack, uint32_t num_entries)
Andrew Boiee8734462017-09-29 16:42:07 -070056{
Andrew Boief3bee952018-05-02 17:44:39 -070057 void *buffer;
Kumar Galaa1b77fd2020-05-27 11:26:57 -050058 int32_t ret;
Andrew Boiee8734462017-09-29 16:42:07 -070059
Nicolas Pitre3d51f7c2019-05-17 22:48:26 -040060 buffer = z_thread_malloc(num_entries * sizeof(stack_data_t));
Flavio Ceolinea716bf2018-09-20 16:30:45 -070061 if (buffer != NULL) {
Andrew Boief3bee952018-05-02 17:44:39 -070062 k_stack_init(stack, buffer, num_entries);
63 stack->flags = K_STACK_FLAG_ALLOC;
Kumar Galaa1b77fd2020-05-27 11:26:57 -050064 ret = (int32_t)0;
Andrew Boief3bee952018-05-02 17:44:39 -070065 } else {
66 ret = -ENOMEM;
67 }
68
69 return ret;
70}
71
72#ifdef CONFIG_USERSPACE
Kumar Galaa1b77fd2020-05-27 11:26:57 -050073static inline int32_t z_vrfy_k_stack_alloc_init(struct k_stack *stack,
74 uint32_t num_entries)
Andrew Boief3bee952018-05-02 17:44:39 -070075{
Andrew Boie8345e5e2018-05-04 15:57:57 -070076 Z_OOPS(Z_SYSCALL_OBJ_NEVER_INIT(stack, K_OBJ_STACK));
77 Z_OOPS(Z_SYSCALL_VERIFY(num_entries > 0));
Andy Ross65649742019-08-06 13:34:31 -070078 return z_impl_k_stack_alloc_init(stack, num_entries);
Andrew Boiee8734462017-09-29 16:42:07 -070079}
Andy Ross65649742019-08-06 13:34:31 -070080#include <syscalls/k_stack_alloc_init_mrsh.c>
Andrew Boiee8734462017-09-29 16:42:07 -070081#endif
82
Anas Nashif1ed67d12019-06-16 08:58:10 -040083int k_stack_cleanup(struct k_stack *stack)
Andrew Boief3bee952018-05-02 17:44:39 -070084{
Anas Nashif1ed67d12019-06-16 08:58:10 -040085 CHECKIF(z_waitq_head(&stack->wait_q) != NULL) {
86 return -EAGAIN;
87 }
Andrew Boief3bee952018-05-02 17:44:39 -070088
Kumar Galaa1b77fd2020-05-27 11:26:57 -050089 if ((stack->flags & K_STACK_FLAG_ALLOC) != (uint8_t)0) {
Andrew Boief3bee952018-05-02 17:44:39 -070090 k_free(stack->base);
91 stack->base = NULL;
92 stack->flags &= ~K_STACK_FLAG_ALLOC;
93 }
Anas Nashif1ed67d12019-06-16 08:58:10 -040094 return 0;
Andrew Boief3bee952018-05-02 17:44:39 -070095}
96
Anas Nashif1ed67d12019-06-16 08:58:10 -040097int z_impl_k_stack_push(struct k_stack *stack, stack_data_t data)
Benjamin Walsh456c6da2016-09-02 18:55:39 -040098{
99 struct k_thread *first_pending_thread;
Jennifer Williams4d330072020-09-29 15:16:39 -0700100 int ret = 0;
101 k_spinlock_key_t key = k_spin_lock(&stack->lock);
Benjamin Walsh456c6da2016-09-02 18:55:39 -0400102
Anas Nashif1ed67d12019-06-16 08:58:10 -0400103 CHECKIF(stack->next == stack->top) {
Jennifer Williams4d330072020-09-29 15:16:39 -0700104 ret = -ENOMEM;
105 goto out;
Anas Nashif1ed67d12019-06-16 08:58:10 -0400106 }
Benjamin Walsh456c6da2016-09-02 18:55:39 -0400107
Patrik Flykt4344e272019-03-08 14:19:05 -0700108 first_pending_thread = z_unpend_first_thread(&stack->wait_q);
Benjamin Walsh456c6da2016-09-02 18:55:39 -0400109
Flavio Ceolinea716bf2018-09-20 16:30:45 -0700110 if (first_pending_thread != NULL) {
Patrik Flykt4344e272019-03-08 14:19:05 -0700111 z_ready_thread(first_pending_thread);
Benjamin Walsh456c6da2016-09-02 18:55:39 -0400112
Andrew Boie4ad9f682019-09-21 16:25:56 -0700113 z_thread_return_value_set_with_data(first_pending_thread,
Benjamin Walsh456c6da2016-09-02 18:55:39 -0400114 0, (void *)data);
Patrik Flykt4344e272019-03-08 14:19:05 -0700115 z_reschedule(&stack->lock, key);
Jennifer Williams4d330072020-09-29 15:16:39 -0700116 goto end;
Benjamin Walsh456c6da2016-09-02 18:55:39 -0400117 } else {
118 *(stack->next) = data;
119 stack->next++;
Jennifer Williams4d330072020-09-29 15:16:39 -0700120 goto out;
Benjamin Walsh456c6da2016-09-02 18:55:39 -0400121 }
122
Jennifer Williams4d330072020-09-29 15:16:39 -0700123out:
124 k_spin_unlock(&stack->lock, key);
125
126end:
127 return ret;
Benjamin Walsh456c6da2016-09-02 18:55:39 -0400128}
129
Andrew Boiee8734462017-09-29 16:42:07 -0700130#ifdef CONFIG_USERSPACE
Anas Nashif1ed67d12019-06-16 08:58:10 -0400131static inline int z_vrfy_k_stack_push(struct k_stack *stack, stack_data_t data)
Andrew Boiee8734462017-09-29 16:42:07 -0700132{
Andrew Boie8345e5e2018-05-04 15:57:57 -0700133 Z_OOPS(Z_SYSCALL_OBJ(stack, K_OBJ_STACK));
Anas Nashif1ed67d12019-06-16 08:58:10 -0400134
135 return z_impl_k_stack_push(stack, data);
Andrew Boiee8734462017-09-29 16:42:07 -0700136}
Andy Ross65649742019-08-06 13:34:31 -0700137#include <syscalls/k_stack_push_mrsh.c>
Andrew Boiee8734462017-09-29 16:42:07 -0700138#endif
139
Andy Ross78327382020-03-05 15:18:14 -0800140int z_impl_k_stack_pop(struct k_stack *stack, stack_data_t *data,
141 k_timeout_t timeout)
Benjamin Walsh456c6da2016-09-02 18:55:39 -0400142{
Andy Rossf0933d02018-07-26 10:23:02 -0700143 k_spinlock_key_t key;
Benjamin Walsh456c6da2016-09-02 18:55:39 -0400144 int result;
145
Andy Rossf0933d02018-07-26 10:23:02 -0700146 key = k_spin_lock(&stack->lock);
Benjamin Walsh456c6da2016-09-02 18:55:39 -0400147
148 if (likely(stack->next > stack->base)) {
149 stack->next--;
150 *data = *(stack->next);
Andy Rossf0933d02018-07-26 10:23:02 -0700151 k_spin_unlock(&stack->lock, key);
Benjamin Walsh456c6da2016-09-02 18:55:39 -0400152 return 0;
153 }
154
Andy Ross78327382020-03-05 15:18:14 -0800155 if (K_TIMEOUT_EQ(timeout, K_NO_WAIT)) {
Andy Rossf0933d02018-07-26 10:23:02 -0700156 k_spin_unlock(&stack->lock, key);
Benjamin Walsh456c6da2016-09-02 18:55:39 -0400157 return -EBUSY;
158 }
159
Patrik Flykt4344e272019-03-08 14:19:05 -0700160 result = z_pend_curr(&stack->lock, key, &stack->wait_q, timeout);
Flavio Ceolindfbe0322018-11-01 20:50:25 -0700161 if (result == -EAGAIN) {
Flavio Ceolin8f488ff2018-09-13 11:43:59 -0700162 return -EAGAIN;
Flavio Ceolindfbe0322018-11-01 20:50:25 -0700163 }
Benjamin Walsh456c6da2016-09-02 18:55:39 -0400164
Nicolas Pitre3d51f7c2019-05-17 22:48:26 -0400165 *data = (stack_data_t)_current->base.swap_data;
Flavio Ceolin8f488ff2018-09-13 11:43:59 -0700166 return 0;
Benjamin Walsh456c6da2016-09-02 18:55:39 -0400167}
Andrew Boiee8734462017-09-29 16:42:07 -0700168
169#ifdef CONFIG_USERSPACE
Andy Ross643701a2019-08-13 12:58:38 -0700170static inline int z_vrfy_k_stack_pop(struct k_stack *stack,
Andy Ross78327382020-03-05 15:18:14 -0800171 stack_data_t *data, k_timeout_t timeout)
Andrew Boiee8734462017-09-29 16:42:07 -0700172{
Andrew Boie8345e5e2018-05-04 15:57:57 -0700173 Z_OOPS(Z_SYSCALL_OBJ(stack, K_OBJ_STACK));
Nicolas Pitre3d51f7c2019-05-17 22:48:26 -0400174 Z_OOPS(Z_SYSCALL_MEMORY_WRITE(data, sizeof(stack_data_t)));
Andy Ross65649742019-08-06 13:34:31 -0700175 return z_impl_k_stack_pop(stack, data, timeout);
Andrew Boiee8734462017-09-29 16:42:07 -0700176}
Andy Ross65649742019-08-06 13:34:31 -0700177#include <syscalls/k_stack_pop_mrsh.c>
Andrew Boiee8734462017-09-29 16:42:07 -0700178#endif