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