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