1 /*
2 * Copyright (c) 2018 Intel Corporation
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/ztest.h>
8 #include <zephyr/kernel.h>
9
10 #define STACK_SIZE (512 + CONFIG_TEST_EXTRA_STACK_SIZE)
11 #define MAIL_LEN 64
12 #define HIGH_PRIO 1
13 #define LOW_PRIO 8
14
15 static K_THREAD_STACK_DEFINE(tstack, STACK_SIZE);
16 static K_THREAD_STACK_DEFINE(high_stack, STACK_SIZE);
17 static K_THREAD_STACK_DEFINE(low_stack, STACK_SIZE);
18
19 static struct k_thread tdata, high_tdata, low_tdata;
20 static struct k_mbox mbox, multi_tmbox;
21 static struct k_sem sync_sema;
22 static k_tid_t tid1, receiver_tid;
23 static char msg_data[2][MAIL_LEN] = {
24 "send to high prio",
25 "send to low prio"};
26
27 static enum mmsg_type {
28 PUT_GET_NULL = 0,
29 TARGET_SOURCE
30 } info_type;
31
msg_sender(struct k_mbox * pmbox,k_timeout_t timeout)32 static void msg_sender(struct k_mbox *pmbox, k_timeout_t timeout)
33 {
34 static struct k_mbox_msg mmsg;
35
36 (void)memset(&mmsg, 0, sizeof(mmsg));
37
38 switch (info_type) {
39 case PUT_GET_NULL:
40 /* mbox sync put empty message */
41 mmsg.info = PUT_GET_NULL;
42 mmsg.size = 0;
43 mmsg.tx_data = NULL;
44 if (K_TIMEOUT_EQ(timeout, K_FOREVER)) {
45 k_mbox_put(pmbox, &mmsg, K_FOREVER);
46 } else if (K_TIMEOUT_EQ(timeout, K_NO_WAIT)) {
47 k_mbox_put(pmbox, &mmsg, K_NO_WAIT);
48 } else {
49 k_mbox_put(pmbox, &mmsg, timeout);
50 }
51 break;
52 default:
53 break;
54 }
55 }
56
msg_receiver(struct k_mbox * pmbox,k_tid_t thd_id,k_timeout_t timeout)57 static void msg_receiver(struct k_mbox *pmbox, k_tid_t thd_id,
58 k_timeout_t timeout)
59 {
60 static struct k_mbox_msg mmsg;
61 static char rxdata[MAIL_LEN];
62
63 switch (info_type) {
64 case PUT_GET_NULL:
65 mmsg.size = sizeof(rxdata);
66 mmsg.rx_source_thread = thd_id;
67 if (K_TIMEOUT_EQ(timeout, K_FOREVER)) {
68 zassert_true(k_mbox_get(pmbox, &mmsg,
69 rxdata, K_FOREVER) == 0, NULL);
70 } else if (K_TIMEOUT_EQ(timeout, K_NO_WAIT)) {
71 zassert_false(k_mbox_get(pmbox, &mmsg,
72 rxdata, K_NO_WAIT) == 0, NULL);
73 } else {
74 zassert_true(k_mbox_get(pmbox, &mmsg,
75 rxdata, timeout) == 0, NULL);
76 }
77 break;
78 default:
79 break;
80 }
81 }
82
test_mbox_init(void)83 static void test_mbox_init(void)
84 {
85 k_mbox_init(&mbox);
86 k_mbox_init(&multi_tmbox);
87
88 k_sem_init(&sync_sema, 0, 2);
89 }
90
test_send(void * p1,void * p2,void * p3)91 static void test_send(void *p1, void *p2, void *p3)
92 {
93 msg_sender((struct k_mbox *)p1, K_NO_WAIT);
94 }
95
96 /* Receive message from any thread with no wait */
ZTEST(mbox_usage,test_msg_receiver)97 ZTEST(mbox_usage, test_msg_receiver)
98 {
99 static k_tid_t tid;
100
101 info_type = PUT_GET_NULL;
102 msg_receiver(&mbox, K_ANY, K_NO_WAIT);
103
104 tid = k_thread_create(&tdata, tstack, STACK_SIZE,
105 test_send, &mbox, NULL, NULL,
106 K_PRIO_PREEMPT(0), 0, K_NO_WAIT);
107
108 msg_receiver(&mbox, K_ANY, K_MSEC(2));
109 k_thread_abort(tid);
110 }
111
test_send_un(void * p1,void * p2,void * p3)112 static void test_send_un(void *p1, void *p2, void *p3)
113 {
114 TC_PRINT("Sender UNLIMITED\n");
115 msg_sender((struct k_mbox *)p1, K_FOREVER);
116 }
117
118 /* Receive message from thread tid1 */
ZTEST(mbox_usage,test_msg_receiver_unlimited)119 ZTEST(mbox_usage, test_msg_receiver_unlimited)
120 {
121 info_type = PUT_GET_NULL;
122
123 receiver_tid = k_current_get();
124 tid1 = k_thread_create(&tdata, tstack, STACK_SIZE,
125 test_send_un, &mbox, NULL, NULL,
126 K_PRIO_PREEMPT(0), 0, K_NO_WAIT);
127
128 msg_receiver(&mbox, tid1, K_FOREVER);
129 k_thread_abort(tid1);
130 }
131
thread_low_prio(void * p1,void * p2,void * p3)132 static void thread_low_prio(void *p1, void *p2, void *p3)
133 {
134 static struct k_mbox_msg mmsg = {0};
135 static char rxdata[MAIL_LEN];
136 int ret;
137
138 mmsg.rx_source_thread = K_ANY;
139 mmsg.size = sizeof(rxdata);
140 ret = k_mbox_get(&multi_tmbox, &mmsg, rxdata, K_FOREVER);
141
142 zassert_equal(ret, 0, "low prio get msg failed");
143 zassert_equal(memcmp(rxdata, msg_data[1], MAIL_LEN), 0,
144 "low prio data error");
145
146 k_sem_give(&sync_sema);
147 }
148
thread_high_prio(void * p1,void * p2,void * p3)149 static void thread_high_prio(void *p1, void *p2, void *p3)
150 {
151 static struct k_mbox_msg mmsg = {0};
152 static char rxdata[MAIL_LEN];
153 int ret;
154
155 mmsg.rx_source_thread = K_ANY;
156 mmsg.size = sizeof(rxdata);
157 ret = k_mbox_get(&multi_tmbox, &mmsg, rxdata, K_FOREVER);
158
159 zassert_equal(ret, 0, "high prio get msg failed");
160 zassert_equal(memcmp(rxdata, msg_data[0], MAIL_LEN), 0,
161 "high prio data error");
162
163 k_sem_give(&sync_sema);
164 }
165
ZTEST_USER(mbox_usage_1cpu,test_multi_thread_send_get)166 ZTEST_USER(mbox_usage_1cpu, test_multi_thread_send_get)
167 {
168 static k_tid_t low_prio, high_prio;
169 struct k_mbox_msg mmsg = {0};
170
171 k_sem_reset(&sync_sema);
172 /* Create diff priority thread to receive msg with same mbox */
173 low_prio = k_thread_create(&low_tdata, low_stack, STACK_SIZE,
174 thread_low_prio, &multi_tmbox, NULL, NULL,
175 LOW_PRIO, 0, K_NO_WAIT);
176
177 high_prio = k_thread_create(&high_tdata, high_stack, STACK_SIZE,
178 thread_high_prio, &multi_tmbox, NULL, NULL,
179 HIGH_PRIO, 0, K_NO_WAIT);
180
181 k_sleep(K_MSEC(20));
182 mmsg.size = sizeof(msg_data[0]);
183 mmsg.tx_data = msg_data[0];
184 mmsg.tx_target_thread = K_ANY;
185 k_mbox_put(&multi_tmbox, &mmsg, K_FOREVER);
186
187 mmsg.size = sizeof(msg_data[1]);
188 mmsg.tx_data = msg_data[1];
189 mmsg.tx_target_thread = K_ANY;
190 k_mbox_put(&multi_tmbox, &mmsg, K_FOREVER);
191
192 /* Sync with threads to ensure process end */
193 k_sem_take(&sync_sema, K_FOREVER);
194 k_sem_take(&sync_sema, K_FOREVER);
195
196 k_thread_abort(low_prio);
197 k_thread_abort(high_prio);
198 }
199
setup_mbox_usage(void)200 void *setup_mbox_usage(void)
201 {
202 test_mbox_init();
203
204 return NULL;
205 }
206
207 ZTEST_SUITE(mbox_usage, NULL, setup_mbox_usage, NULL, NULL, NULL);
208
209 ZTEST_SUITE(mbox_usage_1cpu, NULL, setup_mbox_usage,
210 ztest_simple_1cpu_before, ztest_simple_1cpu_after, NULL);
211