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