blob: 0c461095c6b0d57b7fa090f14f9f01340d0e9baa [file] [log] [blame]
Benjamin Walsh456c6da2016-09-02 18:55:39 -04001/*
2 * Copyright (c) 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 * @file
9 * @brief Message queues.
10 */
11
12
Gerard Marull-Paretascffefc82022-05-06 11:04:23 +020013#include <zephyr/kernel.h>
14#include <zephyr/kernel_structs.h>
Anas Nashif4d994af2021-04-18 23:24:40 -040015
Gerard Marull-Paretascffefc82022-05-06 11:04:23 +020016#include <zephyr/toolchain.h>
17#include <zephyr/linker/sections.h>
Benjamin Walsh456c6da2016-09-02 18:55:39 -040018#include <string.h>
Stephanos Ioannidis2d746042019-10-25 00:08:21 +090019#include <ksched.h>
Anas Nashif8634c3b2023-08-29 17:03:12 +000020#include <wait_q.h>
Gerard Marull-Paretascffefc82022-05-06 11:04:23 +020021#include <zephyr/sys/dlist.h>
22#include <zephyr/sys/math_extras.h>
23#include <zephyr/init.h>
Anas Nashif4e396172023-09-26 22:46:01 +000024#include <zephyr/internal/syscall_handler.h>
Andy Ross4f911e12018-09-05 10:13:38 -070025#include <kernel_internal.h>
Gerard Marull-Paretascffefc82022-05-06 11:04:23 +020026#include <zephyr/sys/check.h>
Allan Stephense7d2cc22016-10-19 16:10:46 -050027
Peter Mitsis6df8efe2023-05-11 14:06:46 -040028#ifdef CONFIG_OBJ_CORE_MSGQ
29static struct k_obj_type obj_type_msgq;
Simon Heinbcd1d192024-03-08 12:00:10 +010030#endif /* CONFIG_OBJ_CORE_MSGQ */
Peter Mitsis6df8efe2023-05-11 14:06:46 -040031
Nick Gravesb445f132021-04-12 12:35:18 -070032#ifdef CONFIG_POLL
33static inline void handle_poll_events(struct k_msgq *msgq, uint32_t state)
34{
35 z_handle_obj_poll_events(&msgq->poll_events, state);
36}
37#endif /* CONFIG_POLL */
38
Anas Nashif7bde81f2019-06-19 07:30:50 -040039void k_msgq_init(struct k_msgq *msgq, char *buffer, size_t msg_size,
Kumar Galaa1b77fd2020-05-27 11:26:57 -050040 uint32_t max_msgs)
Benjamin Walsh456c6da2016-09-02 18:55:39 -040041{
Anas Nashif7bde81f2019-06-19 07:30:50 -040042 msgq->msg_size = msg_size;
43 msgq->max_msgs = max_msgs;
44 msgq->buffer_start = buffer;
45 msgq->buffer_end = buffer + (max_msgs * msg_size);
46 msgq->read_ptr = buffer;
47 msgq->write_ptr = buffer;
48 msgq->used_msgs = 0;
49 msgq->flags = 0;
50 z_waitq_init(&msgq->wait_q);
51 msgq->lock = (struct k_spinlock) {};
Nick Gravesb445f132021-04-12 12:35:18 -070052#ifdef CONFIG_POLL
53 sys_dlist_init(&msgq->poll_events);
54#endif /* CONFIG_POLL */
Torbjörn Leksell9ab447b2021-03-26 12:39:53 +010055
Peter Mitsis6df8efe2023-05-11 14:06:46 -040056#ifdef CONFIG_OBJ_CORE_MSGQ
57 k_obj_core_init_and_link(K_OBJ_CORE(msgq), &obj_type_msgq);
Simon Heinbcd1d192024-03-08 12:00:10 +010058#endif /* CONFIG_OBJ_CORE_MSGQ */
Peter Mitsis6df8efe2023-05-11 14:06:46 -040059
Torbjörn Leksell9ab447b2021-03-26 12:39:53 +010060 SYS_PORT_TRACING_OBJ_INIT(k_msgq, msgq);
61
Anas Nashifc91cad72023-09-26 21:32:13 +000062 k_object_init(msgq);
Benjamin Walsh456c6da2016-09-02 18:55:39 -040063}
64
Anas Nashif7bde81f2019-06-19 07:30:50 -040065int z_impl_k_msgq_alloc_init(struct k_msgq *msgq, size_t msg_size,
Kumar Galaa1b77fd2020-05-27 11:26:57 -050066 uint32_t max_msgs)
Andrew Boie82edb6e2017-10-02 10:53:06 -070067{
Andrew Boie0fe789f2018-04-12 18:35:56 -070068 void *buffer;
69 int ret;
70 size_t total_size;
Andrew Boie82edb6e2017-10-02 10:53:06 -070071
Torbjörn Leksell9ab447b2021-03-26 12:39:53 +010072 SYS_PORT_TRACING_OBJ_FUNC_ENTER(k_msgq, alloc_init, msgq);
73
Jakob Olesenc8708d92019-05-07 10:17:35 -070074 if (size_mul_overflow(msg_size, max_msgs, &total_size)) {
Andrew Boie0fe789f2018-04-12 18:35:56 -070075 ret = -EINVAL;
76 } else {
77 buffer = z_thread_malloc(total_size);
Flavio Ceolinea716bf2018-09-20 16:30:45 -070078 if (buffer != NULL) {
Anas Nashif7bde81f2019-06-19 07:30:50 -040079 k_msgq_init(msgq, buffer, msg_size, max_msgs);
80 msgq->flags = K_MSGQ_FLAG_ALLOC;
Andrew Boie0fe789f2018-04-12 18:35:56 -070081 ret = 0;
82 } else {
83 ret = -ENOMEM;
84 }
85 }
86
Torbjörn Leksell9ab447b2021-03-26 12:39:53 +010087 SYS_PORT_TRACING_OBJ_FUNC_EXIT(k_msgq, alloc_init, msgq, ret);
88
Andrew Boie0fe789f2018-04-12 18:35:56 -070089 return ret;
90}
91
92#ifdef CONFIG_USERSPACE
Anas Nashif25c87db2021-03-29 10:54:23 -040093int z_vrfy_k_msgq_alloc_init(struct k_msgq *msgq, size_t msg_size,
Kumar Galaa1b77fd2020-05-27 11:26:57 -050094 uint32_t max_msgs)
Andrew Boie0fe789f2018-04-12 18:35:56 -070095{
Anas Nashifa08bfeb2023-09-27 11:20:28 +000096 K_OOPS(K_SYSCALL_OBJ_NEVER_INIT(msgq, K_OBJ_MSGQ));
Andrew Boie0fe789f2018-04-12 18:35:56 -070097
Anas Nashif25c87db2021-03-29 10:54:23 -040098 return z_impl_k_msgq_alloc_init(msgq, msg_size, max_msgs);
Andrew Boie82edb6e2017-10-02 10:53:06 -070099}
Yong Cong Sinbbe5e1e2024-01-24 17:35:04 +0800100#include <zephyr/syscalls/k_msgq_alloc_init_mrsh.c>
Simon Heinbcd1d192024-03-08 12:00:10 +0100101#endif /* CONFIG_USERSPACE */
Andrew Boie82edb6e2017-10-02 10:53:06 -0700102
Anas Nashif11b93652019-06-16 08:43:48 -0400103int k_msgq_cleanup(struct k_msgq *msgq)
Andrew Boie0fe789f2018-04-12 18:35:56 -0700104{
Torbjörn Leksell9ab447b2021-03-26 12:39:53 +0100105 SYS_PORT_TRACING_OBJ_FUNC_ENTER(k_msgq, cleanup, msgq);
106
Anas Nashif11b93652019-06-16 08:43:48 -0400107 CHECKIF(z_waitq_head(&msgq->wait_q) != NULL) {
Torbjörn Leksell9ab447b2021-03-26 12:39:53 +0100108 SYS_PORT_TRACING_OBJ_FUNC_EXIT(k_msgq, cleanup, msgq, -EBUSY);
109
Anas Nashif11b93652019-06-16 08:43:48 -0400110 return -EBUSY;
111 }
Andrew Boie0fe789f2018-04-12 18:35:56 -0700112
Anas Nashifbbbc38b2021-03-29 10:03:49 -0400113 if ((msgq->flags & K_MSGQ_FLAG_ALLOC) != 0U) {
Anas Nashif7bde81f2019-06-19 07:30:50 -0400114 k_free(msgq->buffer_start);
115 msgq->flags &= ~K_MSGQ_FLAG_ALLOC;
Andrew Boie0fe789f2018-04-12 18:35:56 -0700116 }
Torbjörn Leksell9ab447b2021-03-26 12:39:53 +0100117
118 SYS_PORT_TRACING_OBJ_FUNC_EXIT(k_msgq, cleanup, msgq, 0);
119
Anas Nashif11b93652019-06-16 08:43:48 -0400120 return 0;
Andrew Boie0fe789f2018-04-12 18:35:56 -0700121}
122
123
Lauren Murphyf29a2d12020-09-16 21:13:40 -0500124int z_impl_k_msgq_put(struct k_msgq *msgq, const void *data, k_timeout_t timeout)
Benjamin Walsh456c6da2016-09-02 18:55:39 -0400125{
Andy Ross78327382020-03-05 15:18:14 -0800126 __ASSERT(!arch_is_in_isr() || K_TIMEOUT_EQ(timeout, K_NO_WAIT), "");
Benjamin Walsh8215ce12016-11-09 19:45:19 -0500127
Benjamin Walshb7ef0cb2016-10-05 17:32:01 -0400128 struct k_thread *pending_thread;
Anas Nashif7bde81f2019-06-19 07:30:50 -0400129 k_spinlock_key_t key;
Benjamin Walsh456c6da2016-09-02 18:55:39 -0400130 int result;
131
Anas Nashif7bde81f2019-06-19 07:30:50 -0400132 key = k_spin_lock(&msgq->lock);
133
Torbjörn Leksell9ab447b2021-03-26 12:39:53 +0100134 SYS_PORT_TRACING_OBJ_FUNC_ENTER(k_msgq, put, msgq, timeout);
135
Anas Nashif7bde81f2019-06-19 07:30:50 -0400136 if (msgq->used_msgs < msgq->max_msgs) {
Benjamin Walsh456c6da2016-09-02 18:55:39 -0400137 /* message queue isn't full */
Anas Nashif7bde81f2019-06-19 07:30:50 -0400138 pending_thread = z_unpend_first_thread(&msgq->wait_q);
Flavio Ceolinea716bf2018-09-20 16:30:45 -0700139 if (pending_thread != NULL) {
Torbjörn Leksell9ab447b2021-03-26 12:39:53 +0100140 SYS_PORT_TRACING_OBJ_FUNC_EXIT(k_msgq, put, msgq, timeout, 0);
141
Benjamin Walsh456c6da2016-09-02 18:55:39 -0400142 /* give message to waiting thread */
Flavio Ceolin66994232018-08-13 15:17:04 -0700143 (void)memcpy(pending_thread->base.swap_data, data,
Anas Nashif7bde81f2019-06-19 07:30:50 -0400144 msgq->msg_size);
Benjamin Walsh456c6da2016-09-02 18:55:39 -0400145 /* wake up waiting thread */
Andrew Boie4f77c2a2019-11-07 12:43:29 -0800146 arch_thread_return_value_set(pending_thread, 0);
Patrik Flykt4344e272019-03-08 14:19:05 -0700147 z_ready_thread(pending_thread);
Anas Nashif7bde81f2019-06-19 07:30:50 -0400148 z_reschedule(&msgq->lock, key);
Andy Ross8606fab2018-03-26 10:54:40 -0700149 return 0;
Benjamin Walsh456c6da2016-09-02 18:55:39 -0400150 } else {
151 /* put message in queue */
Armin Brauns0bc342f2023-05-08 11:12:06 +0000152 __ASSERT_NO_MSG(msgq->write_ptr >= msgq->buffer_start &&
153 msgq->write_ptr < msgq->buffer_end);
Hess Nathanc30a9c4c2024-04-29 14:49:11 +0200154 (void)memcpy(msgq->write_ptr, (char *)data, msgq->msg_size);
Anas Nashif7bde81f2019-06-19 07:30:50 -0400155 msgq->write_ptr += msgq->msg_size;
156 if (msgq->write_ptr == msgq->buffer_end) {
157 msgq->write_ptr = msgq->buffer_start;
Benjamin Walsh456c6da2016-09-02 18:55:39 -0400158 }
Anas Nashif7bde81f2019-06-19 07:30:50 -0400159 msgq->used_msgs++;
Nick Gravesb445f132021-04-12 12:35:18 -0700160#ifdef CONFIG_POLL
161 handle_poll_events(msgq, K_POLL_STATE_MSGQ_DATA_AVAILABLE);
162#endif /* CONFIG_POLL */
Benjamin Walsh456c6da2016-09-02 18:55:39 -0400163 }
164 result = 0;
Andy Ross78327382020-03-05 15:18:14 -0800165 } else if (K_TIMEOUT_EQ(timeout, K_NO_WAIT)) {
Benjamin Walsh456c6da2016-09-02 18:55:39 -0400166 /* don't wait for message space to become available */
167 result = -ENOMSG;
168 } else {
Torbjörn Leksell9ab447b2021-03-26 12:39:53 +0100169 SYS_PORT_TRACING_OBJ_FUNC_BLOCKING(k_msgq, put, msgq, timeout);
170
Benjamin Walsh456c6da2016-09-02 18:55:39 -0400171 /* wait for put message success, failure, or timeout */
Lauren Murphyf29a2d12020-09-16 21:13:40 -0500172 _current->base.swap_data = (void *) data;
Torbjörn Leksell9ab447b2021-03-26 12:39:53 +0100173
174 result = z_pend_curr(&msgq->lock, key, &msgq->wait_q, timeout);
175 SYS_PORT_TRACING_OBJ_FUNC_EXIT(k_msgq, put, msgq, timeout, result);
176 return result;
Benjamin Walsh456c6da2016-09-02 18:55:39 -0400177 }
178
Torbjörn Leksell9ab447b2021-03-26 12:39:53 +0100179 SYS_PORT_TRACING_OBJ_FUNC_EXIT(k_msgq, put, msgq, timeout, result);
180
Anas Nashif7bde81f2019-06-19 07:30:50 -0400181 k_spin_unlock(&msgq->lock, key);
Benjamin Walsh456c6da2016-09-02 18:55:39 -0400182
183 return result;
184}
185
Andrew Boie82edb6e2017-10-02 10:53:06 -0700186#ifdef CONFIG_USERSPACE
Anas Nashif25c87db2021-03-29 10:54:23 -0400187static inline int z_vrfy_k_msgq_put(struct k_msgq *msgq, const void *data,
Andy Ross78327382020-03-05 15:18:14 -0800188 k_timeout_t timeout)
Andrew Boie82edb6e2017-10-02 10:53:06 -0700189{
Anas Nashifa08bfeb2023-09-27 11:20:28 +0000190 K_OOPS(K_SYSCALL_OBJ(msgq, K_OBJ_MSGQ));
191 K_OOPS(K_SYSCALL_MEMORY_READ(data, msgq->msg_size));
Andrew Boie82edb6e2017-10-02 10:53:06 -0700192
Anas Nashif25c87db2021-03-29 10:54:23 -0400193 return z_impl_k_msgq_put(msgq, data, timeout);
Andrew Boie82edb6e2017-10-02 10:53:06 -0700194}
Yong Cong Sinbbe5e1e2024-01-24 17:35:04 +0800195#include <zephyr/syscalls/k_msgq_put_mrsh.c>
Simon Heinbcd1d192024-03-08 12:00:10 +0100196#endif /* CONFIG_USERSPACE */
Andrew Boie82edb6e2017-10-02 10:53:06 -0700197
Anas Nashif7bde81f2019-06-19 07:30:50 -0400198void z_impl_k_msgq_get_attrs(struct k_msgq *msgq, struct k_msgq_attrs *attrs)
Youvedeep Singh188c1ab2018-03-19 20:02:40 +0530199{
Anas Nashif7bde81f2019-06-19 07:30:50 -0400200 attrs->msg_size = msgq->msg_size;
201 attrs->max_msgs = msgq->max_msgs;
202 attrs->used_msgs = msgq->used_msgs;
Youvedeep Singh188c1ab2018-03-19 20:02:40 +0530203}
204
205#ifdef CONFIG_USERSPACE
Anas Nashif25c87db2021-03-29 10:54:23 -0400206static inline void z_vrfy_k_msgq_get_attrs(struct k_msgq *msgq,
Andy Ross643701a2019-08-13 12:58:38 -0700207 struct k_msgq_attrs *attrs)
Youvedeep Singh188c1ab2018-03-19 20:02:40 +0530208{
Anas Nashifa08bfeb2023-09-27 11:20:28 +0000209 K_OOPS(K_SYSCALL_OBJ(msgq, K_OBJ_MSGQ));
210 K_OOPS(K_SYSCALL_MEMORY_WRITE(attrs, sizeof(struct k_msgq_attrs)));
Anas Nashif25c87db2021-03-29 10:54:23 -0400211 z_impl_k_msgq_get_attrs(msgq, attrs);
Youvedeep Singh188c1ab2018-03-19 20:02:40 +0530212}
Yong Cong Sinbbe5e1e2024-01-24 17:35:04 +0800213#include <zephyr/syscalls/k_msgq_get_attrs_mrsh.c>
Simon Heinbcd1d192024-03-08 12:00:10 +0100214#endif /* CONFIG_USERSPACE */
Youvedeep Singh188c1ab2018-03-19 20:02:40 +0530215
Andy Ross78327382020-03-05 15:18:14 -0800216int z_impl_k_msgq_get(struct k_msgq *msgq, void *data, k_timeout_t timeout)
Benjamin Walsh456c6da2016-09-02 18:55:39 -0400217{
Andy Ross78327382020-03-05 15:18:14 -0800218 __ASSERT(!arch_is_in_isr() || K_TIMEOUT_EQ(timeout, K_NO_WAIT), "");
Benjamin Walsh8215ce12016-11-09 19:45:19 -0500219
Anas Nashif7bde81f2019-06-19 07:30:50 -0400220 k_spinlock_key_t key;
Benjamin Walshb7ef0cb2016-10-05 17:32:01 -0400221 struct k_thread *pending_thread;
Benjamin Walsh456c6da2016-09-02 18:55:39 -0400222 int result;
223
Anas Nashif7bde81f2019-06-19 07:30:50 -0400224 key = k_spin_lock(&msgq->lock);
225
Torbjörn Leksell9ab447b2021-03-26 12:39:53 +0100226 SYS_PORT_TRACING_OBJ_FUNC_ENTER(k_msgq, get, msgq, timeout);
227
Anas Nashifbbbc38b2021-03-29 10:03:49 -0400228 if (msgq->used_msgs > 0U) {
Benjamin Walsh456c6da2016-09-02 18:55:39 -0400229 /* take first available message from queue */
Hess Nathanc30a9c4c2024-04-29 14:49:11 +0200230 (void)memcpy((char *)data, msgq->read_ptr, msgq->msg_size);
Anas Nashif7bde81f2019-06-19 07:30:50 -0400231 msgq->read_ptr += msgq->msg_size;
232 if (msgq->read_ptr == msgq->buffer_end) {
233 msgq->read_ptr = msgq->buffer_start;
Benjamin Walsh456c6da2016-09-02 18:55:39 -0400234 }
Anas Nashif7bde81f2019-06-19 07:30:50 -0400235 msgq->used_msgs--;
Benjamin Walsh456c6da2016-09-02 18:55:39 -0400236
237 /* handle first thread waiting to write (if any) */
Anas Nashif7bde81f2019-06-19 07:30:50 -0400238 pending_thread = z_unpend_first_thread(&msgq->wait_q);
Flavio Ceolin4218d5f2018-09-17 09:39:51 -0700239 if (pending_thread != NULL) {
Torbjörn Leksell9ab447b2021-03-26 12:39:53 +0100240 SYS_PORT_TRACING_OBJ_FUNC_BLOCKING(k_msgq, get, msgq, timeout);
241
Benjamin Walsh456c6da2016-09-02 18:55:39 -0400242 /* add thread's message to queue */
Armin Brauns0bc342f2023-05-08 11:12:06 +0000243 __ASSERT_NO_MSG(msgq->write_ptr >= msgq->buffer_start &&
244 msgq->write_ptr < msgq->buffer_end);
Hess Nathanc30a9c4c2024-04-29 14:49:11 +0200245 (void)memcpy(msgq->write_ptr, (char *)pending_thread->base.swap_data,
Anas Nashif7bde81f2019-06-19 07:30:50 -0400246 msgq->msg_size);
247 msgq->write_ptr += msgq->msg_size;
248 if (msgq->write_ptr == msgq->buffer_end) {
249 msgq->write_ptr = msgq->buffer_start;
Benjamin Walsh456c6da2016-09-02 18:55:39 -0400250 }
Anas Nashif7bde81f2019-06-19 07:30:50 -0400251 msgq->used_msgs++;
Benjamin Walsh456c6da2016-09-02 18:55:39 -0400252
253 /* wake up waiting thread */
Andrew Boie4f77c2a2019-11-07 12:43:29 -0800254 arch_thread_return_value_set(pending_thread, 0);
Patrik Flykt4344e272019-03-08 14:19:05 -0700255 z_ready_thread(pending_thread);
Anas Nashif7bde81f2019-06-19 07:30:50 -0400256 z_reschedule(&msgq->lock, key);
Torbjörn Leksell9ab447b2021-03-26 12:39:53 +0100257
258 SYS_PORT_TRACING_OBJ_FUNC_EXIT(k_msgq, get, msgq, timeout, 0);
259
Andy Ross8606fab2018-03-26 10:54:40 -0700260 return 0;
Benjamin Walsh456c6da2016-09-02 18:55:39 -0400261 }
262 result = 0;
Andy Ross78327382020-03-05 15:18:14 -0800263 } else if (K_TIMEOUT_EQ(timeout, K_NO_WAIT)) {
Benjamin Walsh456c6da2016-09-02 18:55:39 -0400264 /* don't wait for a message to become available */
265 result = -ENOMSG;
266 } else {
Torbjörn Leksell9ab447b2021-03-26 12:39:53 +0100267 SYS_PORT_TRACING_OBJ_FUNC_BLOCKING(k_msgq, get, msgq, timeout);
268
Benjamin Walsh456c6da2016-09-02 18:55:39 -0400269 /* wait for get message success or timeout */
Benjamin Walshf6ca7de2016-11-08 10:36:50 -0500270 _current->base.swap_data = data;
Torbjörn Leksell9ab447b2021-03-26 12:39:53 +0100271
272 result = z_pend_curr(&msgq->lock, key, &msgq->wait_q, timeout);
273 SYS_PORT_TRACING_OBJ_FUNC_EXIT(k_msgq, get, msgq, timeout, result);
274 return result;
Benjamin Walsh456c6da2016-09-02 18:55:39 -0400275 }
276
Torbjörn Leksell9ab447b2021-03-26 12:39:53 +0100277 SYS_PORT_TRACING_OBJ_FUNC_EXIT(k_msgq, get, msgq, timeout, result);
278
Anas Nashif7bde81f2019-06-19 07:30:50 -0400279 k_spin_unlock(&msgq->lock, key);
Benjamin Walsh456c6da2016-09-02 18:55:39 -0400280
281 return result;
282}
283
Andrew Boie82edb6e2017-10-02 10:53:06 -0700284#ifdef CONFIG_USERSPACE
Anas Nashif25c87db2021-03-29 10:54:23 -0400285static inline int z_vrfy_k_msgq_get(struct k_msgq *msgq, void *data,
Andy Ross78327382020-03-05 15:18:14 -0800286 k_timeout_t timeout)
Andrew Boie82edb6e2017-10-02 10:53:06 -0700287{
Anas Nashifa08bfeb2023-09-27 11:20:28 +0000288 K_OOPS(K_SYSCALL_OBJ(msgq, K_OBJ_MSGQ));
289 K_OOPS(K_SYSCALL_MEMORY_WRITE(data, msgq->msg_size));
Andrew Boie82edb6e2017-10-02 10:53:06 -0700290
Anas Nashif25c87db2021-03-29 10:54:23 -0400291 return z_impl_k_msgq_get(msgq, data, timeout);
Andrew Boie82edb6e2017-10-02 10:53:06 -0700292}
Yong Cong Sinbbe5e1e2024-01-24 17:35:04 +0800293#include <zephyr/syscalls/k_msgq_get_mrsh.c>
Simon Heinbcd1d192024-03-08 12:00:10 +0100294#endif /* CONFIG_USERSPACE */
Andrew Boie82edb6e2017-10-02 10:53:06 -0700295
Anas Nashif7bde81f2019-06-19 07:30:50 -0400296int z_impl_k_msgq_peek(struct k_msgq *msgq, void *data)
Sathish Kuttana8aa2352018-11-09 21:04:36 -0800297{
Anas Nashif7bde81f2019-06-19 07:30:50 -0400298 k_spinlock_key_t key;
Sathish Kuttana8aa2352018-11-09 21:04:36 -0800299 int result;
300
Anas Nashif7bde81f2019-06-19 07:30:50 -0400301 key = k_spin_lock(&msgq->lock);
302
Anas Nashifbbbc38b2021-03-29 10:03:49 -0400303 if (msgq->used_msgs > 0U) {
Sathish Kuttana8aa2352018-11-09 21:04:36 -0800304 /* take first available message from queue */
Hess Nathanc30a9c4c2024-04-29 14:49:11 +0200305 (void)memcpy((char *)data, msgq->read_ptr, msgq->msg_size);
Sathish Kuttana8aa2352018-11-09 21:04:36 -0800306 result = 0;
307 } else {
308 /* don't wait for a message to become available */
309 result = -ENOMSG;
310 }
311
Torbjörn Leksell9ab447b2021-03-26 12:39:53 +0100312 SYS_PORT_TRACING_OBJ_FUNC(k_msgq, peek, msgq, result);
313
Anas Nashif7bde81f2019-06-19 07:30:50 -0400314 k_spin_unlock(&msgq->lock, key);
Sathish Kuttana8aa2352018-11-09 21:04:36 -0800315
316 return result;
317}
318
319#ifdef CONFIG_USERSPACE
Anas Nashif25c87db2021-03-29 10:54:23 -0400320static inline int z_vrfy_k_msgq_peek(struct k_msgq *msgq, void *data)
Sathish Kuttana8aa2352018-11-09 21:04:36 -0800321{
Anas Nashifa08bfeb2023-09-27 11:20:28 +0000322 K_OOPS(K_SYSCALL_OBJ(msgq, K_OBJ_MSGQ));
323 K_OOPS(K_SYSCALL_MEMORY_WRITE(data, msgq->msg_size));
Sathish Kuttana8aa2352018-11-09 21:04:36 -0800324
Anas Nashif25c87db2021-03-29 10:54:23 -0400325 return z_impl_k_msgq_peek(msgq, data);
Sathish Kuttana8aa2352018-11-09 21:04:36 -0800326}
Yong Cong Sinbbe5e1e2024-01-24 17:35:04 +0800327#include <zephyr/syscalls/k_msgq_peek_mrsh.c>
Simon Heinbcd1d192024-03-08 12:00:10 +0100328#endif /* CONFIG_USERSPACE */
Sathish Kuttana8aa2352018-11-09 21:04:36 -0800329
romain pelletant14bcc852022-12-28 13:06:16 +0100330int z_impl_k_msgq_peek_at(struct k_msgq *msgq, void *data, uint32_t idx)
331{
332 k_spinlock_key_t key;
333 int result;
334 uint32_t bytes_to_end;
335 uint32_t byte_offset;
336 char *start_addr;
337
338 key = k_spin_lock(&msgq->lock);
339
340 if (msgq->used_msgs > idx) {
341 bytes_to_end = (msgq->buffer_end - msgq->read_ptr);
342 byte_offset = idx * msgq->msg_size;
343 start_addr = msgq->read_ptr;
344 /* check item available in start/end of ring buffer */
345 if (bytes_to_end <= byte_offset) {
346 /* Tweak the values in case */
347 byte_offset -= bytes_to_end;
348 /* wrap-around is required */
349 start_addr = msgq->buffer_start;
350 }
351 (void)memcpy(data, start_addr + byte_offset, msgq->msg_size);
352 result = 0;
353 } else {
354 /* don't wait for a message to become available */
355 result = -ENOMSG;
356 }
357
358 SYS_PORT_TRACING_OBJ_FUNC(k_msgq, peek, msgq, result);
359
360 k_spin_unlock(&msgq->lock, key);
361
362 return result;
363}
364
365#ifdef CONFIG_USERSPACE
366static inline int z_vrfy_k_msgq_peek_at(struct k_msgq *msgq, void *data, uint32_t idx)
367{
Anas Nashifa08bfeb2023-09-27 11:20:28 +0000368 K_OOPS(K_SYSCALL_OBJ(msgq, K_OBJ_MSGQ));
369 K_OOPS(K_SYSCALL_MEMORY_WRITE(data, msgq->msg_size));
romain pelletant14bcc852022-12-28 13:06:16 +0100370
371 return z_impl_k_msgq_peek_at(msgq, data, idx);
372}
Yong Cong Sinbbe5e1e2024-01-24 17:35:04 +0800373#include <zephyr/syscalls/k_msgq_peek_at_mrsh.c>
Simon Heinbcd1d192024-03-08 12:00:10 +0100374#endif /* CONFIG_USERSPACE */
romain pelletant14bcc852022-12-28 13:06:16 +0100375
Anas Nashif7bde81f2019-06-19 07:30:50 -0400376void z_impl_k_msgq_purge(struct k_msgq *msgq)
Benjamin Walsh456c6da2016-09-02 18:55:39 -0400377{
Anas Nashif7bde81f2019-06-19 07:30:50 -0400378 k_spinlock_key_t key;
Benjamin Walshb7ef0cb2016-10-05 17:32:01 -0400379 struct k_thread *pending_thread;
Benjamin Walsh456c6da2016-09-02 18:55:39 -0400380
Anas Nashif7bde81f2019-06-19 07:30:50 -0400381 key = k_spin_lock(&msgq->lock);
382
Torbjörn Leksell9ab447b2021-03-26 12:39:53 +0100383 SYS_PORT_TRACING_OBJ_FUNC(k_msgq, purge, msgq);
384
Peter Mitsis340d00a2016-09-22 13:59:00 -0400385 /* wake up any threads that are waiting to write */
Hess Nathan20b55422024-05-02 14:02:20 +0200386 for (pending_thread = z_unpend_first_thread(&msgq->wait_q); pending_thread != NULL;
387 pending_thread = z_unpend_first_thread(&msgq->wait_q)) {
Andrew Boie4f77c2a2019-11-07 12:43:29 -0800388 arch_thread_return_value_set(pending_thread, -ENOMSG);
Patrik Flykt4344e272019-03-08 14:19:05 -0700389 z_ready_thread(pending_thread);
Benjamin Walsh456c6da2016-09-02 18:55:39 -0400390 }
391
Anas Nashif7bde81f2019-06-19 07:30:50 -0400392 msgq->used_msgs = 0;
393 msgq->read_ptr = msgq->write_ptr;
Peter Mitsis340d00a2016-09-22 13:59:00 -0400394
Anas Nashif7bde81f2019-06-19 07:30:50 -0400395 z_reschedule(&msgq->lock, key);
Benjamin Walsh456c6da2016-09-02 18:55:39 -0400396}
Andrew Boie82edb6e2017-10-02 10:53:06 -0700397
398#ifdef CONFIG_USERSPACE
Anas Nashif25c87db2021-03-29 10:54:23 -0400399static inline void z_vrfy_k_msgq_purge(struct k_msgq *msgq)
Andy Ross65649742019-08-06 13:34:31 -0700400{
Anas Nashifa08bfeb2023-09-27 11:20:28 +0000401 K_OOPS(K_SYSCALL_OBJ(msgq, K_OBJ_MSGQ));
Anas Nashif25c87db2021-03-29 10:54:23 -0400402 z_impl_k_msgq_purge(msgq);
Andy Ross65649742019-08-06 13:34:31 -0700403}
Yong Cong Sinbbe5e1e2024-01-24 17:35:04 +0800404#include <zephyr/syscalls/k_msgq_purge_mrsh.c>
Andy Ross65649742019-08-06 13:34:31 -0700405
Anas Nashif25c87db2021-03-29 10:54:23 -0400406static inline uint32_t z_vrfy_k_msgq_num_free_get(struct k_msgq *msgq)
Andy Ross65649742019-08-06 13:34:31 -0700407{
Anas Nashifa08bfeb2023-09-27 11:20:28 +0000408 K_OOPS(K_SYSCALL_OBJ(msgq, K_OBJ_MSGQ));
Anas Nashif25c87db2021-03-29 10:54:23 -0400409 return z_impl_k_msgq_num_free_get(msgq);
Andy Ross65649742019-08-06 13:34:31 -0700410}
Yong Cong Sinbbe5e1e2024-01-24 17:35:04 +0800411#include <zephyr/syscalls/k_msgq_num_free_get_mrsh.c>
Andy Ross65649742019-08-06 13:34:31 -0700412
Anas Nashif25c87db2021-03-29 10:54:23 -0400413static inline uint32_t z_vrfy_k_msgq_num_used_get(struct k_msgq *msgq)
Andy Ross65649742019-08-06 13:34:31 -0700414{
Anas Nashifa08bfeb2023-09-27 11:20:28 +0000415 K_OOPS(K_SYSCALL_OBJ(msgq, K_OBJ_MSGQ));
Anas Nashif25c87db2021-03-29 10:54:23 -0400416 return z_impl_k_msgq_num_used_get(msgq);
Andy Ross65649742019-08-06 13:34:31 -0700417}
Yong Cong Sinbbe5e1e2024-01-24 17:35:04 +0800418#include <zephyr/syscalls/k_msgq_num_used_get_mrsh.c>
Andy Ross65649742019-08-06 13:34:31 -0700419
Simon Heinbcd1d192024-03-08 12:00:10 +0100420#endif /* CONFIG_USERSPACE */
Peter Mitsis6df8efe2023-05-11 14:06:46 -0400421
422#ifdef CONFIG_OBJ_CORE_MSGQ
423static int init_msgq_obj_core_list(void)
424{
425 /* Initialize msgq object type */
426
427 z_obj_type_init(&obj_type_msgq, K_OBJ_TYPE_MSGQ_ID,
428 offsetof(struct k_msgq, obj_core));
429
430 /* Initialize and link statically defined message queues */
431
432 STRUCT_SECTION_FOREACH(k_msgq, msgq) {
433 k_obj_core_init_and_link(K_OBJ_CORE(msgq), &obj_type_msgq);
434 }
435
436 return 0;
437};
438
439SYS_INIT(init_msgq_obj_core_list, PRE_KERNEL_1,
440 CONFIG_KERNEL_INIT_PRIORITY_OBJECTS);
441
Simon Heinbcd1d192024-03-08 12:00:10 +0100442#endif /* CONFIG_OBJ_CORE_MSGQ */