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 #include <zephyr/portability/cmsis_os2.h>
10 #include <zephyr/portability/cmsis_types.h>
11
12 #define WAIT_TICKS 5
13 #define TIMEOUT_TICKS (10 + WAIT_TICKS)
14 #define STACKSZ CONFIG_CMSIS_V2_THREAD_MAX_STACK_SIZE
15
16 int max_mtx_cnt = CONFIG_CMSIS_V2_MUTEX_MAX_COUNT;
17 const osMutexAttr_t mutex_attr = {"myMutex", osMutexRecursive | osMutexPrioInherit, NULL, 0U};
18
cleanup_max_mutex(osMutexId_t * mutex_ids)19 void cleanup_max_mutex(osMutexId_t *mutex_ids)
20 {
21 int mutex_count = 0;
22 osStatus_t status;
23
24 for (mutex_count = 0; mutex_count < max_mtx_cnt; mutex_count++) {
25 status = osMutexDelete(mutex_ids[mutex_count]);
26 zassert_true(status == osOK, "Mutex delete fail");
27 }
28 }
29
test_max_mutex(void)30 void test_max_mutex(void)
31 {
32 osMutexId_t mutex_ids[CONFIG_CMSIS_V2_MUTEX_MAX_COUNT + 1];
33 int mtx_cnt = 0;
34
35 /* Try mutex creation for more than maximum count */
36 for (mtx_cnt = 0; mtx_cnt < max_mtx_cnt + 1; mtx_cnt++) {
37 mutex_ids[mtx_cnt] = osMutexNew(&mutex_attr);
38 if (mtx_cnt == max_mtx_cnt) {
39 zassert_true(mutex_ids[mtx_cnt] == NULL,
40 "Mutex creation pass unexpectedly after max count");
41 cleanup_max_mutex(mutex_ids);
42 } else {
43 zassert_true(mutex_ids[mtx_cnt] != NULL,
44 "Multiple mutex creation failed before max count");
45 }
46 }
47 }
48
ZTEST(cmsis_mutex,test_mutex)49 ZTEST(cmsis_mutex, test_mutex)
50 {
51 osMutexId_t mutex_id = 0;
52 osThreadId_t id;
53 osStatus_t status;
54 const char *name;
55
56 /* Try deleting invalid mutex object */
57 status = osMutexDelete(mutex_id);
58 zassert_true(status == osErrorParameter, "Invalid Mutex deleted unexpectedly!");
59
60 mutex_id = osMutexNew(&mutex_attr);
61 zassert_true(mutex_id != NULL, "Mutex1 creation failed");
62
63 name = osMutexGetName(mutex_id);
64 zassert_str_equal(mutex_attr.name, name, "Error getting Mutex name");
65
66 /* Try to release mutex without obtaining it */
67 status = osMutexRelease(mutex_id);
68 zassert_true(status == osErrorResource, "Mutex released unexpectedly!");
69
70 /* Try figuring out the owner for a Mutex which has not been
71 * acquired by any thread yet.
72 */
73 id = osMutexGetOwner(mutex_id);
74 zassert_true(id == NULL, "Something wrong with MutexGetOwner!");
75
76 status = osMutexAcquire(mutex_id, 0);
77 zassert_true(status == osOK, "Mutex wait failure");
78
79 id = osMutexGetOwner(mutex_id);
80 zassert_equal(id, osThreadGetId(), "Current thread is not the owner!");
81
82 /* Try to acquire an already acquired mutex */
83 status = osMutexAcquire(mutex_id, 0);
84 zassert_true(status == osOK, "Mutex wait failure");
85
86 status = osMutexRelease(mutex_id);
87 zassert_true(status == osOK, "Mutex release failure");
88
89 /* Release mutex again as it was acquired twice */
90 status = osMutexRelease(mutex_id);
91 zassert_true(status == osOK, "Mutex release failure");
92
93 /* Try to release mutex that was already released */
94 status = osMutexRelease(mutex_id);
95 zassert_true(status == osErrorResource, "Mutex released unexpectedly!");
96
97 status = osMutexDelete(mutex_id);
98 zassert_true(status == osOK, "Mutex delete failure");
99
100 /* Try mutex creation for more than maximum allowed count */
101 test_max_mutex();
102 }
103
tThread_entry_lock_timeout(void * arg)104 void tThread_entry_lock_timeout(void *arg)
105 {
106 osStatus_t status;
107 osThreadId_t id;
108
109 /* Mutex cannot be acquired/released here as it is still held
110 * by the other thread. Try with and without timeout.
111 */
112 status = osMutexAcquire((osMutexId_t)arg, 0);
113 zassert_true(status == osErrorResource);
114
115 status = osMutexAcquire((osMutexId_t)arg, WAIT_TICKS);
116 zassert_true(status == osErrorTimeout);
117
118 status = osMutexRelease((osMutexId_t)arg);
119 zassert_true(status == osErrorResource, "Mutex unexpectedly released");
120
121 id = osMutexGetOwner((osMutexId_t)arg);
122 zassert_not_equal(id, osThreadGetId(), "Unexpectedly, current thread is the mutex owner!");
123
124 /* This delay ensures that the mutex gets released by the other
125 * thread in the meantime
126 */
127 osDelay(TIMEOUT_TICKS);
128
129 /* Now that the mutex is free, it should be possible to acquire
130 * and release it.
131 */
132 status = osMutexAcquire((osMutexId_t)arg, TIMEOUT_TICKS);
133 zassert_true(status == osOK);
134 osMutexRelease((osMutexId_t)arg);
135 }
136
137 static K_THREAD_STACK_DEFINE(test_stack, STACKSZ);
138 static osThreadAttr_t thread_attr = {.name = "Mutex_check",
139 .attr_bits = osThreadDetached,
140 .cb_mem = NULL,
141 .cb_size = 0,
142 .stack_mem = &test_stack,
143 .stack_size = STACKSZ,
144 .priority = osPriorityNormal,
145 .tz_module = 0,
146 .reserved = 0};
147
ZTEST(cmsis_mutex,test_mutex_lock_timeout)148 ZTEST(cmsis_mutex, test_mutex_lock_timeout)
149 {
150 osThreadId_t id;
151 osMutexId_t mutex_id;
152 osStatus_t status;
153
154 mutex_id = osMutexNew(&mutex_attr);
155 zassert_true(mutex_id != NULL, "Mutex2 creation failed");
156
157 id = osThreadNew(tThread_entry_lock_timeout, mutex_id, &thread_attr);
158 zassert_true(id != NULL, "Thread creation failed");
159
160 status = osMutexAcquire(mutex_id, osWaitForever);
161 zassert_true(status == osOK, "Mutex wait failure");
162
163 /* wait for spawn thread to take action */
164 osDelay(TIMEOUT_TICKS);
165
166 /* Release the mutex to be used by the other thread */
167 osMutexRelease(mutex_id);
168 osDelay(TIMEOUT_TICKS);
169
170 osMutexDelete(mutex_id);
171 }
172
173 static struct cmsis_rtos_mutex_cb mutex_cb2;
174 static const osMutexAttr_t mutex_attrs2 = {
175 .name = "Mutex2",
176 .attr_bits = osMutexPrioInherit,
177 .cb_mem = &mutex_cb2,
178 .cb_size = sizeof(mutex_cb2),
179 };
ZTEST(cmsis_mutex,test_mutex_static_allocation)180 ZTEST(cmsis_mutex, test_mutex_static_allocation)
181 {
182 osMutexId_t id;
183
184 id = osMutexNew(&mutex_attrs2);
185 zassert_not_null(id, "Failed creating mutex using static cb");
186
187 zassert_true(osMutexDelete(id) == osOK, "osMutexDelete failed");
188 }
189
ZTEST(cmsis_mutex,test_mutex_static_multiple_new)190 ZTEST(cmsis_mutex, test_mutex_static_multiple_new)
191 {
192 osMutexId_t id;
193
194 for (int i = 0; i < 100; ++i) {
195 id = osMutexNew(&mutex_attrs2);
196 zassert_not_null(id, "Failed creating mutex using static cb");
197
198 zassert_true(osMutexDelete(id) == osOK, "osMutexDelete failed");
199 }
200 }
201 ZTEST_SUITE(cmsis_mutex, NULL, NULL, NULL, NULL, NULL);
202