1 /*
2  * Copyright (c) 2018 Intel Corporation
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/kernel.h>
8 #include <zephyr/portability/cmsis_types.h>
9 #include <string.h>
10 #include "wrapper.h"
11 
12 K_MEM_SLAB_DEFINE(cmsis_rtos_mutex_cb_slab, sizeof(struct cmsis_rtos_mutex_cb),
13 		  CONFIG_CMSIS_V2_MUTEX_MAX_COUNT, 4);
14 
15 static const osMutexAttr_t init_mutex_attrs = {
16 	.name = "ZephyrMutex",
17 	.attr_bits = osMutexPrioInherit,
18 	.cb_mem = NULL,
19 	.cb_size = 0,
20 };
21 
22 /**
23  * @brief Create and Initialize a Mutex object.
24  */
osMutexNew(const osMutexAttr_t * attr)25 osMutexId_t osMutexNew(const osMutexAttr_t *attr)
26 {
27 	struct cmsis_rtos_mutex_cb *mutex;
28 
29 	if (k_is_in_isr()) {
30 		return NULL;
31 	}
32 
33 	if (attr == NULL) {
34 		attr = &init_mutex_attrs;
35 	}
36 
37 	__ASSERT(attr->attr_bits & osMutexPrioInherit,
38 		 "Zephyr supports osMutexPrioInherit by default. Do not unselect it\n");
39 
40 	__ASSERT(!(attr->attr_bits & osMutexRobust), "Zephyr does not support osMutexRobust.\n");
41 
42 	if (attr->cb_mem != NULL) {
43 		__ASSERT(attr->cb_size == sizeof(struct cmsis_rtos_mutex_cb), "Invalid cb_size\n");
44 		mutex = (struct cmsis_rtos_mutex_cb *)attr->cb_mem;
45 	} else if (k_mem_slab_alloc(&cmsis_rtos_mutex_cb_slab, (void **)&mutex, K_MSEC(100)) != 0) {
46 		return NULL;
47 	}
48 	memset(mutex, 0, sizeof(struct cmsis_rtos_mutex_cb));
49 	mutex->is_cb_dynamic_allocation = attr->cb_mem == NULL;
50 
51 	k_mutex_init(&mutex->z_mutex);
52 	mutex->state = attr->attr_bits;
53 
54 	if (attr->name == NULL) {
55 		strncpy(mutex->name, init_mutex_attrs.name, sizeof(mutex->name) - 1);
56 	} else {
57 		strncpy(mutex->name, attr->name, sizeof(mutex->name) - 1);
58 	}
59 
60 	return (osMutexId_t)mutex;
61 }
62 
63 /**
64  * @brief Wait until a Mutex becomes available.
65  */
osMutexAcquire(osMutexId_t mutex_id,uint32_t timeout)66 osStatus_t osMutexAcquire(osMutexId_t mutex_id, uint32_t timeout)
67 {
68 	struct cmsis_rtos_mutex_cb *mutex = (struct cmsis_rtos_mutex_cb *)mutex_id;
69 	int status;
70 
71 	if (mutex_id == NULL) {
72 		return osErrorParameter;
73 	}
74 
75 	if (k_is_in_isr()) {
76 		return osErrorISR;
77 	}
78 
79 	if (timeout == osWaitForever) {
80 		status = k_mutex_lock(&mutex->z_mutex, K_FOREVER);
81 	} else if (timeout == 0U) {
82 		status = k_mutex_lock(&mutex->z_mutex, K_NO_WAIT);
83 	} else {
84 		status = k_mutex_lock(&mutex->z_mutex, K_TICKS(timeout));
85 	}
86 
87 	if (timeout != 0 && (status == -EAGAIN || status == -EBUSY)) {
88 		return osErrorTimeout;
89 	} else if (status != 0) {
90 		return osErrorResource;
91 	} else {
92 		return osOK;
93 	}
94 }
95 
96 /**
97  * @brief Release a Mutex that was obtained by osMutexWait.
98  */
osMutexRelease(osMutexId_t mutex_id)99 osStatus_t osMutexRelease(osMutexId_t mutex_id)
100 {
101 	struct cmsis_rtos_mutex_cb *mutex = (struct cmsis_rtos_mutex_cb *)mutex_id;
102 
103 	if (mutex_id == NULL) {
104 		return osErrorParameter;
105 	}
106 
107 	if (k_is_in_isr()) {
108 		return osErrorISR;
109 	}
110 
111 	if (k_mutex_unlock(&mutex->z_mutex) != 0) {
112 		return osErrorResource;
113 	}
114 
115 	return osOK;
116 }
117 
118 /**
119  * @brief Delete a Mutex that was created by osMutexCreate.
120  */
osMutexDelete(osMutexId_t mutex_id)121 osStatus_t osMutexDelete(osMutexId_t mutex_id)
122 {
123 	struct cmsis_rtos_mutex_cb *mutex = (struct cmsis_rtos_mutex_cb *)mutex_id;
124 
125 	if (mutex_id == NULL) {
126 		return osErrorParameter;
127 	}
128 
129 	if (k_is_in_isr()) {
130 		return osErrorISR;
131 	}
132 
133 	/* The status code "osErrorResource" (mutex specified by parameter
134 	 * mutex_id is in an invalid mutex state) is not supported in Zephyr.
135 	 */
136 	if (mutex->is_cb_dynamic_allocation) {
137 		k_mem_slab_free(&cmsis_rtos_mutex_cb_slab, (void *)mutex);
138 	}
139 
140 	return osOK;
141 }
142 
osMutexGetOwner(osMutexId_t mutex_id)143 osThreadId_t osMutexGetOwner(osMutexId_t mutex_id)
144 {
145 	struct cmsis_rtos_mutex_cb *mutex = (struct cmsis_rtos_mutex_cb *)mutex_id;
146 
147 	if (k_is_in_isr() || (mutex == NULL)) {
148 		return NULL;
149 	}
150 
151 	/* Mutex was not obtained before */
152 	if (mutex->z_mutex.lock_count == 0U) {
153 		return NULL;
154 	}
155 
156 	return get_cmsis_thread_id(mutex->z_mutex.owner);
157 }
158 
osMutexGetName(osMutexId_t mutex_id)159 const char *osMutexGetName(osMutexId_t mutex_id)
160 {
161 	struct cmsis_rtos_mutex_cb *mutex = (struct cmsis_rtos_mutex_cb *)mutex_id;
162 
163 	if (k_is_in_isr() || (mutex == NULL)) {
164 		return NULL;
165 	}
166 
167 	return mutex->name;
168 }
169