|  | /* | 
|  | * Copyright (c) 2018 Intel Corporation | 
|  | * | 
|  | * SPDX-License-Identifier: Apache-2.0 | 
|  | */ | 
|  |  | 
|  | #include <kernel_structs.h> | 
|  | #include "wrapper.h" | 
|  |  | 
|  | K_MEM_SLAB_DEFINE(cv2_mutex_slab, sizeof(struct cv2_mutex), | 
|  | CONFIG_CMSIS_V2_MUTEX_MAX_COUNT, 4); | 
|  |  | 
|  | static const osMutexAttr_t init_mutex_attrs = { | 
|  | .name = "ZephyrMutex", | 
|  | .attr_bits = osMutexPrioInherit, | 
|  | .cb_mem = NULL, | 
|  | .cb_size = 0, | 
|  | }; | 
|  |  | 
|  | /** | 
|  | * @brief Create and Initialize a Mutex object. | 
|  | */ | 
|  | osMutexId_t osMutexNew(const osMutexAttr_t *attr) | 
|  | { | 
|  | struct cv2_mutex *mutex; | 
|  |  | 
|  | if (k_is_in_isr()) { | 
|  | return NULL; | 
|  | } | 
|  |  | 
|  | if (attr == NULL) { | 
|  | attr = &init_mutex_attrs; | 
|  | } | 
|  |  | 
|  | __ASSERT(attr->attr_bits & osMutexPrioInherit, | 
|  | "Zephyr supports osMutexPrioInherit by default. Do not unselect it\n"); | 
|  |  | 
|  | __ASSERT(!(attr->attr_bits & osMutexRobust), | 
|  | "Zephyr does not support osMutexRobust.\n"); | 
|  |  | 
|  | if (k_mem_slab_alloc(&cv2_mutex_slab, (void **)&mutex, 100) == 0) { | 
|  | memset(mutex, 0, sizeof(struct cv2_mutex)); | 
|  | } else { | 
|  | return NULL; | 
|  | } | 
|  |  | 
|  | k_mutex_init(&mutex->z_mutex); | 
|  | mutex->state = attr->attr_bits; | 
|  |  | 
|  | if (attr->name == NULL) { | 
|  | strncpy(mutex->name, init_mutex_attrs.name, | 
|  | sizeof(mutex->name) - 1); | 
|  | } else { | 
|  | strncpy(mutex->name, attr->name, sizeof(mutex->name) - 1); | 
|  | } | 
|  |  | 
|  | return (osMutexId_t)mutex; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * @brief Wait until a Mutex becomes available. | 
|  | */ | 
|  | osStatus_t osMutexAcquire(osMutexId_t mutex_id, uint32_t timeout) | 
|  | { | 
|  | struct cv2_mutex *mutex = (struct cv2_mutex *) mutex_id; | 
|  | int status; | 
|  |  | 
|  | if (mutex_id == NULL) { | 
|  | return osErrorParameter; | 
|  | } | 
|  |  | 
|  | if (k_is_in_isr()) { | 
|  | return osErrorISR; | 
|  | } | 
|  |  | 
|  | if (mutex->z_mutex.lock_count == 0 || | 
|  | mutex->z_mutex.owner == _current) { | 
|  | } | 
|  |  | 
|  | /* Throw an error if the mutex is not configured to be recursive and | 
|  | * the current thread is trying to acquire the mutex again. | 
|  | */ | 
|  | if ((mutex->state & osMutexRecursive) == 0) { | 
|  | if ((mutex->z_mutex.owner == _current) && | 
|  | (mutex->z_mutex.lock_count != 0)) { | 
|  | return osErrorResource; | 
|  | } | 
|  | } | 
|  |  | 
|  | if (timeout == osWaitForever) { | 
|  | status = k_mutex_lock(&mutex->z_mutex, K_FOREVER); | 
|  | } else if (timeout == 0) { | 
|  | status = k_mutex_lock(&mutex->z_mutex, K_NO_WAIT); | 
|  | } else { | 
|  | status = k_mutex_lock(&mutex->z_mutex, | 
|  | __ticks_to_ms(timeout)); | 
|  | } | 
|  |  | 
|  | if (status == -EBUSY) { | 
|  | return osErrorResource; | 
|  | } else if (status == -EAGAIN) { | 
|  | return osErrorTimeout; | 
|  | } else { | 
|  | return osOK; | 
|  | } | 
|  | } | 
|  |  | 
|  | /** | 
|  | * @brief Release a Mutex that was obtained by osMutexWait. | 
|  | */ | 
|  | osStatus_t osMutexRelease(osMutexId_t mutex_id) | 
|  | { | 
|  | struct cv2_mutex *mutex = (struct cv2_mutex *) mutex_id; | 
|  |  | 
|  | if (mutex_id == NULL) { | 
|  | return osErrorParameter; | 
|  | } | 
|  |  | 
|  | if (k_is_in_isr()) { | 
|  | return osErrorISR; | 
|  | } | 
|  |  | 
|  | /* Mutex was not obtained before or was not owned by current thread */ | 
|  | if ((mutex->z_mutex.lock_count == 0) || | 
|  | (mutex->z_mutex.owner != _current)) { | 
|  | return osErrorResource; | 
|  | } | 
|  |  | 
|  | k_mutex_unlock(&mutex->z_mutex); | 
|  |  | 
|  | return osOK; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * @brief Delete a Mutex that was created by osMutexCreate. | 
|  | */ | 
|  | osStatus_t osMutexDelete(osMutexId_t mutex_id) | 
|  | { | 
|  | struct cv2_mutex *mutex = (struct cv2_mutex *)mutex_id; | 
|  |  | 
|  | if (mutex_id == NULL) { | 
|  | return osErrorParameter; | 
|  | } | 
|  |  | 
|  | if (k_is_in_isr()) { | 
|  | return osErrorISR; | 
|  | } | 
|  |  | 
|  | /* The status code "osErrorResource" (mutex specified by parameter | 
|  | * mutex_id is in an invalid mutex state) is not supported in Zephyr. | 
|  | */ | 
|  |  | 
|  | k_mem_slab_free(&cv2_mutex_slab, (void *) &mutex); | 
|  |  | 
|  | return osOK; | 
|  | } | 
|  |  | 
|  |  | 
|  | osThreadId_t osMutexGetOwner(osMutexId_t mutex_id) | 
|  | { | 
|  | struct cv2_mutex *mutex = (struct cv2_mutex *)mutex_id; | 
|  |  | 
|  | if (k_is_in_isr() || (mutex == NULL)) { | 
|  | return NULL; | 
|  | } | 
|  |  | 
|  | /* Mutex was not obtained before */ | 
|  | if (mutex->z_mutex.lock_count == 0) { | 
|  | return NULL; | 
|  | } | 
|  |  | 
|  | return get_cmsis_thread_id(mutex->z_mutex.owner); | 
|  | } | 
|  |  | 
|  | const char *osMutexGetName(osMutexId_t mutex_id) | 
|  | { | 
|  | struct cv2_mutex *mutex = (struct cv2_mutex *)mutex_id; | 
|  |  | 
|  | if (k_is_in_isr() || (mutex == NULL)) { | 
|  | return NULL; | 
|  | } | 
|  |  | 
|  | return mutex->name; | 
|  | } |