blob: 16d4ffcd1076afc517983230a336b0d7e9cd7e2d [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>
Anas Nashif397d29d2017-06-17 11:30:47 -040015#include <linker/sections.h>
Benjamin Walshb4b108d2016-10-13 10:31:48 -040016#include <ksched.h>
Benjamin Walsh456c6da2016-09-02 18:55:39 -040017#include <wait_q.h>
18#include <misc/__assert.h>
Allan Stephense7d2cc22016-10-19 16:10:46 -050019#include <init.h>
Andrew Boiee8734462017-09-29 16:42:07 -070020#include <syscall_handler.h>
Andy Ross4f911e12018-09-05 10:13:38 -070021#include <kernel_internal.h>
Allan Stephense7d2cc22016-10-19 16:10:46 -050022
23extern struct k_stack _k_stack_list_start[];
24extern struct k_stack _k_stack_list_end[];
25
Anas Nashif2f203c22016-12-18 06:57:45 -050026#ifdef CONFIG_OBJECT_TRACING
Allan Stephense7d2cc22016-10-19 16:10:46 -050027
Maciek Borzecki059544d2017-05-18 12:16:45 +020028struct k_stack *_trace_list_k_stack;
29
Allan Stephense7d2cc22016-10-19 16:10:46 -050030/*
31 * Complete initialization of statically defined stacks.
32 */
33static int init_stack_module(struct device *dev)
34{
35 ARG_UNUSED(dev);
36
37 struct k_stack *stack;
38
39 for (stack = _k_stack_list_start; stack < _k_stack_list_end; stack++) {
40 SYS_TRACING_OBJ_INIT(k_stack, stack);
41 }
42 return 0;
43}
44
Andrew Boie0b474ee2016-11-08 11:06:55 -080045SYS_INIT(init_stack_module, PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_OBJECTS);
Allan Stephense7d2cc22016-10-19 16:10:46 -050046
Anas Nashif2f203c22016-12-18 06:57:45 -050047#endif /* CONFIG_OBJECT_TRACING */
Benjamin Walsh456c6da2016-09-02 18:55:39 -040048
Andrew Boief3bee952018-05-02 17:44:39 -070049void k_stack_init(struct k_stack *stack, u32_t *buffer,
Adithya Baglody28080d32018-10-15 11:48:51 +053050 u32_t num_entries)
Benjamin Walsh456c6da2016-09-02 18:55:39 -040051{
Andy Rossccf3bf72018-05-10 11:10:34 -070052 _waitq_init(&stack->wait_q);
Andy Rossf0933d02018-07-26 10:23:02 -070053 stack->lock = (struct k_spinlock) {};
54 stack->next = stack->base = buffer;
Benjamin Walsh456c6da2016-09-02 18:55:39 -040055 stack->top = stack->base + num_entries;
56
57 SYS_TRACING_OBJ_INIT(k_stack, stack);
Andrew Boie945af952017-08-22 13:15:23 -070058 _k_object_init(stack);
Benjamin Walsh456c6da2016-09-02 18:55:39 -040059}
60
Adithya Baglody28080d32018-10-15 11:48:51 +053061s32_t _impl_k_stack_alloc_init(struct k_stack *stack, u32_t num_entries)
Andrew Boiee8734462017-09-29 16:42:07 -070062{
Andrew Boief3bee952018-05-02 17:44:39 -070063 void *buffer;
Adithya Baglody28080d32018-10-15 11:48:51 +053064 s32_t ret;
Andrew Boiee8734462017-09-29 16:42:07 -070065
Andrew Boief3bee952018-05-02 17:44:39 -070066 buffer = z_thread_malloc(num_entries);
Flavio Ceolinea716bf2018-09-20 16:30:45 -070067 if (buffer != NULL) {
Andrew Boief3bee952018-05-02 17:44:39 -070068 k_stack_init(stack, buffer, num_entries);
69 stack->flags = K_STACK_FLAG_ALLOC;
Adithya Baglody28080d32018-10-15 11:48:51 +053070 ret = (s32_t)0;
Andrew Boief3bee952018-05-02 17:44:39 -070071 } else {
72 ret = -ENOMEM;
73 }
74
75 return ret;
76}
77
78#ifdef CONFIG_USERSPACE
Andrew Boie8345e5e2018-05-04 15:57:57 -070079Z_SYSCALL_HANDLER(k_stack_alloc_init, stack, num_entries)
Andrew Boief3bee952018-05-02 17:44:39 -070080{
Andrew Boie8345e5e2018-05-04 15:57:57 -070081 Z_OOPS(Z_SYSCALL_OBJ_NEVER_INIT(stack, K_OBJ_STACK));
82 Z_OOPS(Z_SYSCALL_VERIFY(num_entries > 0));
Andrew Boief3bee952018-05-02 17:44:39 -070083
Flavio Ceolin585d90f2018-09-12 23:03:05 -070084 return _impl_k_stack_alloc_init((struct k_stack *)stack, num_entries);
Andrew Boiee8734462017-09-29 16:42:07 -070085}
86#endif
87
Andrew Boief3bee952018-05-02 17:44:39 -070088void k_stack_cleanup(struct k_stack *stack)
89{
Adithya Baglody28080d32018-10-15 11:48:51 +053090 __ASSERT_NO_MSG(_waitq_head(&stack->wait_q) == NULL);
Andrew Boief3bee952018-05-02 17:44:39 -070091
Adithya Baglody28080d32018-10-15 11:48:51 +053092 if ((stack->flags & K_STACK_FLAG_ALLOC) != (u8_t)0) {
Andrew Boief3bee952018-05-02 17:44:39 -070093 k_free(stack->base);
94 stack->base = NULL;
95 stack->flags &= ~K_STACK_FLAG_ALLOC;
96 }
97}
98
Andrew Boiee8734462017-09-29 16:42:07 -070099void _impl_k_stack_push(struct k_stack *stack, u32_t data)
Benjamin Walsh456c6da2016-09-02 18:55:39 -0400100{
101 struct k_thread *first_pending_thread;
Andy Rossf0933d02018-07-26 10:23:02 -0700102 k_spinlock_key_t key;
Benjamin Walsh456c6da2016-09-02 18:55:39 -0400103
104 __ASSERT(stack->next != stack->top, "stack is full");
105
Andy Rossf0933d02018-07-26 10:23:02 -0700106 key = k_spin_lock(&stack->lock);
Benjamin Walsh456c6da2016-09-02 18:55:39 -0400107
108 first_pending_thread = _unpend_first_thread(&stack->wait_q);
109
Flavio Ceolinea716bf2018-09-20 16:30:45 -0700110 if (first_pending_thread != NULL) {
Benjamin Walsh456c6da2016-09-02 18:55:39 -0400111 _ready_thread(first_pending_thread);
112
113 _set_thread_return_value_with_data(first_pending_thread,
114 0, (void *)data);
Andy Rossf0933d02018-07-26 10:23:02 -0700115 _reschedule(&stack->lock, key);
Andy Ross8606fab2018-03-26 10:54:40 -0700116 return;
Benjamin Walsh456c6da2016-09-02 18:55:39 -0400117 } else {
118 *(stack->next) = data;
119 stack->next++;
Andy Rossf0933d02018-07-26 10:23:02 -0700120 k_spin_unlock(&stack->lock, key);
Benjamin Walsh456c6da2016-09-02 18:55:39 -0400121 }
122
Benjamin Walsh456c6da2016-09-02 18:55:39 -0400123}
124
Andrew Boiee8734462017-09-29 16:42:07 -0700125#ifdef CONFIG_USERSPACE
Andrew Boie8345e5e2018-05-04 15:57:57 -0700126Z_SYSCALL_HANDLER(k_stack_push, stack_p, data)
Andrew Boiee8734462017-09-29 16:42:07 -0700127{
128 struct k_stack *stack = (struct k_stack *)stack_p;
Andrew Boiee8734462017-09-29 16:42:07 -0700129
Andrew Boie8345e5e2018-05-04 15:57:57 -0700130 Z_OOPS(Z_SYSCALL_OBJ(stack, K_OBJ_STACK));
131 Z_OOPS(Z_SYSCALL_VERIFY_MSG(stack->next != stack->top,
132 "stack is full"));
Andrew Boiee8734462017-09-29 16:42:07 -0700133
134 _impl_k_stack_push(stack, data);
135 return 0;
136}
137#endif
138
139int _impl_k_stack_pop(struct k_stack *stack, u32_t *data, s32_t timeout)
Benjamin Walsh456c6da2016-09-02 18:55:39 -0400140{
Andy Rossf0933d02018-07-26 10:23:02 -0700141 k_spinlock_key_t key;
Benjamin Walsh456c6da2016-09-02 18:55:39 -0400142 int result;
143
Andy Rossf0933d02018-07-26 10:23:02 -0700144 key = k_spin_lock(&stack->lock);
Benjamin Walsh456c6da2016-09-02 18:55:39 -0400145
146 if (likely(stack->next > stack->base)) {
147 stack->next--;
148 *data = *(stack->next);
Andy Rossf0933d02018-07-26 10:23:02 -0700149 k_spin_unlock(&stack->lock, key);
Benjamin Walsh456c6da2016-09-02 18:55:39 -0400150 return 0;
151 }
152
153 if (timeout == K_NO_WAIT) {
Andy Rossf0933d02018-07-26 10:23:02 -0700154 k_spin_unlock(&stack->lock, key);
Benjamin Walsh456c6da2016-09-02 18:55:39 -0400155 return -EBUSY;
156 }
157
Andy Rossf0933d02018-07-26 10:23:02 -0700158 result = _pend_curr(&stack->lock, key, &stack->wait_q, timeout);
Flavio Ceolindfbe0322018-11-01 20:50:25 -0700159 if (result == -EAGAIN) {
Flavio Ceolin8f488ff2018-09-13 11:43:59 -0700160 return -EAGAIN;
Flavio Ceolindfbe0322018-11-01 20:50:25 -0700161 }
Benjamin Walsh456c6da2016-09-02 18:55:39 -0400162
Flavio Ceolin8f488ff2018-09-13 11:43:59 -0700163 *data = (u32_t)_current->base.swap_data;
164 return 0;
Benjamin Walsh456c6da2016-09-02 18:55:39 -0400165}
Andrew Boiee8734462017-09-29 16:42:07 -0700166
167#ifdef CONFIG_USERSPACE
Andrew Boie8345e5e2018-05-04 15:57:57 -0700168Z_SYSCALL_HANDLER(k_stack_pop, stack, data, timeout)
Andrew Boiee8734462017-09-29 16:42:07 -0700169{
Andrew Boie8345e5e2018-05-04 15:57:57 -0700170 Z_OOPS(Z_SYSCALL_OBJ(stack, K_OBJ_STACK));
171 Z_OOPS(Z_SYSCALL_MEMORY_WRITE(data, sizeof(u32_t)));
Andrew Boiee8734462017-09-29 16:42:07 -0700172
173 return _impl_k_stack_pop((struct k_stack *)stack, (u32_t *)data,
174 timeout);
Andrew Boiee8734462017-09-29 16:42:07 -0700175}
176#endif