mirror of
https://github.com/DarkFlippers/unleashed-firmware
synced 2024-12-23 19:23:09 +00:00
839e52ac32
* Furi: remove CMSIS thread api, migrate to FuriThread, remove unused CMSIS APIs * Furi: magic thread catcher validating thread completion; backtrace improver * Furi: allow furi_thread_get_current_id outside of thread context * Furi: use IRQ instead of ISR for core primitives
217 lines
5.4 KiB
C
217 lines
5.4 KiB
C
#include "mutex.h"
|
|
#include "check.h"
|
|
#include "common_defines.h"
|
|
|
|
#include <semphr.h>
|
|
|
|
osMutexId_t osMutexNew(const osMutexAttr_t* attr) {
|
|
SemaphoreHandle_t hMutex;
|
|
uint32_t type;
|
|
uint32_t rmtx;
|
|
int32_t mem;
|
|
|
|
hMutex = NULL;
|
|
|
|
if(FURI_IS_IRQ_MODE() == 0U) {
|
|
if(attr != NULL) {
|
|
type = attr->attr_bits;
|
|
} else {
|
|
type = 0U;
|
|
}
|
|
|
|
if((type & osMutexRecursive) == osMutexRecursive) {
|
|
rmtx = 1U;
|
|
} else {
|
|
rmtx = 0U;
|
|
}
|
|
|
|
if((type & osMutexRobust) != osMutexRobust) {
|
|
mem = -1;
|
|
|
|
if(attr != NULL) {
|
|
if((attr->cb_mem != NULL) && (attr->cb_size >= sizeof(StaticSemaphore_t))) {
|
|
/* The memory for control block is provided, use static object */
|
|
mem = 1;
|
|
} else {
|
|
if((attr->cb_mem == NULL) && (attr->cb_size == 0U)) {
|
|
/* Control block will be allocated from the dynamic pool */
|
|
mem = 0;
|
|
}
|
|
}
|
|
} else {
|
|
mem = 0;
|
|
}
|
|
|
|
if(mem == 1) {
|
|
#if(configSUPPORT_STATIC_ALLOCATION == 1)
|
|
if(rmtx != 0U) {
|
|
#if(configUSE_RECURSIVE_MUTEXES == 1)
|
|
hMutex = xSemaphoreCreateRecursiveMutexStatic(attr->cb_mem);
|
|
#endif
|
|
} else {
|
|
hMutex = xSemaphoreCreateMutexStatic(attr->cb_mem);
|
|
}
|
|
#endif
|
|
} else {
|
|
if(mem == 0) {
|
|
#if(configSUPPORT_DYNAMIC_ALLOCATION == 1)
|
|
if(rmtx != 0U) {
|
|
#if(configUSE_RECURSIVE_MUTEXES == 1)
|
|
hMutex = xSemaphoreCreateRecursiveMutex();
|
|
#endif
|
|
} else {
|
|
hMutex = xSemaphoreCreateMutex();
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
|
|
#if(configQUEUE_REGISTRY_SIZE > 0)
|
|
if(hMutex != NULL) {
|
|
if((attr != NULL) && (attr->name != NULL)) {
|
|
/* Only non-NULL name objects are added to the Queue Registry */
|
|
vQueueAddToRegistry(hMutex, attr->name);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
if((hMutex != NULL) && (rmtx != 0U)) {
|
|
/* Set LSB as 'recursive mutex flag' */
|
|
hMutex = (SemaphoreHandle_t)((uint32_t)hMutex | 1U);
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Return mutex ID */
|
|
return ((osMutexId_t)hMutex);
|
|
}
|
|
|
|
/*
|
|
Acquire a Mutex or timeout if it is locked.
|
|
*/
|
|
osStatus_t osMutexAcquire(osMutexId_t mutex_id, uint32_t timeout) {
|
|
SemaphoreHandle_t hMutex;
|
|
osStatus_t stat;
|
|
uint32_t rmtx;
|
|
|
|
hMutex = (SemaphoreHandle_t)((uint32_t)mutex_id & ~1U);
|
|
|
|
/* Extract recursive mutex flag */
|
|
rmtx = (uint32_t)mutex_id & 1U;
|
|
|
|
stat = osOK;
|
|
|
|
if(FURI_IS_IRQ_MODE() != 0U) {
|
|
stat = osErrorISR;
|
|
} else if(hMutex == NULL) {
|
|
stat = osErrorParameter;
|
|
} else {
|
|
if(rmtx != 0U) {
|
|
#if(configUSE_RECURSIVE_MUTEXES == 1)
|
|
if(xSemaphoreTakeRecursive(hMutex, timeout) != pdPASS) {
|
|
if(timeout != 0U) {
|
|
stat = osErrorTimeout;
|
|
} else {
|
|
stat = osErrorResource;
|
|
}
|
|
}
|
|
#endif
|
|
} else {
|
|
if(xSemaphoreTake(hMutex, timeout) != pdPASS) {
|
|
if(timeout != 0U) {
|
|
stat = osErrorTimeout;
|
|
} else {
|
|
stat = osErrorResource;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Return execution status */
|
|
return (stat);
|
|
}
|
|
|
|
/*
|
|
Release a Mutex that was acquired by osMutexAcquire.
|
|
*/
|
|
osStatus_t osMutexRelease(osMutexId_t mutex_id) {
|
|
SemaphoreHandle_t hMutex;
|
|
osStatus_t stat;
|
|
uint32_t rmtx;
|
|
|
|
hMutex = (SemaphoreHandle_t)((uint32_t)mutex_id & ~1U);
|
|
|
|
/* Extract recursive mutex flag */
|
|
rmtx = (uint32_t)mutex_id & 1U;
|
|
|
|
stat = osOK;
|
|
|
|
if(FURI_IS_IRQ_MODE() != 0U) {
|
|
stat = osErrorISR;
|
|
} else if(hMutex == NULL) {
|
|
stat = osErrorParameter;
|
|
} else {
|
|
if(rmtx != 0U) {
|
|
#if(configUSE_RECURSIVE_MUTEXES == 1)
|
|
if(xSemaphoreGiveRecursive(hMutex) != pdPASS) {
|
|
stat = osErrorResource;
|
|
}
|
|
#endif
|
|
} else {
|
|
if(xSemaphoreGive(hMutex) != pdPASS) {
|
|
stat = osErrorResource;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Return execution status */
|
|
return (stat);
|
|
}
|
|
|
|
/*
|
|
Get Thread which owns a Mutex object.
|
|
*/
|
|
FuriThreadId osMutexGetOwner(osMutexId_t mutex_id) {
|
|
SemaphoreHandle_t hMutex;
|
|
FuriThreadId owner;
|
|
|
|
hMutex = (SemaphoreHandle_t)((uint32_t)mutex_id & ~1U);
|
|
|
|
if((FURI_IS_IRQ_MODE() != 0U) || (hMutex == NULL)) {
|
|
owner = 0;
|
|
} else {
|
|
owner = (FuriThreadId)xSemaphoreGetMutexHolder(hMutex);
|
|
}
|
|
|
|
/* Return owner thread ID */
|
|
return (owner);
|
|
}
|
|
|
|
/*
|
|
Delete a Mutex object.
|
|
*/
|
|
osStatus_t osMutexDelete(osMutexId_t mutex_id) {
|
|
osStatus_t stat;
|
|
#ifndef USE_FreeRTOS_HEAP_1
|
|
SemaphoreHandle_t hMutex;
|
|
|
|
hMutex = (SemaphoreHandle_t)((uint32_t)mutex_id & ~1U);
|
|
|
|
if(FURI_IS_IRQ_MODE() != 0U) {
|
|
stat = osErrorISR;
|
|
} else if(hMutex == NULL) {
|
|
stat = osErrorParameter;
|
|
} else {
|
|
#if(configQUEUE_REGISTRY_SIZE > 0)
|
|
vQueueUnregisterQueue(hMutex);
|
|
#endif
|
|
stat = osOK;
|
|
vSemaphoreDelete(hMutex);
|
|
}
|
|
#else
|
|
stat = osError;
|
|
#endif
|
|
|
|
/* Return execution status */
|
|
return (stat);
|
|
}
|