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