1 /*
2  * Copyright (c) 2017 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_os.h>
10 
11 #define TIMEOUT 500
12 
13 osMutexDef(Mutex_1);
14 osMutexDef(Mutex_2);
15 osMutexDef(Mutex_multi);
16 
17 int max_mtx_cnt = CONFIG_CMSIS_MUTEX_MAX_COUNT;
18 
cleanup_max_mutex(osMutexId * mutex_ids)19 void cleanup_max_mutex(osMutexId *mutex_ids)
20 {
21 	int mutex_count = 0;
22 	osStatus 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 mutex_ids[CONFIG_CMSIS_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] = osMutexCreate(osMutex(Mutex_multi));
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 mutex_id = 0;
52 	osStatus status;
53 
54 	/* Try deleting invalid mutex object */
55 	status = osMutexDelete(mutex_id);
56 	zassert_true(status == osErrorParameter,
57 		     "Invalid Mutex deleted unexpectedly!");
58 
59 	mutex_id = osMutexCreate(osMutex(Mutex_1));
60 	zassert_true(mutex_id != NULL, "Mutex1 creation failed");
61 
62 	/* Try to release mutex without obtaining it */
63 	status = osMutexRelease(mutex_id);
64 	zassert_true(status == osErrorResource, "Mutex released unexpectedly!");
65 
66 	status = osMutexWait(mutex_id, 0);
67 	zassert_true(status == osOK, "Mutex wait failure");
68 
69 	/* Try to acquire an already acquired mutex */
70 	status = osMutexWait(mutex_id, 0);
71 	zassert_true(status == osOK, "Mutex wait failure");
72 
73 	status = osMutexRelease(mutex_id);
74 	zassert_true(status == osOK, "Mutex release failure");
75 
76 	/* Release mutex again as it was acquired twice */
77 	status = osMutexRelease(mutex_id);
78 	zassert_true(status == osOK, "Mutex release failure");
79 
80 	/* Try to release mutex that was already released */
81 	status = osMutexRelease(mutex_id);
82 	zassert_true(status == osErrorResource, "Mutex released unexpectedly!");
83 
84 	status = osMutexDelete(mutex_id);
85 	zassert_true(status == osOK, "Mutex delete failure");
86 
87 	/* Try mutex creation for more than maximum allowed count */
88 	test_max_mutex();
89 }
90 
tThread_entry_lock_timeout(void const * arg)91 void tThread_entry_lock_timeout(void const *arg)
92 {
93 	osStatus status;
94 
95 	/* Mutex cannot be acquired here as it is still held by the
96 	 * other thread. Try with and without timeout.
97 	 */
98 	status = osMutexWait((osMutexId)arg, 0);
99 	zassert_true(status == osErrorResource);
100 
101 	status = osMutexWait((osMutexId)arg, TIMEOUT - 100);
102 	zassert_true(status == osErrorTimeoutResource);
103 
104 	/* At this point, mutex is held by the other thread.
105 	 * Trying to release it here should fail.
106 	 */
107 	status = osMutexRelease((osMutexId)arg);
108 	zassert_true(status == osErrorResource, "Mutex unexpectedly released");
109 
110 	/* This delay ensures that the mutex gets released by the other
111 	 * thread in the meantime
112 	 */
113 	osDelay(TIMEOUT - 100);
114 
115 	/* Now that the mutex is free, it should be possible to acquire
116 	 * and release it.
117 	 */
118 	status = osMutexWait((osMutexId)arg, TIMEOUT);
119 	zassert_true(status == osOK);
120 	osMutexRelease((osMutexId)arg);
121 }
122 
123 osThreadDef(tThread_entry_lock_timeout, osPriorityNormal, 1, 0);
124 
ZTEST(cmsis_mutex,test_mutex_lock_timeout)125 ZTEST(cmsis_mutex, test_mutex_lock_timeout)
126 {
127 	osThreadId id;
128 	osMutexId mutex_id;
129 	osStatus status;
130 
131 	mutex_id = osMutexCreate(osMutex(Mutex_2));
132 	zassert_true(mutex_id != NULL, "Mutex2 creation failed");
133 
134 	id = osThreadCreate(osThread(tThread_entry_lock_timeout), mutex_id);
135 	zassert_true(id != NULL, "Thread creation failed");
136 
137 	status = osMutexWait(mutex_id, osWaitForever);
138 	zassert_true(status == osOK, "Mutex wait failure");
139 
140 	/* wait for spawn thread to take action */
141 	osDelay(TIMEOUT);
142 
143 	/* Release the mutex to be used by the other thread */
144 	osMutexRelease(mutex_id);
145 	osDelay(TIMEOUT);
146 
147 	osMutexDelete(mutex_id);
148 }
149 ZTEST_SUITE(cmsis_mutex, NULL, NULL, NULL, NULL, NULL);
150