blob: 4a2269305d6bf0cd52e810a8856f98444b7b2f9c [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>
Allan Stephense7d2cc22016-10-19 16:10:46 -050021
22extern struct k_stack _k_stack_list_start[];
23extern struct k_stack _k_stack_list_end[];
24
Anas Nashif2f203c22016-12-18 06:57:45 -050025#ifdef CONFIG_OBJECT_TRACING
Allan Stephense7d2cc22016-10-19 16:10:46 -050026
Maciek Borzecki059544d2017-05-18 12:16:45 +020027struct k_stack *_trace_list_k_stack;
28
Allan Stephense7d2cc22016-10-19 16:10:46 -050029/*
30 * Complete initialization of statically defined stacks.
31 */
32static int init_stack_module(struct device *dev)
33{
34 ARG_UNUSED(dev);
35
36 struct k_stack *stack;
37
38 for (stack = _k_stack_list_start; stack < _k_stack_list_end; stack++) {
39 SYS_TRACING_OBJ_INIT(k_stack, stack);
40 }
41 return 0;
42}
43
Andrew Boie0b474ee2016-11-08 11:06:55 -080044SYS_INIT(init_stack_module, PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_OBJECTS);
Allan Stephense7d2cc22016-10-19 16:10:46 -050045
Anas Nashif2f203c22016-12-18 06:57:45 -050046#endif /* CONFIG_OBJECT_TRACING */
Benjamin Walsh456c6da2016-09-02 18:55:39 -040047
Andrew Boief3bee952018-05-02 17:44:39 -070048void k_stack_init(struct k_stack *stack, u32_t *buffer,
Adithya Baglody28080d32018-10-15 11:48:51 +053049 u32_t num_entries)
Benjamin Walsh456c6da2016-09-02 18:55:39 -040050{
Andy Rossccf3bf72018-05-10 11:10:34 -070051 _waitq_init(&stack->wait_q);
Adithya Baglody28080d32018-10-15 11:48:51 +053052 stack->base = buffer;
53 stack->next = buffer;
Benjamin Walsh456c6da2016-09-02 18:55:39 -040054 stack->top = stack->base + num_entries;
55
56 SYS_TRACING_OBJ_INIT(k_stack, stack);
Andrew Boie945af952017-08-22 13:15:23 -070057 _k_object_init(stack);
Benjamin Walsh456c6da2016-09-02 18:55:39 -040058}
59
Adithya Baglody28080d32018-10-15 11:48:51 +053060s32_t _impl_k_stack_alloc_init(struct k_stack *stack, u32_t num_entries)
Andrew Boiee8734462017-09-29 16:42:07 -070061{
Andrew Boief3bee952018-05-02 17:44:39 -070062 void *buffer;
Adithya Baglody28080d32018-10-15 11:48:51 +053063 s32_t ret;
Andrew Boiee8734462017-09-29 16:42:07 -070064
Andrew Boief3bee952018-05-02 17:44:39 -070065 buffer = z_thread_malloc(num_entries);
Flavio Ceolinea716bf2018-09-20 16:30:45 -070066 if (buffer != NULL) {
Andrew Boief3bee952018-05-02 17:44:39 -070067 k_stack_init(stack, buffer, num_entries);
68 stack->flags = K_STACK_FLAG_ALLOC;
Adithya Baglody28080d32018-10-15 11:48:51 +053069 ret = (s32_t)0;
Andrew Boief3bee952018-05-02 17:44:39 -070070 } else {
71 ret = -ENOMEM;
72 }
73
74 return ret;
75}
76
77#ifdef CONFIG_USERSPACE
Andrew Boie8345e5e2018-05-04 15:57:57 -070078Z_SYSCALL_HANDLER(k_stack_alloc_init, stack, num_entries)
Andrew Boief3bee952018-05-02 17:44:39 -070079{
Andrew Boie8345e5e2018-05-04 15:57:57 -070080 Z_OOPS(Z_SYSCALL_OBJ_NEVER_INIT(stack, K_OBJ_STACK));
81 Z_OOPS(Z_SYSCALL_VERIFY(num_entries > 0));
Andrew Boief3bee952018-05-02 17:44:39 -070082
Flavio Ceolin585d90f2018-09-12 23:03:05 -070083 return _impl_k_stack_alloc_init((struct k_stack *)stack, num_entries);
Andrew Boiee8734462017-09-29 16:42:07 -070084}
85#endif
86
Andrew Boief3bee952018-05-02 17:44:39 -070087void k_stack_cleanup(struct k_stack *stack)
88{
Adithya Baglody28080d32018-10-15 11:48:51 +053089 __ASSERT_NO_MSG(_waitq_head(&stack->wait_q) == NULL);
Andrew Boief3bee952018-05-02 17:44:39 -070090
Adithya Baglody28080d32018-10-15 11:48:51 +053091 if ((stack->flags & K_STACK_FLAG_ALLOC) != (u8_t)0) {
Andrew Boief3bee952018-05-02 17:44:39 -070092 k_free(stack->base);
93 stack->base = NULL;
94 stack->flags &= ~K_STACK_FLAG_ALLOC;
95 }
96}
97
Andrew Boiee8734462017-09-29 16:42:07 -070098void _impl_k_stack_push(struct k_stack *stack, u32_t data)
Benjamin Walsh456c6da2016-09-02 18:55:39 -040099{
100 struct k_thread *first_pending_thread;
Adithya Baglody28080d32018-10-15 11:48:51 +0530101 u32_t key;
Benjamin Walsh456c6da2016-09-02 18:55:39 -0400102
103 __ASSERT(stack->next != stack->top, "stack is full");
104
105 key = irq_lock();
106
107 first_pending_thread = _unpend_first_thread(&stack->wait_q);
108
Flavio Ceolinea716bf2018-09-20 16:30:45 -0700109 if (first_pending_thread != NULL) {
Benjamin Walsh456c6da2016-09-02 18:55:39 -0400110 _ready_thread(first_pending_thread);
111
112 _set_thread_return_value_with_data(first_pending_thread,
113 0, (void *)data);
Andy Ross22642cf2018-04-02 18:24:58 -0700114 _reschedule(key);
Andy Ross8606fab2018-03-26 10:54:40 -0700115 return;
Benjamin Walsh456c6da2016-09-02 18:55:39 -0400116 } else {
117 *(stack->next) = data;
118 stack->next++;
Andy Ross8606fab2018-03-26 10:54:40 -0700119 irq_unlock(key);
Benjamin Walsh456c6da2016-09-02 18:55:39 -0400120 }
121
Benjamin Walsh456c6da2016-09-02 18:55:39 -0400122}
123
Andrew Boiee8734462017-09-29 16:42:07 -0700124#ifdef CONFIG_USERSPACE
Andrew Boie8345e5e2018-05-04 15:57:57 -0700125Z_SYSCALL_HANDLER(k_stack_push, stack_p, data)
Andrew Boiee8734462017-09-29 16:42:07 -0700126{
127 struct k_stack *stack = (struct k_stack *)stack_p;
Andrew Boiee8734462017-09-29 16:42:07 -0700128
Andrew Boie8345e5e2018-05-04 15:57:57 -0700129 Z_OOPS(Z_SYSCALL_OBJ(stack, K_OBJ_STACK));
130 Z_OOPS(Z_SYSCALL_VERIFY_MSG(stack->next != stack->top,
131 "stack is full"));
Andrew Boiee8734462017-09-29 16:42:07 -0700132
133 _impl_k_stack_push(stack, data);
134 return 0;
135}
136#endif
137
138int _impl_k_stack_pop(struct k_stack *stack, u32_t *data, s32_t timeout)
Benjamin Walsh456c6da2016-09-02 18:55:39 -0400139{
Adithya Baglody28080d32018-10-15 11:48:51 +0530140 u32_t key;
Benjamin Walsh456c6da2016-09-02 18:55:39 -0400141 int result;
142
143 key = irq_lock();
144
145 if (likely(stack->next > stack->base)) {
146 stack->next--;
147 *data = *(stack->next);
148 irq_unlock(key);
149 return 0;
150 }
151
152 if (timeout == K_NO_WAIT) {
153 irq_unlock(key);
154 return -EBUSY;
155 }
156
Andy Rosse0a572b2018-03-26 11:58:10 -0700157 result = _pend_current_thread(key, &stack->wait_q, timeout);
Flavio Ceolindfbe0322018-11-01 20:50:25 -0700158 if (result == -EAGAIN) {
Flavio Ceolin8f488ff2018-09-13 11:43:59 -0700159 return -EAGAIN;
Flavio Ceolindfbe0322018-11-01 20:50:25 -0700160 }
Benjamin Walsh456c6da2016-09-02 18:55:39 -0400161
Flavio Ceolin8f488ff2018-09-13 11:43:59 -0700162 *data = (u32_t)_current->base.swap_data;
163 return 0;
Benjamin Walsh456c6da2016-09-02 18:55:39 -0400164}
Andrew Boiee8734462017-09-29 16:42:07 -0700165
166#ifdef CONFIG_USERSPACE
Andrew Boie8345e5e2018-05-04 15:57:57 -0700167Z_SYSCALL_HANDLER(k_stack_pop, stack, data, timeout)
Andrew Boiee8734462017-09-29 16:42:07 -0700168{
Andrew Boie8345e5e2018-05-04 15:57:57 -0700169 Z_OOPS(Z_SYSCALL_OBJ(stack, K_OBJ_STACK));
170 Z_OOPS(Z_SYSCALL_MEMORY_WRITE(data, sizeof(u32_t)));
Andrew Boiee8734462017-09-29 16:42:07 -0700171
172 return _impl_k_stack_pop((struct k_stack *)stack, (u32_t *)data,
173 timeout);
Andrew Boiee8734462017-09-29 16:42:07 -0700174}
175#endif