use crate::config::*;
use crate::kernel::list::*;
use crate::kernel::tasks::*;
#[cfg(any(feature = "alloc", feature = "heap-4", feature = "heap-5"))]
use crate::memory::{pvPortMalloc, vPortFree};
use crate::port::*;
use crate::trace::*;
use crate::types::*;
use core::ffi::c_void;
use core::ptr;
const queueUNLOCKED: i8 = -1;
const queueLOCKED_UNMODIFIED: i8 = 0;
const queueINT8_MAX: i8 = 127;
pub const queueSEND_TO_BACK: BaseType_t = 0;
pub const queueSEND_TO_FRONT: BaseType_t = 1;
pub const queueOVERWRITE: BaseType_t = 2;
pub const queueQUEUE_TYPE_BASE: u8 = 0;
pub const queueQUEUE_TYPE_MUTEX: u8 = 1;
pub const queueQUEUE_TYPE_COUNTING_SEMAPHORE: u8 = 2;
pub const queueQUEUE_TYPE_BINARY_SEMAPHORE: u8 = 3;
pub const queueQUEUE_TYPE_RECURSIVE_MUTEX: u8 = 4;
pub const queueQUEUE_TYPE_SET: u8 = 5;
const queueSEMAPHORE_QUEUE_ITEM_LENGTH: UBaseType_t = 0;
const queueMUTEX_GIVE_BLOCK_TIME: TickType_t = 0;
#[repr(C)]
#[derive(Clone, Copy)]
pub struct QueuePointers_t {
pub pcTail: *mut i8,
pub pcReadFrom: *mut i8,
}
#[repr(C)]
#[derive(Clone, Copy)]
pub struct SemaphoreData_t {
pub xMutexHolder: TaskHandle_t,
pub uxRecursiveCallCount: UBaseType_t,
}
#[repr(C)]
#[derive(Clone, Copy)]
pub union QueueUnion_t {
pub xQueue: QueuePointers_t,
pub xSemaphore: SemaphoreData_t,
}
#[repr(C)]
pub struct xQUEUE {
pub pcHead: *mut i8,
pub pcWriteTo: *mut i8,
pub u: QueueUnion_t,
pub xTasksWaitingToSend: List_t,
pub xTasksWaitingToReceive: List_t,
pub uxMessagesWaiting: UBaseType_t,
pub uxLength: UBaseType_t,
pub uxItemSize: UBaseType_t,
pub cRxLock: i8,
pub cTxLock: i8,
#[cfg(any(feature = "alloc", feature = "heap-4", feature = "heap-5"))]
pub ucStaticallyAllocated: u8,
#[cfg(feature = "queue-sets")]
pub pxQueueSetContainer: *mut xQUEUE,
#[cfg(feature = "trace-facility")]
pub uxQueueNumber: UBaseType_t,
#[cfg(feature = "trace-facility")]
pub ucQueueType: u8,
}
pub type Queue_t = xQUEUE;
pub type QueueHandle_t = *mut Queue_t;
#[cfg(feature = "queue-sets")]
pub type QueueSetHandle_t = *mut Queue_t;
#[cfg(feature = "queue-sets")]
pub type QueueSetMemberHandle_t = *mut Queue_t;
#[repr(C)]
pub struct StaticQueue_t {
_data: xQUEUE,
}
impl StaticQueue_t {
pub const fn new() -> Self {
StaticQueue_t {
_data: xQUEUE {
pcHead: core::ptr::null_mut(),
pcWriteTo: core::ptr::null_mut(),
u: QueueUnion_t {
xQueue: QueuePointers_t {
pcTail: core::ptr::null_mut(),
pcReadFrom: core::ptr::null_mut(),
},
},
xTasksWaitingToSend: List_t::new(),
xTasksWaitingToReceive: List_t::new(),
uxMessagesWaiting: 0,
uxLength: 0,
uxItemSize: 0,
cRxLock: 0,
cTxLock: 0,
#[cfg(any(feature = "alloc", feature = "heap-4", feature = "heap-5"))]
ucStaticallyAllocated: 0,
#[cfg(feature = "queue-sets")]
pxQueueSetContainer: core::ptr::null_mut(),
#[cfg(feature = "trace-facility")]
uxQueueNumber: 0,
#[cfg(feature = "trace-facility")]
ucQueueType: 0,
},
}
}
}
#[inline(always)]
fn mtCOVERAGE_TEST_DELAY() {}
#[inline(always)]
fn mtCOVERAGE_TEST_MARKER() {}
#[inline(always)]
unsafe fn queueYIELD_IF_USING_PREEMPTION() {
if configUSE_PREEMPTION != 0 {
portYIELD_WITHIN_API();
}
}
#[inline(always)]
unsafe fn prvLockQueue(pxQueue: *mut Queue_t) {
taskENTER_CRITICAL();
{
if (*pxQueue).cRxLock == queueUNLOCKED {
(*pxQueue).cRxLock = queueLOCKED_UNMODIFIED;
}
if (*pxQueue).cTxLock == queueUNLOCKED {
(*pxQueue).cTxLock = queueLOCKED_UNMODIFIED;
}
}
taskEXIT_CRITICAL();
}
#[inline(always)]
unsafe fn prvIncrementQueueTxLock(pxQueue: *mut Queue_t, cTxLock: i8) {
let uxNumberOfTasks = uxTaskGetNumberOfTasks();
if (cTxLock as UBaseType_t) < uxNumberOfTasks {
configASSERT(cTxLock != queueINT8_MAX);
(*pxQueue).cTxLock = cTxLock + 1;
}
}
#[inline(always)]
unsafe fn prvIncrementQueueRxLock(pxQueue: *mut Queue_t, cRxLock: i8) {
let uxNumberOfTasks = uxTaskGetNumberOfTasks();
if (cRxLock as UBaseType_t) < uxNumberOfTasks {
configASSERT(cRxLock != queueINT8_MAX);
(*pxQueue).cRxLock = cRxLock + 1;
}
}
pub unsafe fn xQueueGenericReset(xQueue: QueueHandle_t, xNewQueue: BaseType_t) -> BaseType_t {
let mut xReturn: BaseType_t = pdPASS;
let pxQueue: *mut Queue_t = xQueue;
traceENTER_xQueueGenericReset(pxQueue as *mut c_void, xNewQueue);
configASSERT(!pxQueue.is_null());
if !pxQueue.is_null()
&& (*pxQueue).uxLength >= 1
&& (usize::MAX / (*pxQueue).uxLength as usize) >= (*pxQueue).uxItemSize as usize
{
taskENTER_CRITICAL();
{
(*pxQueue).u.xQueue.pcTail = (*pxQueue)
.pcHead
.add(((*pxQueue).uxLength * (*pxQueue).uxItemSize) as usize);
(*pxQueue).uxMessagesWaiting = 0;
(*pxQueue).pcWriteTo = (*pxQueue).pcHead;
(*pxQueue).u.xQueue.pcReadFrom = (*pxQueue)
.pcHead
.add((((*pxQueue).uxLength - 1) * (*pxQueue).uxItemSize) as usize);
(*pxQueue).cRxLock = queueUNLOCKED;
(*pxQueue).cTxLock = queueUNLOCKED;
if xNewQueue == pdFALSE {
if listLIST_IS_EMPTY(ptr::addr_of!((*pxQueue).xTasksWaitingToSend)) == pdFALSE {
if xTaskRemoveFromEventList(ptr::addr_of!((*pxQueue).xTasksWaitingToSend))
!= pdFALSE
{
queueYIELD_IF_USING_PREEMPTION();
} else {
mtCOVERAGE_TEST_MARKER();
}
} else {
mtCOVERAGE_TEST_MARKER();
}
} else {
vListInitialise(ptr::addr_of_mut!((*pxQueue).xTasksWaitingToSend));
vListInitialise(ptr::addr_of_mut!((*pxQueue).xTasksWaitingToReceive));
}
}
taskEXIT_CRITICAL();
} else {
xReturn = pdFAIL;
}
configASSERT(xReturn != pdFAIL);
traceRETURN_xQueueGenericReset(xReturn);
xReturn
}
unsafe fn prvInitialiseNewQueue(
uxQueueLength: UBaseType_t,
uxItemSize: UBaseType_t,
pucQueueStorage: *mut u8,
#[allow(unused_variables)] ucQueueType: u8,
pxNewQueue: *mut Queue_t,
) {
if uxItemSize == 0 {
(*pxNewQueue).pcHead = pxNewQueue as *mut i8;
} else {
(*pxNewQueue).pcHead = pucQueueStorage as *mut i8;
}
(*pxNewQueue).uxLength = uxQueueLength;
(*pxNewQueue).uxItemSize = uxItemSize;
xQueueGenericReset(pxNewQueue, pdTRUE);
#[cfg(feature = "trace-facility")]
{
(*pxNewQueue).ucQueueType = ucQueueType;
}
#[cfg(feature = "queue-sets")]
{
(*pxNewQueue).pxQueueSetContainer = ptr::null_mut();
}
traceQUEUE_CREATE(pxNewQueue as *mut c_void);
}
pub unsafe fn xQueueGenericCreateStatic(
uxQueueLength: UBaseType_t,
uxItemSize: UBaseType_t,
pucQueueStorage: *mut u8,
pxStaticQueue: *mut StaticQueue_t,
ucQueueType: u8,
) -> QueueHandle_t {
let mut pxNewQueue: *mut Queue_t = ptr::null_mut();
traceENTER_xQueueGenericCreateStatic(
uxQueueLength,
uxItemSize,
pucQueueStorage as *mut c_void,
pxStaticQueue as *mut c_void,
ucQueueType,
);
configASSERT(!pxStaticQueue.is_null());
if uxQueueLength > 0
&& !pxStaticQueue.is_null()
&& !((!pucQueueStorage.is_null()) && (uxItemSize == 0))
&& !((pucQueueStorage.is_null()) && (uxItemSize != 0))
{
pxNewQueue = pxStaticQueue as *mut Queue_t;
#[cfg(any(feature = "alloc", feature = "heap-4", feature = "heap-5"))]
{
(*pxNewQueue).ucStaticallyAllocated = pdTRUE as u8;
}
prvInitialiseNewQueue(
uxQueueLength,
uxItemSize,
pucQueueStorage,
ucQueueType,
pxNewQueue,
);
} else {
configASSERT(!pxNewQueue.is_null());
mtCOVERAGE_TEST_MARKER();
}
traceRETURN_xQueueGenericCreateStatic(pxNewQueue as *mut c_void);
pxNewQueue
}
pub unsafe fn xQueueGenericGetStaticBuffers(
xQueue: QueueHandle_t,
ppucQueueStorage: *mut *mut u8,
ppxStaticQueue: *mut *mut StaticQueue_t,
) -> BaseType_t {
let xReturn: BaseType_t;
let pxQueue = xQueue as *const Queue_t;
traceENTER_xQueueGenericGetStaticBuffers(
xQueue,
ppucQueueStorage as *mut c_void,
ppxStaticQueue as *mut c_void,
);
configASSERT(!pxQueue.is_null());
configASSERT(!ppxStaticQueue.is_null());
#[cfg(any(feature = "alloc", feature = "heap-4", feature = "heap-5"))]
{
if (*pxQueue).ucStaticallyAllocated == pdTRUE as u8 {
if !ppucQueueStorage.is_null() {
*ppucQueueStorage = (*pxQueue).pcHead as *mut u8;
}
*ppxStaticQueue = pxQueue as *mut StaticQueue_t;
xReturn = pdTRUE;
} else {
xReturn = pdFALSE;
}
}
#[cfg(not(any(feature = "alloc", feature = "heap-4", feature = "heap-5")))]
{
if !ppucQueueStorage.is_null() {
*ppucQueueStorage = (*pxQueue).pcHead as *mut u8;
}
*ppxStaticQueue = pxQueue as *mut StaticQueue_t;
xReturn = pdTRUE;
}
traceRETURN_xQueueGenericGetStaticBuffers(xReturn);
xReturn
}
#[cfg(any(feature = "alloc", feature = "heap-4", feature = "heap-5"))]
pub unsafe fn xQueueGenericCreate(
uxQueueLength: UBaseType_t,
uxItemSize: UBaseType_t,
ucQueueType: u8,
) -> QueueHandle_t {
let mut pxNewQueue: *mut Queue_t = ptr::null_mut();
traceENTER_xQueueGenericCreate(uxQueueLength, uxItemSize, ucQueueType);
if uxQueueLength > 0
&& (usize::MAX / uxQueueLength as usize) >= uxItemSize as usize
&& (usize::MAX - core::mem::size_of::<Queue_t>())
>= (uxQueueLength as usize * uxItemSize as usize)
{
let xQueueSizeInBytes: usize = uxQueueLength as usize * uxItemSize as usize;
pxNewQueue =
pvPortMalloc(core::mem::size_of::<Queue_t>() + xQueueSizeInBytes) as *mut Queue_t;
if !pxNewQueue.is_null() {
let pucQueueStorage: *mut u8 =
(pxNewQueue as *mut u8).add(core::mem::size_of::<Queue_t>());
(*pxNewQueue).ucStaticallyAllocated = pdFALSE as u8;
prvInitialiseNewQueue(
uxQueueLength,
uxItemSize,
pucQueueStorage,
ucQueueType,
pxNewQueue,
);
} else {
traceQUEUE_CREATE_FAILED(ucQueueType);
mtCOVERAGE_TEST_MARKER();
}
} else {
configASSERT(!pxNewQueue.is_null());
mtCOVERAGE_TEST_MARKER();
}
traceRETURN_xQueueGenericCreate(pxNewQueue as *mut c_void);
pxNewQueue
}
#[cfg(any(feature = "alloc", feature = "heap-4", feature = "heap-5"))]
#[inline(always)]
pub unsafe fn xQueueCreate(uxQueueLength: UBaseType_t, uxItemSize: UBaseType_t) -> QueueHandle_t {
xQueueGenericCreate(uxQueueLength, uxItemSize, queueQUEUE_TYPE_BASE)
}
#[inline(always)]
pub unsafe fn xQueueCreateStatic(
uxQueueLength: UBaseType_t,
uxItemSize: UBaseType_t,
pucQueueStorage: *mut u8,
pxQueueBuffer: *mut StaticQueue_t,
) -> QueueHandle_t {
xQueueGenericCreateStatic(
uxQueueLength,
uxItemSize,
pucQueueStorage,
pxQueueBuffer,
queueQUEUE_TYPE_BASE,
)
}
unsafe fn prvCopyDataToQueue(
pxQueue: *mut Queue_t,
pvItemToQueue: *const c_void,
xPosition: BaseType_t,
) -> BaseType_t {
#[allow(unused_mut)] let mut xReturn: BaseType_t = pdFALSE;
let uxMessagesWaiting: UBaseType_t = (*pxQueue).uxMessagesWaiting;
if (*pxQueue).uxItemSize == 0 {
#[cfg(feature = "use-mutexes")]
{
if (*pxQueue).pcHead.is_null() {
xReturn = unsafe { xTaskPriorityDisinherit((*pxQueue).u.xSemaphore.xMutexHolder) };
(*pxQueue).u.xSemaphore.xMutexHolder = ptr::null_mut();
} else {
mtCOVERAGE_TEST_MARKER();
}
}
} else if xPosition == queueSEND_TO_BACK {
ptr::copy_nonoverlapping(
pvItemToQueue as *const u8,
(*pxQueue).pcWriteTo as *mut u8,
(*pxQueue).uxItemSize as usize,
);
(*pxQueue).pcWriteTo = (*pxQueue).pcWriteTo.add((*pxQueue).uxItemSize as usize);
if (*pxQueue).pcWriteTo >= (*pxQueue).u.xQueue.pcTail {
(*pxQueue).pcWriteTo = (*pxQueue).pcHead;
} else {
mtCOVERAGE_TEST_MARKER();
}
} else {
ptr::copy_nonoverlapping(
pvItemToQueue as *const u8,
(*pxQueue).u.xQueue.pcReadFrom as *mut u8,
(*pxQueue).uxItemSize as usize,
);
if (*pxQueue).u.xQueue.pcReadFrom == (*pxQueue).pcHead {
(*pxQueue).u.xQueue.pcReadFrom = (*pxQueue).u.xQueue.pcTail;
}
(*pxQueue).u.xQueue.pcReadFrom = (*pxQueue)
.u
.xQueue
.pcReadFrom
.sub((*pxQueue).uxItemSize as usize);
if xPosition == queueOVERWRITE {
if uxMessagesWaiting > 0 {
(*pxQueue).uxMessagesWaiting = uxMessagesWaiting - 1;
} else {
mtCOVERAGE_TEST_MARKER();
}
} else {
mtCOVERAGE_TEST_MARKER();
}
}
(*pxQueue).uxMessagesWaiting = (*pxQueue).uxMessagesWaiting + 1;
xReturn
}
unsafe fn prvCopyDataFromQueue(pxQueue: *mut Queue_t, pvBuffer: *mut c_void) {
if (*pxQueue).uxItemSize != 0 {
(*pxQueue).u.xQueue.pcReadFrom = (*pxQueue)
.u
.xQueue
.pcReadFrom
.add((*pxQueue).uxItemSize as usize);
if (*pxQueue).u.xQueue.pcReadFrom >= (*pxQueue).u.xQueue.pcTail {
(*pxQueue).u.xQueue.pcReadFrom = (*pxQueue).pcHead;
} else {
mtCOVERAGE_TEST_MARKER();
}
ptr::copy_nonoverlapping(
(*pxQueue).u.xQueue.pcReadFrom as *const u8,
pvBuffer as *mut u8,
(*pxQueue).uxItemSize as usize,
);
}
}
unsafe fn prvIsQueueEmpty(pxQueue: *const Queue_t) -> BaseType_t {
let xReturn: BaseType_t;
taskENTER_CRITICAL();
{
if (*pxQueue).uxMessagesWaiting == 0 {
xReturn = pdTRUE;
} else {
xReturn = pdFALSE;
}
}
taskEXIT_CRITICAL();
xReturn
}
unsafe fn prvIsQueueFull(pxQueue: *const Queue_t) -> BaseType_t {
let xReturn: BaseType_t;
taskENTER_CRITICAL();
{
if (*pxQueue).uxMessagesWaiting == (*pxQueue).uxLength {
xReturn = pdTRUE;
} else {
xReturn = pdFALSE;
}
}
taskEXIT_CRITICAL();
xReturn
}
pub unsafe fn xQueueGenericSend(
xQueue: QueueHandle_t,
pvItemToQueue: *const c_void,
mut xTicksToWait: TickType_t,
xCopyPosition: BaseType_t,
) -> BaseType_t {
let mut xEntryTimeSet: BaseType_t = pdFALSE;
let xYieldRequired: BaseType_t;
let mut xTimeOut = TimeOut_t::new();
let pxQueue: *mut Queue_t = xQueue;
traceENTER_xQueueGenericSend(
pxQueue as *mut c_void,
pvItemToQueue,
xTicksToWait,
xCopyPosition,
);
configASSERT(!pxQueue.is_null());
configASSERT(!(pvItemToQueue.is_null() && (*pxQueue).uxItemSize != 0));
configASSERT(!(xCopyPosition == queueOVERWRITE && (*pxQueue).uxLength != 1));
configASSERT(!(xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED && xTicksToWait != 0));
loop {
taskENTER_CRITICAL();
{
if (*pxQueue).uxMessagesWaiting < (*pxQueue).uxLength || xCopyPosition == queueOVERWRITE
{
traceQUEUE_SEND(pxQueue as *mut c_void);
#[cfg(feature = "queue-sets")]
let uxPreviousMessagesWaiting = (*pxQueue).uxMessagesWaiting;
xYieldRequired = prvCopyDataToQueue(pxQueue, pvItemToQueue, xCopyPosition);
#[cfg(feature = "queue-sets")]
{
if !(*pxQueue).pxQueueSetContainer.is_null() {
if xCopyPosition == queueOVERWRITE && uxPreviousMessagesWaiting != 0 {
mtCOVERAGE_TEST_MARKER();
} else if prvNotifyQueueSetContainer(pxQueue) != pdFALSE {
queueYIELD_IF_USING_PREEMPTION();
}
} else {
if listLIST_IS_EMPTY(ptr::addr_of!((*pxQueue).xTasksWaitingToReceive))
== pdFALSE
{
if xTaskRemoveFromEventList(ptr::addr_of!(
(*pxQueue).xTasksWaitingToReceive
)) != pdFALSE
{
queueYIELD_IF_USING_PREEMPTION();
}
} else if xYieldRequired != pdFALSE {
queueYIELD_IF_USING_PREEMPTION();
}
}
}
#[cfg(not(feature = "queue-sets"))]
{
if listLIST_IS_EMPTY(ptr::addr_of!((*pxQueue).xTasksWaitingToReceive))
== pdFALSE
{
if xTaskRemoveFromEventList(ptr::addr_of!(
(*pxQueue).xTasksWaitingToReceive
)) != pdFALSE
{
queueYIELD_IF_USING_PREEMPTION();
} else {
mtCOVERAGE_TEST_MARKER();
}
} else if xYieldRequired != pdFALSE {
queueYIELD_IF_USING_PREEMPTION();
} else {
mtCOVERAGE_TEST_MARKER();
}
}
taskEXIT_CRITICAL();
traceRETURN_xQueueGenericSend(pdPASS);
return pdPASS;
} else {
if xTicksToWait == 0 {
taskEXIT_CRITICAL();
traceQUEUE_SEND_FAILED(pxQueue as *mut c_void);
traceRETURN_xQueueGenericSend(errQUEUE_FULL);
return errQUEUE_FULL;
} else if xEntryTimeSet == pdFALSE {
unsafe { vTaskInternalSetTimeOutState(&mut xTimeOut) };
xEntryTimeSet = pdTRUE;
} else {
mtCOVERAGE_TEST_MARKER();
}
}
}
taskEXIT_CRITICAL();
vTaskSuspendAll();
prvLockQueue(pxQueue);
if unsafe { xTaskCheckForTimeOut(&mut xTimeOut, &mut xTicksToWait) } == pdFALSE {
if prvIsQueueFull(pxQueue) != pdFALSE {
traceBLOCKING_ON_QUEUE_SEND(pxQueue as *mut c_void);
vTaskPlaceOnEventList(
ptr::addr_of_mut!((*pxQueue).xTasksWaitingToSend),
xTicksToWait,
);
prvUnlockQueue(pxQueue);
if xTaskResumeAll() == pdFALSE {
portYIELD_WITHIN_API();
}
} else {
prvUnlockQueue(pxQueue);
xTaskResumeAll();
}
} else {
prvUnlockQueue(pxQueue);
xTaskResumeAll();
traceQUEUE_SEND_FAILED(pxQueue as *mut c_void);
traceRETURN_xQueueGenericSend(errQUEUE_FULL);
return errQUEUE_FULL;
}
}
}
pub unsafe fn xQueueReceive(
xQueue: QueueHandle_t,
pvBuffer: *mut c_void,
mut xTicksToWait: TickType_t,
) -> BaseType_t {
let mut xEntryTimeSet: BaseType_t = pdFALSE;
let mut xTimeOut = TimeOut_t::new();
let pxQueue: *mut Queue_t = xQueue;
traceENTER_xQueueReceive(pxQueue as *mut c_void, pvBuffer, xTicksToWait);
configASSERT(!pxQueue.is_null());
configASSERT(!(pvBuffer.is_null() && (*pxQueue).uxItemSize != 0));
configASSERT(!(xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED && xTicksToWait != 0));
loop {
taskENTER_CRITICAL();
{
let uxMessagesWaiting = (*pxQueue).uxMessagesWaiting;
if uxMessagesWaiting > 0 {
prvCopyDataFromQueue(pxQueue, pvBuffer);
traceQUEUE_RECEIVE(pxQueue as *mut c_void);
(*pxQueue).uxMessagesWaiting = uxMessagesWaiting - 1;
if listLIST_IS_EMPTY(ptr::addr_of!((*pxQueue).xTasksWaitingToSend)) == pdFALSE {
if xTaskRemoveFromEventList(ptr::addr_of!((*pxQueue).xTasksWaitingToSend))
!= pdFALSE
{
queueYIELD_IF_USING_PREEMPTION();
} else {
mtCOVERAGE_TEST_MARKER();
}
} else {
mtCOVERAGE_TEST_MARKER();
}
taskEXIT_CRITICAL();
traceRETURN_xQueueReceive(pdPASS);
return pdPASS;
} else {
if xTicksToWait == 0 {
taskEXIT_CRITICAL();
traceQUEUE_RECEIVE_FAILED(pxQueue as *mut c_void);
traceRETURN_xQueueReceive(errQUEUE_EMPTY);
return errQUEUE_EMPTY;
} else if xEntryTimeSet == pdFALSE {
unsafe { vTaskInternalSetTimeOutState(&mut xTimeOut) };
xEntryTimeSet = pdTRUE;
} else {
mtCOVERAGE_TEST_MARKER();
}
}
}
taskEXIT_CRITICAL();
vTaskSuspendAll();
prvLockQueue(pxQueue);
if unsafe { xTaskCheckForTimeOut(&mut xTimeOut, &mut xTicksToWait) } == pdFALSE {
if prvIsQueueEmpty(pxQueue) != pdFALSE {
traceBLOCKING_ON_QUEUE_RECEIVE(pxQueue as *mut c_void);
vTaskPlaceOnEventList(
ptr::addr_of_mut!((*pxQueue).xTasksWaitingToReceive),
xTicksToWait,
);
prvUnlockQueue(pxQueue);
if xTaskResumeAll() == pdFALSE {
portYIELD_WITHIN_API();
}
} else {
prvUnlockQueue(pxQueue);
xTaskResumeAll();
}
} else {
prvUnlockQueue(pxQueue);
xTaskResumeAll();
if prvIsQueueEmpty(pxQueue) != pdFALSE {
traceQUEUE_RECEIVE_FAILED(pxQueue as *mut c_void);
traceRETURN_xQueueReceive(errQUEUE_EMPTY);
return errQUEUE_EMPTY;
}
}
}
}
pub unsafe fn xQueuePeek(
xQueue: QueueHandle_t,
pvBuffer: *mut c_void,
mut xTicksToWait: TickType_t,
) -> BaseType_t {
let mut xEntryTimeSet: BaseType_t = pdFALSE;
let mut xTimeOut = TimeOut_t::new();
let pxQueue: *mut Queue_t = xQueue;
traceENTER_xQueuePeek(pxQueue as *mut c_void, pvBuffer, xTicksToWait);
configASSERT(!pxQueue.is_null());
configASSERT(!(pvBuffer.is_null() && (*pxQueue).uxItemSize != 0));
configASSERT(!(xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED && xTicksToWait != 0));
loop {
taskENTER_CRITICAL();
{
let uxMessagesWaiting = (*pxQueue).uxMessagesWaiting;
if uxMessagesWaiting > 0 {
let pcOriginalReadPosition = (*pxQueue).u.xQueue.pcReadFrom;
prvCopyDataFromQueue(pxQueue, pvBuffer);
(*pxQueue).u.xQueue.pcReadFrom = pcOriginalReadPosition;
traceQUEUE_PEEK(pxQueue as *mut c_void);
if listLIST_IS_EMPTY(ptr::addr_of!((*pxQueue).xTasksWaitingToReceive)) == pdFALSE {
if xTaskRemoveFromEventList(ptr::addr_of!((*pxQueue).xTasksWaitingToReceive))
!= pdFALSE
{
queueYIELD_IF_USING_PREEMPTION();
}
}
taskEXIT_CRITICAL();
traceRETURN_xQueuePeek(pdPASS);
return pdPASS;
} else {
if xTicksToWait == 0 {
taskEXIT_CRITICAL();
traceQUEUE_PEEK_FAILED(pxQueue as *mut c_void);
traceRETURN_xQueuePeek(errQUEUE_EMPTY);
return errQUEUE_EMPTY;
} else if xEntryTimeSet == pdFALSE {
unsafe { vTaskInternalSetTimeOutState(&mut xTimeOut) };
xEntryTimeSet = pdTRUE;
}
}
}
taskEXIT_CRITICAL();
vTaskSuspendAll();
prvLockQueue(pxQueue);
if unsafe { xTaskCheckForTimeOut(&mut xTimeOut, &mut xTicksToWait) } == pdFALSE {
if prvIsQueueEmpty(pxQueue) != pdFALSE {
traceBLOCKING_ON_QUEUE_PEEK(pxQueue as *mut c_void);
vTaskPlaceOnEventList(
ptr::addr_of_mut!((*pxQueue).xTasksWaitingToReceive),
xTicksToWait,
);
prvUnlockQueue(pxQueue);
if xTaskResumeAll() == pdFALSE {
portYIELD_WITHIN_API();
}
} else {
prvUnlockQueue(pxQueue);
xTaskResumeAll();
}
} else {
prvUnlockQueue(pxQueue);
xTaskResumeAll();
if prvIsQueueEmpty(pxQueue) != pdFALSE {
traceQUEUE_PEEK_FAILED(pxQueue as *mut c_void);
traceRETURN_xQueuePeek(errQUEUE_EMPTY);
return errQUEUE_EMPTY;
}
}
}
}
pub unsafe fn xQueueReceiveFromISR(
xQueue: QueueHandle_t,
pvBuffer: *mut c_void,
pxHigherPriorityTaskWoken: *mut BaseType_t,
) -> BaseType_t {
let xReturn: BaseType_t;
let pxQueue = xQueue as *mut Queue_t;
traceENTER_xQueueReceiveFromISR(xQueue, pvBuffer, pxHigherPriorityTaskWoken);
configASSERT(!pxQueue.is_null());
configASSERT(!(pvBuffer.is_null() && (*pxQueue).uxItemSize != 0));
let uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
{
let uxMessagesWaiting = (*pxQueue).uxMessagesWaiting;
if uxMessagesWaiting > 0 {
let cRxLock = (*pxQueue).cRxLock;
traceQUEUE_RECEIVE_FROM_ISR(pxQueue as *mut c_void);
prvCopyDataFromQueue(pxQueue, pvBuffer);
(*pxQueue).uxMessagesWaiting = uxMessagesWaiting - 1;
if cRxLock == queueUNLOCKED {
if listLIST_IS_EMPTY(ptr::addr_of!((*pxQueue).xTasksWaitingToSend)) == pdFALSE {
if xTaskRemoveFromEventList(ptr::addr_of!((*pxQueue).xTasksWaitingToSend))
!= pdFALSE
{
if !pxHigherPriorityTaskWoken.is_null() {
*pxHigherPriorityTaskWoken = pdTRUE;
}
}
}
} else {
prvIncrementQueueRxLock(pxQueue, cRxLock);
}
xReturn = pdPASS;
} else {
traceQUEUE_RECEIVE_FROM_ISR_FAILED(pxQueue as *mut c_void);
xReturn = pdFAIL;
}
}
portCLEAR_INTERRUPT_MASK_FROM_ISR(uxSavedInterruptStatus);
traceRETURN_xQueueReceiveFromISR(xReturn);
xReturn
}
pub unsafe fn xQueuePeekFromISR(xQueue: QueueHandle_t, pvBuffer: *mut c_void) -> BaseType_t {
let xReturn: BaseType_t;
let pxQueue = xQueue as *mut Queue_t;
traceENTER_xQueuePeekFromISR(xQueue, pvBuffer);
configASSERT(!pxQueue.is_null());
configASSERT(!pvBuffer.is_null());
configASSERT((*pxQueue).uxItemSize != 0);
let uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
{
if (*pxQueue).uxMessagesWaiting > 0 {
traceQUEUE_PEEK_FROM_ISR(pxQueue as *mut c_void);
let pcOriginalReadPosition = (*pxQueue).u.xQueue.pcReadFrom;
prvCopyDataFromQueue(pxQueue, pvBuffer);
(*pxQueue).u.xQueue.pcReadFrom = pcOriginalReadPosition;
xReturn = pdPASS;
} else {
traceQUEUE_PEEK_FROM_ISR_FAILED(pxQueue as *mut c_void);
xReturn = pdFAIL;
}
}
portCLEAR_INTERRUPT_MASK_FROM_ISR(uxSavedInterruptStatus);
traceRETURN_xQueuePeekFromISR(xReturn);
xReturn
}
unsafe fn prvUnlockQueue(pxQueue: *mut Queue_t) {
taskENTER_CRITICAL();
{
let mut cTxLock: i8 = (*pxQueue).cTxLock;
while cTxLock > queueLOCKED_UNMODIFIED {
#[cfg(feature = "queue-sets")]
{
if !(*pxQueue).pxQueueSetContainer.is_null() {
if prvNotifyQueueSetContainer(pxQueue) != pdFALSE {
vTaskMissedYield();
}
} else if listLIST_IS_EMPTY(ptr::addr_of!((*pxQueue).xTasksWaitingToReceive))
== pdFALSE
{
if xTaskRemoveFromEventList(ptr::addr_of!((*pxQueue).xTasksWaitingToReceive))
!= pdFALSE
{
vTaskMissedYield();
}
} else {
break;
}
}
#[cfg(not(feature = "queue-sets"))]
{
if listLIST_IS_EMPTY(ptr::addr_of!((*pxQueue).xTasksWaitingToReceive)) == pdFALSE {
if xTaskRemoveFromEventList(ptr::addr_of!((*pxQueue).xTasksWaitingToReceive))
!= pdFALSE
{
vTaskMissedYield();
}
} else {
break;
}
}
cTxLock -= 1;
}
(*pxQueue).cTxLock = queueUNLOCKED;
}
taskEXIT_CRITICAL();
taskENTER_CRITICAL();
{
let mut cRxLock: i8 = (*pxQueue).cRxLock;
while cRxLock > queueLOCKED_UNMODIFIED {
if listLIST_IS_EMPTY(ptr::addr_of!((*pxQueue).xTasksWaitingToSend)) == pdFALSE {
if xTaskRemoveFromEventList(ptr::addr_of!((*pxQueue).xTasksWaitingToSend))
!= pdFALSE
{
vTaskMissedYield();
}
cRxLock -= 1;
} else {
break;
}
}
(*pxQueue).cRxLock = queueUNLOCKED;
}
taskEXIT_CRITICAL();
}
pub unsafe fn uxQueueMessagesWaiting(xQueue: QueueHandle_t) -> UBaseType_t {
let uxReturn: UBaseType_t;
configASSERT(!xQueue.is_null());
taskENTER_CRITICAL();
{
uxReturn = (*xQueue).uxMessagesWaiting;
}
taskEXIT_CRITICAL();
uxReturn
}
pub unsafe fn uxQueueSpacesAvailable(xQueue: QueueHandle_t) -> UBaseType_t {
let uxReturn: UBaseType_t;
configASSERT(!xQueue.is_null());
taskENTER_CRITICAL();
{
uxReturn = (*xQueue).uxLength - (*xQueue).uxMessagesWaiting;
}
taskEXIT_CRITICAL();
uxReturn
}
pub unsafe fn uxQueueMessagesWaitingFromISR(xQueue: QueueHandle_t) -> UBaseType_t {
let uxReturn: UBaseType_t;
traceENTER_uxQueueMessagesWaitingFromISR(xQueue);
configASSERT(!xQueue.is_null());
uxReturn = (*xQueue).uxMessagesWaiting;
traceRETURN_uxQueueMessagesWaitingFromISR(uxReturn);
uxReturn
}
pub unsafe fn vQueueDelete(xQueue: QueueHandle_t) {
let pxQueue = xQueue as *mut Queue_t;
traceENTER_vQueueDelete(xQueue);
configASSERT(!pxQueue.is_null());
traceQUEUE_DELETE(pxQueue as *mut c_void);
#[cfg(feature = "queue-registry")]
{
vQueueUnregisterQueue(xQueue);
}
#[cfg(any(feature = "alloc", feature = "heap-4", feature = "heap-5"))]
{
if (*pxQueue).ucStaticallyAllocated == pdFALSE as u8 {
vPortFree(pxQueue as *mut c_void);
} else {
mtCOVERAGE_TEST_MARKER();
}
}
traceRETURN_vQueueDelete();
}
pub unsafe fn uxQueueGetQueueItemSize(xQueue: QueueHandle_t) -> UBaseType_t {
configASSERT(!xQueue.is_null());
(*xQueue).uxItemSize
}
pub unsafe fn uxQueueGetQueueLength(xQueue: QueueHandle_t) -> UBaseType_t {
configASSERT(!xQueue.is_null());
(*xQueue).uxLength
}
pub unsafe fn xQueueIsQueueEmptyFromISR(xQueue: QueueHandle_t) -> BaseType_t {
let xReturn: BaseType_t;
traceENTER_xQueueIsQueueEmptyFromISR(xQueue);
configASSERT(!xQueue.is_null());
if (*xQueue).uxMessagesWaiting == 0 {
xReturn = pdTRUE;
} else {
xReturn = pdFALSE;
}
traceRETURN_xQueueIsQueueEmptyFromISR(xReturn);
xReturn
}
pub unsafe fn xQueueIsQueueFullFromISR(xQueue: QueueHandle_t) -> BaseType_t {
let xReturn: BaseType_t;
traceENTER_xQueueIsQueueFullFromISR(xQueue);
configASSERT(!xQueue.is_null());
if (*xQueue).uxMessagesWaiting == (*xQueue).uxLength {
xReturn = pdTRUE;
} else {
xReturn = pdFALSE;
}
traceRETURN_xQueueIsQueueFullFromISR(xReturn);
xReturn
}
#[cfg(feature = "trace-facility")]
pub unsafe fn uxQueueGetQueueNumber(xQueue: QueueHandle_t) -> UBaseType_t {
traceENTER_uxQueueGetQueueNumber(xQueue);
let uxReturn = (*xQueue).uxQueueNumber;
traceRETURN_uxQueueGetQueueNumber(uxReturn);
uxReturn
}
#[cfg(feature = "trace-facility")]
pub unsafe fn vQueueSetQueueNumber(xQueue: QueueHandle_t, uxQueueNumber: UBaseType_t) {
traceENTER_vQueueSetQueueNumber(xQueue, uxQueueNumber);
(*xQueue).uxQueueNumber = uxQueueNumber;
traceRETURN_vQueueSetQueueNumber();
}
#[cfg(feature = "trace-facility")]
pub unsafe fn ucQueueGetQueueType(xQueue: QueueHandle_t) -> u8 {
traceENTER_ucQueueGetQueueType(xQueue);
let ucReturn = (*xQueue).ucQueueType;
traceRETURN_ucQueueGetQueueType(ucReturn);
ucReturn
}
#[inline(always)]
fn traceENTER_xQueueGenericReset(_pxQueue: *mut c_void, _xNewQueue: BaseType_t) {}
#[inline(always)]
fn traceRETURN_xQueueGenericReset(_xReturn: BaseType_t) {}
#[inline(always)]
fn traceENTER_xQueueGenericCreateStatic(
_uxQueueLength: UBaseType_t,
_uxItemSize: UBaseType_t,
_pucQueueStorage: *mut c_void,
_pxStaticQueue: *mut c_void,
_ucQueueType: u8,
) {
}
#[inline(always)]
fn traceRETURN_xQueueGenericCreateStatic(_pxNewQueue: *mut c_void) {}
#[inline(always)]
fn traceENTER_xQueueGenericGetStaticBuffers(
_xQueue: QueueHandle_t,
_ppucQueueStorage: *mut c_void,
_ppxStaticQueue: *mut c_void,
) {
}
#[inline(always)]
fn traceRETURN_xQueueGenericGetStaticBuffers(_xReturn: BaseType_t) {}
#[inline(always)]
fn traceENTER_xQueueGenericCreate(
_uxQueueLength: UBaseType_t,
_uxItemSize: UBaseType_t,
_ucQueueType: u8,
) {
}
#[inline(always)]
fn traceRETURN_xQueueGenericCreate(_pxNewQueue: *mut c_void) {}
#[inline(always)]
fn traceENTER_xQueueGenericSend(
_pxQueue: *mut c_void,
_pvItemToQueue: *const c_void,
_xTicksToWait: TickType_t,
_xCopyPosition: BaseType_t,
) {
}
#[inline(always)]
fn traceRETURN_xQueueGenericSend(_xReturn: BaseType_t) {}
#[inline(always)]
fn traceENTER_xQueueReceive(
_pxQueue: *mut c_void,
_pvBuffer: *mut c_void,
_xTicksToWait: TickType_t,
) {
}
#[inline(always)]
fn traceRETURN_xQueueReceive(_xReturn: BaseType_t) {}
#[cfg(feature = "use-mutexes")]
#[inline(always)]
fn traceENTER_xQueueCreateMutexStatic(_ucQueueType: u8, _pxStaticQueue: *mut StaticQueue_t) {}
#[cfg(feature = "use-mutexes")]
#[inline(always)]
fn traceRETURN_xQueueCreateMutexStatic(_xNewQueue: QueueHandle_t) {}
#[cfg(feature = "use-mutexes")]
#[inline(always)]
fn traceENTER_xQueueCreateMutex(_ucQueueType: u8) {}
#[cfg(feature = "use-mutexes")]
#[inline(always)]
fn traceRETURN_xQueueCreateMutex(_xNewQueue: QueueHandle_t) {}
#[cfg(feature = "use-mutexes")]
#[inline(always)]
fn traceCREATE_MUTEX(_pxNewQueue: *mut c_void) {}
#[cfg(feature = "use-mutexes")]
#[inline(always)]
fn traceCREATE_MUTEX_FAILED() {}
#[cfg(feature = "use-mutexes")]
#[inline(always)]
fn traceENTER_xQueueGetMutexHolder(_xSemaphore: QueueHandle_t) {}
#[cfg(feature = "use-mutexes")]
#[inline(always)]
fn traceRETURN_xQueueGetMutexHolder(_pxReturn: TaskHandle_t) {}
#[cfg(feature = "use-mutexes")]
#[inline(always)]
fn traceENTER_xQueueGetMutexHolderFromISR(_xSemaphore: QueueHandle_t) {}
#[cfg(feature = "use-mutexes")]
#[inline(always)]
fn traceRETURN_xQueueGetMutexHolderFromISR(_pxReturn: TaskHandle_t) {}
#[cfg(feature = "use-mutexes")]
#[inline(always)]
fn traceENTER_xQueueGiveMutexRecursive(_xMutex: QueueHandle_t) {}
#[cfg(feature = "use-mutexes")]
#[inline(always)]
fn traceRETURN_xQueueGiveMutexRecursive(_xReturn: BaseType_t) {}
#[cfg(feature = "use-mutexes")]
#[inline(always)]
fn traceGIVE_MUTEX_RECURSIVE(_pxMutex: *mut c_void) {}
#[cfg(feature = "use-mutexes")]
#[inline(always)]
fn traceGIVE_MUTEX_RECURSIVE_FAILED(_pxMutex: *mut c_void) {}
#[cfg(feature = "use-mutexes")]
#[inline(always)]
fn traceENTER_xQueueTakeMutexRecursive(_xMutex: QueueHandle_t, _xTicksToWait: TickType_t) {}
#[cfg(feature = "use-mutexes")]
#[inline(always)]
fn traceRETURN_xQueueTakeMutexRecursive(_xReturn: BaseType_t) {}
#[cfg(feature = "use-mutexes")]
#[inline(always)]
fn traceTAKE_MUTEX_RECURSIVE(_pxMutex: *mut c_void) {}
#[cfg(feature = "use-mutexes")]
#[inline(always)]
fn traceTAKE_MUTEX_RECURSIVE_FAILED(_pxMutex: *mut c_void) {}
#[cfg(any(feature = "alloc", feature = "heap-4", feature = "heap-5"))]
#[inline(always)]
fn traceENTER_xQueueCreateCountingSemaphore(
_uxMaxCount: UBaseType_t,
_uxInitialCount: UBaseType_t,
) {
}
#[cfg(any(feature = "alloc", feature = "heap-4", feature = "heap-5"))]
#[inline(always)]
fn traceRETURN_xQueueCreateCountingSemaphore(_xHandle: QueueHandle_t) {}
#[inline(always)]
fn traceENTER_xQueueCreateCountingSemaphoreStatic(
_uxMaxCount: UBaseType_t,
_uxInitialCount: UBaseType_t,
_pxStaticQueue: *mut StaticQueue_t,
) {
}
#[inline(always)]
fn traceRETURN_xQueueCreateCountingSemaphoreStatic(_xHandle: QueueHandle_t) {}
#[inline(always)]
fn traceCREATE_COUNTING_SEMAPHORE() {}
#[inline(always)]
fn traceCREATE_COUNTING_SEMAPHORE_FAILED() {}
#[inline(always)]
fn traceENTER_xQueueGiveFromISR(
_xQueue: QueueHandle_t,
_pxHigherPriorityTaskWoken: *mut BaseType_t,
) {
}
#[inline(always)]
fn traceRETURN_xQueueGiveFromISR(_xReturn: BaseType_t) {}
#[inline(always)]
fn traceQUEUE_SEND_FROM_ISR(_pxQueue: *mut c_void) {}
#[inline(always)]
fn traceQUEUE_SEND_FROM_ISR_FAILED(_pxQueue: *mut c_void) {}
#[inline(always)]
fn traceENTER_xQueuePeek(_pxQueue: *mut c_void, _pvBuffer: *mut c_void, _xTicksToWait: TickType_t) {
}
#[inline(always)]
fn traceRETURN_xQueuePeek(_xReturn: BaseType_t) {}
#[inline(always)]
fn traceQUEUE_PEEK(_pxQueue: *mut c_void) {}
#[inline(always)]
fn traceQUEUE_PEEK_FAILED(_pxQueue: *mut c_void) {}
#[inline(always)]
fn traceBLOCKING_ON_QUEUE_PEEK(_pxQueue: *mut c_void) {}
#[inline(always)]
fn traceENTER_xQueueReceiveFromISR(
_xQueue: QueueHandle_t,
_pvBuffer: *mut c_void,
_pxHigherPriorityTaskWoken: *mut BaseType_t,
) {
}
#[inline(always)]
fn traceRETURN_xQueueReceiveFromISR(_xReturn: BaseType_t) {}
#[inline(always)]
fn traceQUEUE_RECEIVE_FROM_ISR(_pxQueue: *mut c_void) {}
#[inline(always)]
fn traceQUEUE_RECEIVE_FROM_ISR_FAILED(_pxQueue: *mut c_void) {}
#[inline(always)]
fn traceENTER_xQueuePeekFromISR(_xQueue: QueueHandle_t, _pvBuffer: *mut c_void) {}
#[inline(always)]
fn traceRETURN_xQueuePeekFromISR(_xReturn: BaseType_t) {}
#[inline(always)]
fn traceQUEUE_PEEK_FROM_ISR(_pxQueue: *mut c_void) {}
#[inline(always)]
fn traceQUEUE_PEEK_FROM_ISR_FAILED(_pxQueue: *mut c_void) {}
#[inline(always)]
fn traceENTER_uxQueueMessagesWaitingFromISR(_xQueue: QueueHandle_t) {}
#[inline(always)]
fn traceRETURN_uxQueueMessagesWaitingFromISR(_uxReturn: UBaseType_t) {}
#[inline(always)]
fn traceENTER_vQueueDelete(_xQueue: QueueHandle_t) {}
#[inline(always)]
fn traceRETURN_vQueueDelete() {}
#[inline(always)]
fn traceQUEUE_DELETE(_pxQueue: *mut c_void) {}
#[inline(always)]
fn traceENTER_xQueueIsQueueEmptyFromISR(_xQueue: QueueHandle_t) {}
#[inline(always)]
fn traceRETURN_xQueueIsQueueEmptyFromISR(_xReturn: BaseType_t) {}
#[inline(always)]
fn traceENTER_xQueueIsQueueFullFromISR(_xQueue: QueueHandle_t) {}
#[inline(always)]
fn traceRETURN_xQueueIsQueueFullFromISR(_xReturn: BaseType_t) {}
#[cfg(feature = "trace-facility")]
#[inline(always)]
fn traceENTER_uxQueueGetQueueNumber(_xQueue: QueueHandle_t) {}
#[cfg(feature = "trace-facility")]
#[inline(always)]
fn traceRETURN_uxQueueGetQueueNumber(_uxReturn: UBaseType_t) {}
#[cfg(feature = "trace-facility")]
#[inline(always)]
fn traceENTER_vQueueSetQueueNumber(_xQueue: QueueHandle_t, _uxQueueNumber: UBaseType_t) {}
#[cfg(feature = "trace-facility")]
#[inline(always)]
fn traceRETURN_vQueueSetQueueNumber() {}
#[cfg(feature = "trace-facility")]
#[inline(always)]
fn traceENTER_ucQueueGetQueueType(_xQueue: QueueHandle_t) {}
#[cfg(feature = "trace-facility")]
#[inline(always)]
fn traceRETURN_ucQueueGetQueueType(_ucReturn: u8) {}
#[inline(always)]
pub unsafe fn xQueueSendToBack(
xQueue: QueueHandle_t,
pvItemToQueue: *const c_void,
xTicksToWait: TickType_t,
) -> BaseType_t {
xQueueGenericSend(xQueue, pvItemToQueue, xTicksToWait, queueSEND_TO_BACK)
}
#[inline(always)]
pub unsafe fn xQueueSendToFront(
xQueue: QueueHandle_t,
pvItemToQueue: *const c_void,
xTicksToWait: TickType_t,
) -> BaseType_t {
xQueueGenericSend(xQueue, pvItemToQueue, xTicksToWait, queueSEND_TO_FRONT)
}
#[inline(always)]
pub unsafe fn xQueueSend(
xQueue: QueueHandle_t,
pvItemToQueue: *const c_void,
xTicksToWait: TickType_t,
) -> BaseType_t {
xQueueSendToBack(xQueue, pvItemToQueue, xTicksToWait)
}
#[inline(always)]
pub unsafe fn xQueueOverwrite(xQueue: QueueHandle_t, pvItemToQueue: *const c_void) -> BaseType_t {
xQueueGenericSend(xQueue, pvItemToQueue, 0, queueOVERWRITE)
}
#[inline(always)]
pub unsafe fn xQueueSendToBackFromISR(
xQueue: QueueHandle_t,
pvItemToQueue: *const c_void,
pxHigherPriorityTaskWoken: *mut BaseType_t,
) -> BaseType_t {
xQueueGenericSendFromISR(
xQueue,
pvItemToQueue,
pxHigherPriorityTaskWoken,
queueSEND_TO_BACK,
)
}
#[inline(always)]
pub unsafe fn xQueueSendToFrontFromISR(
xQueue: QueueHandle_t,
pvItemToQueue: *const c_void,
pxHigherPriorityTaskWoken: *mut BaseType_t,
) -> BaseType_t {
xQueueGenericSendFromISR(
xQueue,
pvItemToQueue,
pxHigherPriorityTaskWoken,
queueSEND_TO_FRONT,
)
}
#[inline(always)]
pub unsafe fn xQueueOverwriteFromISR(
xQueue: QueueHandle_t,
pvItemToQueue: *const c_void,
pxHigherPriorityTaskWoken: *mut BaseType_t,
) -> BaseType_t {
xQueueGenericSendFromISR(
xQueue,
pvItemToQueue,
pxHigherPriorityTaskWoken,
queueOVERWRITE,
)
}
#[inline(always)]
pub unsafe fn xQueueSendFromISR(
xQueue: QueueHandle_t,
pvItemToQueue: *const c_void,
pxHigherPriorityTaskWoken: *mut BaseType_t,
) -> BaseType_t {
xQueueSendToBackFromISR(xQueue, pvItemToQueue, pxHigherPriorityTaskWoken)
}
#[allow(unused_assignments)] pub unsafe fn xQueueGenericSendFromISR(
xQueue: QueueHandle_t,
pvItemToQueue: *const c_void,
pxHigherPriorityTaskWoken: *mut BaseType_t,
xCopyPosition: BaseType_t,
) -> BaseType_t {
let mut xReturn: BaseType_t = pdFAIL;
let pxQueue = xQueue as *mut Queue_t;
configASSERT(!pxQueue.is_null());
configASSERT(!(pvItemToQueue.is_null() && (*pxQueue).uxItemSize != 0));
configASSERT(!(xCopyPosition == queueOVERWRITE && (*pxQueue).uxLength != 1));
let uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
{
if (*pxQueue).uxMessagesWaiting < (*pxQueue).uxLength || xCopyPosition == queueOVERWRITE {
let cTxLock = (*pxQueue).cTxLock;
#[cfg(feature = "queue-sets")]
let uxPreviousMessagesWaiting = (*pxQueue).uxMessagesWaiting;
traceQUEUE_SEND_FROM_ISR(pxQueue as *mut c_void);
prvCopyDataToQueue(pxQueue, pvItemToQueue, xCopyPosition);
#[cfg(feature = "queue-sets")]
{
if cTxLock == queueUNLOCKED && !(*pxQueue).pxQueueSetContainer.is_null() {
if xCopyPosition == queueOVERWRITE && uxPreviousMessagesWaiting != 0 {
mtCOVERAGE_TEST_MARKER();
} else if prvNotifyQueueSetContainer(pxQueue) != pdFALSE {
if !pxHigherPriorityTaskWoken.is_null() {
*pxHigherPriorityTaskWoken = pdTRUE;
}
}
} else if (*pxQueue).pxQueueSetContainer.is_null() {
if cTxLock == queueUNLOCKED {
if listLIST_IS_EMPTY(ptr::addr_of!((*pxQueue).xTasksWaitingToReceive))
== pdFALSE
{
if xTaskRemoveFromEventList(ptr::addr_of!(
(*pxQueue).xTasksWaitingToReceive
)) != pdFALSE
{
if !pxHigherPriorityTaskWoken.is_null() {
*pxHigherPriorityTaskWoken = pdTRUE;
}
}
}
} else {
prvIncrementQueueTxLock(pxQueue, cTxLock);
}
} else {
prvIncrementQueueTxLock(pxQueue, cTxLock);
}
}
#[cfg(not(feature = "queue-sets"))]
{
if cTxLock == queueUNLOCKED {
if listLIST_IS_EMPTY(ptr::addr_of!((*pxQueue).xTasksWaitingToReceive))
== pdFALSE
{
if xTaskRemoveFromEventList(ptr::addr_of!(
(*pxQueue).xTasksWaitingToReceive
)) != pdFALSE
{
if !pxHigherPriorityTaskWoken.is_null() {
*pxHigherPriorityTaskWoken = pdTRUE;
}
}
}
} else {
prvIncrementQueueTxLock(pxQueue, cTxLock);
}
}
xReturn = pdPASS;
} else {
traceQUEUE_SEND_FROM_ISR_FAILED(pxQueue as *mut c_void);
xReturn = errQUEUE_FULL;
}
}
portCLEAR_INTERRUPT_MASK_FROM_ISR(uxSavedInterruptStatus);
xReturn
}
pub unsafe fn xQueueGiveFromISR(
xQueue: QueueHandle_t,
pxHigherPriorityTaskWoken: *mut BaseType_t,
) -> BaseType_t {
let xReturn: BaseType_t;
let pxQueue = xQueue as *mut Queue_t;
traceENTER_xQueueGiveFromISR(xQueue, pxHigherPriorityTaskWoken);
configASSERT(!pxQueue.is_null());
configASSERT((*pxQueue).uxItemSize == 0);
configASSERT(!(*pxQueue).pcHead.is_null() || (*pxQueue).u.xSemaphore.xMutexHolder.is_null());
let uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
{
let uxMessagesWaiting = (*pxQueue).uxMessagesWaiting;
if uxMessagesWaiting < (*pxQueue).uxLength {
let cTxLock = (*pxQueue).cTxLock;
traceQUEUE_SEND_FROM_ISR(pxQueue as *mut c_void);
(*pxQueue).uxMessagesWaiting = uxMessagesWaiting + 1;
#[cfg(feature = "queue-sets")]
{
if cTxLock == queueUNLOCKED {
if !(*pxQueue).pxQueueSetContainer.is_null() {
if prvNotifyQueueSetContainer(pxQueue) != pdFALSE {
if !pxHigherPriorityTaskWoken.is_null() {
*pxHigherPriorityTaskWoken = pdTRUE;
}
}
} else {
if listLIST_IS_EMPTY(ptr::addr_of!((*pxQueue).xTasksWaitingToReceive))
== pdFALSE
{
if xTaskRemoveFromEventList(ptr::addr_of!(
(*pxQueue).xTasksWaitingToReceive
)) != pdFALSE
{
if !pxHigherPriorityTaskWoken.is_null() {
*pxHigherPriorityTaskWoken = pdTRUE;
}
}
}
}
} else {
prvIncrementQueueTxLock(pxQueue, cTxLock);
}
}
#[cfg(not(feature = "queue-sets"))]
{
if cTxLock == queueUNLOCKED {
if listLIST_IS_EMPTY(ptr::addr_of!((*pxQueue).xTasksWaitingToReceive))
== pdFALSE
{
if xTaskRemoveFromEventList(ptr::addr_of!(
(*pxQueue).xTasksWaitingToReceive
)) != pdFALSE
{
if !pxHigherPriorityTaskWoken.is_null() {
*pxHigherPriorityTaskWoken = pdTRUE;
}
}
}
} else {
prvIncrementQueueTxLock(pxQueue, cTxLock);
}
}
xReturn = pdPASS;
} else {
traceQUEUE_SEND_FROM_ISR_FAILED(pxQueue as *mut c_void);
xReturn = errQUEUE_FULL;
}
}
portCLEAR_INTERRUPT_MASK_FROM_ISR(uxSavedInterruptStatus);
traceRETURN_xQueueGiveFromISR(xReturn);
xReturn
}
#[cfg(feature = "timers")]
pub unsafe fn vQueueWaitForMessageRestricted(
xQueue: QueueHandle_t,
xTicksToWait: TickType_t,
xWaitIndefinitely: BaseType_t,
) {
let pxQueue = xQueue as *mut Queue_t;
prvLockQueue(pxQueue);
if (*pxQueue).uxMessagesWaiting == 0 {
vTaskPlaceOnEventListRestricted(
ptr::addr_of_mut!((*pxQueue).xTasksWaitingToReceive),
xTicksToWait,
xWaitIndefinitely,
);
}
prvUnlockQueue(pxQueue);
}
#[cfg(all(
any(feature = "alloc", feature = "heap-4", feature = "heap-5"),
feature = "use-mutexes"
))]
pub unsafe fn xQueueCreateMutex(ucQueueType: u8) -> QueueHandle_t {
traceENTER_xQueueCreateMutex(ucQueueType);
let xNewQueue = xQueueGenericCreate(1, 0, ucQueueType);
prvInitialiseMutex(xNewQueue as *mut Queue_t);
traceRETURN_xQueueCreateMutex(xNewQueue);
xNewQueue
}
#[cfg(feature = "use-mutexes")]
pub unsafe fn xQueueCreateMutexStatic(
ucQueueType: u8,
pxStaticQueue: *mut StaticQueue_t,
) -> QueueHandle_t {
traceENTER_xQueueCreateMutexStatic(ucQueueType, pxStaticQueue);
let xNewQueue = xQueueGenericCreateStatic(1, 0, ptr::null_mut(), pxStaticQueue, ucQueueType);
prvInitialiseMutex(xNewQueue as *mut Queue_t);
traceRETURN_xQueueCreateMutexStatic(xNewQueue);
xNewQueue
}
#[cfg(feature = "use-mutexes")]
unsafe fn prvInitialiseMutex(pxNewQueue: *mut Queue_t) {
if !pxNewQueue.is_null() {
(*pxNewQueue).u.xSemaphore.xMutexHolder = ptr::null_mut();
(*pxNewQueue).u.xSemaphore.uxRecursiveCallCount = 0;
(*pxNewQueue).pcHead = ptr::null_mut();
traceCREATE_MUTEX(pxNewQueue as *mut c_void);
xQueueGenericSend(
pxNewQueue as QueueHandle_t,
ptr::null(),
0,
queueSEND_TO_BACK,
);
} else {
traceCREATE_MUTEX_FAILED();
}
}
#[cfg(feature = "use-mutexes")]
pub unsafe fn xQueueGetMutexHolder(xSemaphore: QueueHandle_t) -> TaskHandle_t {
let mut pxReturn: TaskHandle_t = ptr::null_mut();
let pxSemaphore = xSemaphore as *mut Queue_t;
traceENTER_xQueueGetMutexHolder(xSemaphore);
configASSERT(!xSemaphore.is_null());
taskENTER_CRITICAL();
{
if (*pxSemaphore).pcHead.is_null() {
pxReturn = (*pxSemaphore).u.xSemaphore.xMutexHolder;
}
}
taskEXIT_CRITICAL();
traceRETURN_xQueueGetMutexHolder(pxReturn);
pxReturn
}
#[cfg(feature = "use-mutexes")]
pub unsafe fn xQueueGetMutexHolderFromISR(xSemaphore: QueueHandle_t) -> TaskHandle_t {
let pxReturn: TaskHandle_t;
traceENTER_xQueueGetMutexHolderFromISR(xSemaphore);
configASSERT(!xSemaphore.is_null());
if (*(xSemaphore as *mut Queue_t)).pcHead.is_null() {
pxReturn = (*(xSemaphore as *mut Queue_t)).u.xSemaphore.xMutexHolder;
} else {
pxReturn = ptr::null_mut();
}
traceRETURN_xQueueGetMutexHolderFromISR(pxReturn);
pxReturn
}
#[cfg(feature = "use-mutexes")]
pub unsafe fn xQueueGiveMutexRecursive(xMutex: QueueHandle_t) -> BaseType_t {
let xReturn: BaseType_t;
let pxMutex = xMutex as *mut Queue_t;
traceENTER_xQueueGiveMutexRecursive(xMutex);
configASSERT(!pxMutex.is_null());
if (*pxMutex).u.xSemaphore.xMutexHolder == xTaskGetCurrentTaskHandle() {
traceGIVE_MUTEX_RECURSIVE(pxMutex as *mut c_void);
(*pxMutex).u.xSemaphore.uxRecursiveCallCount -= 1;
if (*pxMutex).u.xSemaphore.uxRecursiveCallCount == 0 {
xQueueGenericSend(pxMutex as QueueHandle_t, ptr::null(), 0, queueSEND_TO_BACK);
}
xReturn = pdPASS;
} else {
xReturn = pdFAIL;
traceGIVE_MUTEX_RECURSIVE_FAILED(pxMutex as *mut c_void);
}
traceRETURN_xQueueGiveMutexRecursive(xReturn);
xReturn
}
pub unsafe fn xQueueSemaphoreTake(
xQueue: QueueHandle_t,
mut xTicksToWait: TickType_t,
) -> BaseType_t {
let pxQueue = xQueue as *mut Queue_t;
let mut xEntryTimeSet = pdFALSE;
let mut xTimeOut = TimeOut_t::new();
#[cfg(feature = "use-mutexes")]
let mut xInheritanceOccurred = pdFALSE;
configASSERT(!pxQueue.is_null());
configASSERT((*pxQueue).uxItemSize == 0);
configASSERT(!(xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED && xTicksToWait != 0));
loop {
taskENTER_CRITICAL();
{
let uxSemaphoreCount = (*pxQueue).uxMessagesWaiting;
if uxSemaphoreCount > 0 {
traceQUEUE_RECEIVE(pxQueue as *mut c_void);
(*pxQueue).uxMessagesWaiting = uxSemaphoreCount - 1;
#[cfg(feature = "use-mutexes")]
{
if (*pxQueue).pcHead.is_null() {
(*pxQueue).u.xSemaphore.xMutexHolder = pvTaskIncrementMutexHeldCount();
}
}
if listLIST_IS_EMPTY(ptr::addr_of!((*pxQueue).xTasksWaitingToSend)) == pdFALSE
&& xTaskRemoveFromEventList(ptr::addr_of!((*pxQueue).xTasksWaitingToSend))
!= pdFALSE
{
queueYIELD_IF_USING_PREEMPTION();
}
taskEXIT_CRITICAL();
return pdPASS;
}
if xTicksToWait == 0 {
taskEXIT_CRITICAL();
traceQUEUE_RECEIVE_FAILED(pxQueue as *mut c_void);
return errQUEUE_EMPTY;
} else if xEntryTimeSet == pdFALSE {
unsafe { vTaskInternalSetTimeOutState(&mut xTimeOut) };
xEntryTimeSet = pdTRUE;
}
}
taskEXIT_CRITICAL();
vTaskSuspendAll();
prvLockQueue(pxQueue);
if unsafe { xTaskCheckForTimeOut(&mut xTimeOut, &mut xTicksToWait) } == pdFALSE {
if prvIsQueueEmpty(pxQueue) != pdFALSE {
traceBLOCKING_ON_QUEUE_RECEIVE(pxQueue as *mut c_void);
#[cfg(feature = "use-mutexes")]
{
if (*pxQueue).pcHead.is_null() {
taskENTER_CRITICAL();
xInheritanceOccurred =
unsafe { xTaskPriorityInherit((*pxQueue).u.xSemaphore.xMutexHolder) };
taskEXIT_CRITICAL();
}
}
vTaskPlaceOnEventList(
ptr::addr_of_mut!((*pxQueue).xTasksWaitingToReceive),
xTicksToWait,
);
prvUnlockQueue(pxQueue);
if xTaskResumeAll() == pdFALSE {
portYIELD_WITHIN_API();
}
} else {
prvUnlockQueue(pxQueue);
xTaskResumeAll();
}
} else {
prvUnlockQueue(pxQueue);
xTaskResumeAll();
if prvIsQueueEmpty(pxQueue) != pdFALSE {
#[cfg(feature = "use-mutexes")]
{
if xInheritanceOccurred != pdFALSE {
taskENTER_CRITICAL();
let uxHighestWaitingPriority =
prvGetHighestPriorityOfWaitToReceiveList(pxQueue);
unsafe {
vTaskPriorityDisinheritAfterTimeout(
(*pxQueue).u.xSemaphore.xMutexHolder,
uxHighestWaitingPriority,
)
};
taskEXIT_CRITICAL();
}
}
traceQUEUE_RECEIVE_FAILED(pxQueue as *mut c_void);
return errQUEUE_EMPTY;
}
}
}
}
#[cfg(feature = "use-mutexes")]
unsafe fn prvGetHighestPriorityOfWaitToReceiveList(pxQueue: *const Queue_t) -> UBaseType_t {
if listCURRENT_LIST_LENGTH(ptr::addr_of!((*pxQueue).xTasksWaitingToReceive)) > 0 {
configMAX_PRIORITIES
- listGET_ITEM_VALUE_OF_HEAD_ENTRY(ptr::addr_of!((*pxQueue).xTasksWaitingToReceive))
as UBaseType_t
} else {
tskIDLE_PRIORITY
}
}
#[cfg(feature = "use-mutexes")]
pub unsafe fn xQueueTakeMutexRecursive(
xMutex: QueueHandle_t,
xTicksToWait: TickType_t,
) -> BaseType_t {
let xReturn: BaseType_t;
let pxMutex = xMutex as *mut Queue_t;
traceENTER_xQueueTakeMutexRecursive(xMutex, xTicksToWait);
configASSERT(!pxMutex.is_null());
let xCurrentTaskHandle = xTaskGetCurrentTaskHandle();
if (*pxMutex).u.xSemaphore.xMutexHolder == xCurrentTaskHandle {
(*pxMutex).u.xSemaphore.uxRecursiveCallCount =
(*pxMutex).u.xSemaphore.uxRecursiveCallCount.wrapping_add(1);
configASSERT((*pxMutex).u.xSemaphore.uxRecursiveCallCount != 0);
xReturn = pdPASS;
traceTAKE_MUTEX_RECURSIVE(pxMutex as *mut c_void);
} else {
xReturn = xQueueSemaphoreTake(xMutex, xTicksToWait);
if xReturn == pdPASS {
(*pxMutex).u.xSemaphore.uxRecursiveCallCount =
(*pxMutex).u.xSemaphore.uxRecursiveCallCount.wrapping_add(1);
configASSERT((*pxMutex).u.xSemaphore.uxRecursiveCallCount != 0);
traceTAKE_MUTEX_RECURSIVE(pxMutex as *mut c_void);
} else {
traceTAKE_MUTEX_RECURSIVE_FAILED(pxMutex as *mut c_void);
}
}
traceRETURN_xQueueTakeMutexRecursive(xReturn);
xReturn
}
#[cfg(any(feature = "alloc", feature = "heap-4", feature = "heap-5"))]
pub unsafe fn xQueueCreateCountingSemaphore(
uxMaxCount: UBaseType_t,
uxInitialCount: UBaseType_t,
) -> QueueHandle_t {
let xHandle: QueueHandle_t;
traceENTER_xQueueCreateCountingSemaphore(uxMaxCount, uxInitialCount);
configASSERT(uxMaxCount != 0);
configASSERT(uxInitialCount <= uxMaxCount);
xHandle = xQueueGenericCreate(
uxMaxCount,
queueSEMAPHORE_QUEUE_ITEM_LENGTH,
queueQUEUE_TYPE_COUNTING_SEMAPHORE,
);
if !xHandle.is_null() {
let pxQueue = xHandle as *mut Queue_t;
(*pxQueue).uxMessagesWaiting = uxInitialCount;
traceCREATE_COUNTING_SEMAPHORE();
} else {
traceCREATE_COUNTING_SEMAPHORE_FAILED();
}
traceRETURN_xQueueCreateCountingSemaphore(xHandle);
xHandle
}
pub unsafe fn xQueueCreateCountingSemaphoreStatic(
uxMaxCount: UBaseType_t,
uxInitialCount: UBaseType_t,
pxStaticQueue: *mut StaticQueue_t,
) -> QueueHandle_t {
let xHandle: QueueHandle_t;
traceENTER_xQueueCreateCountingSemaphoreStatic(uxMaxCount, uxInitialCount, pxStaticQueue);
configASSERT(uxMaxCount != 0);
configASSERT(uxInitialCount <= uxMaxCount);
xHandle = xQueueGenericCreateStatic(
uxMaxCount,
queueSEMAPHORE_QUEUE_ITEM_LENGTH,
ptr::null_mut(),
pxStaticQueue,
queueQUEUE_TYPE_COUNTING_SEMAPHORE,
);
if !xHandle.is_null() {
let pxQueue = xHandle as *mut Queue_t;
(*pxQueue).uxMessagesWaiting = uxInitialCount;
traceCREATE_COUNTING_SEMAPHORE();
} else {
traceCREATE_COUNTING_SEMAPHORE_FAILED();
}
traceRETURN_xQueueCreateCountingSemaphoreStatic(xHandle);
xHandle
}
#[cfg(feature = "queue-sets")]
unsafe fn prvNotifyQueueSetContainer(pxQueue: *const Queue_t) -> BaseType_t {
let pxQueueSetContainer = (*pxQueue).pxQueueSetContainer;
let mut xReturn: BaseType_t = pdFALSE;
configASSERT(!pxQueueSetContainer.is_null());
configASSERT((*pxQueueSetContainer).uxMessagesWaiting < (*pxQueueSetContainer).uxLength);
if (*pxQueueSetContainer).uxMessagesWaiting < (*pxQueueSetContainer).uxLength {
let cTxLock = (*pxQueueSetContainer).cTxLock;
traceQUEUE_SET_SEND(pxQueueSetContainer as *mut c_void);
xReturn = prvCopyDataToQueue(
pxQueueSetContainer,
&pxQueue as *const *const Queue_t as *const c_void,
queueSEND_TO_BACK,
);
if cTxLock == queueUNLOCKED {
if listLIST_IS_EMPTY(ptr::addr_of!((*pxQueueSetContainer).xTasksWaitingToReceive))
== pdFALSE
{
if xTaskRemoveFromEventList(ptr::addr_of!(
(*pxQueueSetContainer).xTasksWaitingToReceive
)) != pdFALSE
{
xReturn = pdTRUE;
}
}
} else {
prvIncrementQueueTxLock(pxQueueSetContainer, cTxLock);
}
}
xReturn
}
#[cfg(all(
feature = "queue-sets",
any(feature = "alloc", feature = "heap-4", feature = "heap-5")
))]
pub unsafe fn xQueueCreateSet(uxEventQueueLength: UBaseType_t) -> QueueSetHandle_t {
let pxQueue = xQueueGenericCreate(
uxEventQueueLength,
core::mem::size_of::<*mut Queue_t>() as UBaseType_t,
queueQUEUE_TYPE_SET,
);
pxQueue
}
#[cfg(feature = "queue-sets")]
pub unsafe fn xQueueCreateSetStatic(
uxEventQueueLength: UBaseType_t,
pucQueueStorage: *mut u8,
pxStaticQueue: *mut StaticQueue_t,
) -> QueueSetHandle_t {
let pxQueue = xQueueGenericCreateStatic(
uxEventQueueLength,
core::mem::size_of::<*mut Queue_t>() as UBaseType_t,
pucQueueStorage,
pxStaticQueue,
queueQUEUE_TYPE_SET,
);
pxQueue
}
#[cfg(feature = "queue-sets")]
pub unsafe fn xQueueAddToSet(
xQueueOrSemaphore: QueueSetMemberHandle_t,
xQueueSet: QueueSetHandle_t,
) -> BaseType_t {
let xReturn: BaseType_t;
taskENTER_CRITICAL();
{
if !(*xQueueOrSemaphore).pxQueueSetContainer.is_null() {
xReturn = pdFAIL;
} else if (*xQueueOrSemaphore).uxMessagesWaiting != 0 {
xReturn = pdFAIL;
} else {
(*xQueueOrSemaphore).pxQueueSetContainer = xQueueSet;
xReturn = pdPASS;
}
}
taskEXIT_CRITICAL();
xReturn
}
#[cfg(feature = "queue-sets")]
pub unsafe fn xQueueRemoveFromSet(
xQueueOrSemaphore: QueueSetMemberHandle_t,
xQueueSet: QueueSetHandle_t,
) -> BaseType_t {
let xReturn: BaseType_t;
if (*xQueueOrSemaphore).pxQueueSetContainer != xQueueSet {
xReturn = pdFAIL;
} else if (*xQueueOrSemaphore).uxMessagesWaiting != 0 {
xReturn = pdFAIL;
} else {
taskENTER_CRITICAL();
{
(*xQueueOrSemaphore).pxQueueSetContainer = ptr::null_mut();
}
taskEXIT_CRITICAL();
xReturn = pdPASS;
}
xReturn
}
#[cfg(feature = "queue-sets")]
pub unsafe fn xQueueSelectFromSet(
xQueueSet: QueueSetHandle_t,
xTicksToWait: TickType_t,
) -> QueueSetMemberHandle_t {
let mut xReturn: QueueSetMemberHandle_t = ptr::null_mut();
xQueueReceive(
xQueueSet,
&mut xReturn as *mut QueueSetMemberHandle_t as *mut c_void,
xTicksToWait,
);
xReturn
}
#[cfg(feature = "queue-sets")]
pub unsafe fn xQueueSelectFromSetFromISR(xQueueSet: QueueSetHandle_t) -> QueueSetMemberHandle_t {
let mut xReturn: QueueSetMemberHandle_t = ptr::null_mut();
let _ = xQueueReceiveFromISR(
xQueueSet,
&mut xReturn as *mut QueueSetMemberHandle_t as *mut c_void,
ptr::null_mut(),
);
xReturn
}
#[cfg(feature = "queue-sets")]
#[inline(always)]
fn traceQUEUE_SET_SEND(_pxQueue: *mut c_void) {}
#[cfg(feature = "queue-registry")]
mod queue_registry {
use super::*;
use crate::config::configQUEUE_REGISTRY_SIZE;
#[repr(C)]
struct QueueRegistryItem {
pcQueueName: *const u8,
xHandle: QueueHandle_t,
}
impl QueueRegistryItem {
const fn new() -> Self {
QueueRegistryItem {
pcQueueName: ptr::null(),
xHandle: ptr::null_mut(),
}
}
}
static mut QUEUE_REGISTRY: [QueueRegistryItem; configQUEUE_REGISTRY_SIZE] =
[const { QueueRegistryItem::new() }; configQUEUE_REGISTRY_SIZE];
pub unsafe fn vQueueAddToRegistry(xQueue: QueueHandle_t, pcQueueName: *const u8) {
traceENTER_vQueueAddToRegistry(xQueue, pcQueueName);
configASSERT(!xQueue.is_null());
if !pcQueueName.is_null() {
let mut pxEntryToWrite: Option<usize> = None;
for ux in 0..configQUEUE_REGISTRY_SIZE {
if xQueue == QUEUE_REGISTRY[ux].xHandle {
pxEntryToWrite = Some(ux);
break;
}
else if pxEntryToWrite.is_none() && QUEUE_REGISTRY[ux].pcQueueName.is_null() {
pxEntryToWrite = Some(ux);
}
}
if let Some(ux) = pxEntryToWrite {
QUEUE_REGISTRY[ux].pcQueueName = pcQueueName;
QUEUE_REGISTRY[ux].xHandle = xQueue;
traceQUEUE_REGISTRY_ADD(xQueue, pcQueueName);
}
}
traceRETURN_vQueueAddToRegistry();
}
pub unsafe fn pcQueueGetName(xQueue: QueueHandle_t) -> *const u8 {
traceENTER_pcQueueGetName(xQueue);
configASSERT(!xQueue.is_null());
let mut pcReturn: *const u8 = ptr::null();
for ux in 0..configQUEUE_REGISTRY_SIZE {
if QUEUE_REGISTRY[ux].xHandle == xQueue {
pcReturn = QUEUE_REGISTRY[ux].pcQueueName;
break;
}
}
traceRETURN_pcQueueGetName(pcReturn);
pcReturn
}
pub unsafe fn vQueueUnregisterQueue(xQueue: QueueHandle_t) {
traceENTER_vQueueUnregisterQueue(xQueue);
configASSERT(!xQueue.is_null());
for ux in 0..configQUEUE_REGISTRY_SIZE {
if QUEUE_REGISTRY[ux].xHandle == xQueue {
QUEUE_REGISTRY[ux].pcQueueName = ptr::null();
QUEUE_REGISTRY[ux].xHandle = ptr::null_mut();
break;
}
}
traceRETURN_vQueueUnregisterQueue();
}
#[inline(always)]
fn traceENTER_vQueueAddToRegistry(_xQueue: QueueHandle_t, _pcQueueName: *const u8) {}
#[inline(always)]
fn traceRETURN_vQueueAddToRegistry() {}
#[inline(always)]
fn traceQUEUE_REGISTRY_ADD(_xQueue: QueueHandle_t, _pcQueueName: *const u8) {}
#[inline(always)]
fn traceENTER_pcQueueGetName(_xQueue: QueueHandle_t) {}
#[inline(always)]
fn traceRETURN_pcQueueGetName(_pcReturn: *const u8) {}
#[inline(always)]
fn traceENTER_vQueueUnregisterQueue(_xQueue: QueueHandle_t) {}
#[inline(always)]
fn traceRETURN_vQueueUnregisterQueue() {}
}
#[cfg(feature = "queue-registry")]
pub use queue_registry::*;
#[cfg(all(test, feature = "port-test"))]
mod tests {
use super::*;
#[cfg(feature = "use-mutexes")]
use crate::kernel::tasks::{pxCurrentTCB, TCB_t};
#[test]
fn capacity_one_send_to_front_wraps_within_storage() {
let mut queue_buffer = StaticQueue_t::new();
let mut storage = [0u32; 1];
let queue = unsafe {
xQueueCreateStatic(
1,
core::mem::size_of::<u32>() as UBaseType_t,
storage.as_mut_ptr() as *mut u8,
&mut queue_buffer,
)
};
assert!(!queue.is_null());
let sent = 0x1234_5678u32;
assert_eq!(
unsafe {
xQueueGenericSend(
queue,
&sent as *const u32 as *const c_void,
0,
queueSEND_TO_FRONT,
)
},
pdPASS
);
let mut received = 0u32;
assert_eq!(
unsafe { xQueueReceive(queue, &mut received as *mut u32 as *mut c_void, 0,) },
pdPASS
);
assert_eq!(received, sent);
}
#[test]
fn capacity_one_overwrite_from_isr_replaces_existing_item() {
let mut queue_buffer = StaticQueue_t::new();
let mut storage = [0u32; 1];
let queue = unsafe {
xQueueCreateStatic(
1,
core::mem::size_of::<u32>() as UBaseType_t,
storage.as_mut_ptr() as *mut u8,
&mut queue_buffer,
)
};
assert!(!queue.is_null());
let first = 0x1111_1111u32;
let replacement = 0x2222_2222u32;
assert_eq!(
unsafe {
xQueueGenericSend(
queue,
&first as *const u32 as *const c_void,
0,
queueSEND_TO_BACK,
)
},
pdPASS
);
assert_eq!(
unsafe {
xQueueOverwriteFromISR(
queue,
&replacement as *const u32 as *const c_void,
ptr::null_mut(),
)
},
pdPASS
);
assert_eq!(unsafe { uxQueueMessagesWaiting(queue) }, 1);
let mut received = 0u32;
assert_eq!(
unsafe { xQueueReceive(queue, &mut received as *mut u32 as *mut c_void, 0,) },
pdPASS
);
assert_eq!(received, replacement);
}
#[cfg(feature = "queue-sets")]
#[test]
fn locked_queue_set_isr_paths_defer_events_and_cap_lock_counts() {
crate::port::test_port_reset();
let mut member_buffer = StaticQueue_t::new();
let mut set_buffer = StaticQueue_t::new();
let mut set_storage = [ptr::null_mut::<Queue_t>(); 1];
unsafe {
let member = xQueueGenericCreateStatic(
1,
queueSEMAPHORE_QUEUE_ITEM_LENGTH,
ptr::null_mut(),
&mut member_buffer,
queueQUEUE_TYPE_BINARY_SEMAPHORE,
);
let set =
xQueueCreateSetStatic(1, set_storage.as_mut_ptr().cast::<u8>(), &mut set_buffer);
assert!(!member.is_null() && !set.is_null());
assert_eq!(xQueueAddToSet(member, set), pdPASS);
(*member).cTxLock = queueLOCKED_UNMODIFIED;
assert_eq!(xQueueGiveFromISR(member, ptr::null_mut()), pdPASS);
assert_eq!((*member).cTxLock, queueLOCKED_UNMODIFIED);
assert_eq!((*set).uxMessagesWaiting, 0);
(*member).uxMessagesWaiting = 0;
(*member).cTxLock = queueUNLOCKED;
assert_eq!(xQueueGiveFromISR(member, ptr::null_mut()), pdPASS);
assert_eq!((*set).uxMessagesWaiting, 1);
(*set).cRxLock = queueLOCKED_UNMODIFIED;
assert_eq!(xQueueSelectFromSetFromISR(set), member);
assert_eq!((*set).cRxLock, queueLOCKED_UNMODIFIED);
assert_eq!((*set).uxMessagesWaiting, 0);
}
}
#[cfg(feature = "use-mutexes")]
#[test]
fn ordinary_mutex_take_records_and_give_clears_owner() {
crate::port::test_port_reset();
let mut current = TCB_t::new();
current.uxPriority = 2;
current.uxBasePriority = 2;
let current_ptr = core::ptr::addr_of_mut!(current);
let mut mutex_buffer = StaticQueue_t::new();
unsafe {
pxCurrentTCB = current_ptr;
let mutex = xQueueCreateMutexStatic(queueQUEUE_TYPE_MUTEX, &mut mutex_buffer);
assert!(!mutex.is_null());
assert_eq!(xQueueSemaphoreTake(mutex, 0), pdPASS);
assert!((*mutex).u.xSemaphore.xMutexHolder == current_ptr.cast());
assert_eq!((*current_ptr).uxMutexesHeld, 1);
assert_eq!((*mutex).uxMessagesWaiting, 0);
assert_eq!(
xQueueGenericSend(mutex, ptr::null(), 0, queueSEND_TO_BACK),
pdPASS
);
assert!((*mutex).u.xSemaphore.xMutexHolder.is_null());
assert_eq!((*current_ptr).uxMutexesHeld, 0);
assert_eq!((*mutex).uxMessagesWaiting, 1);
pxCurrentTCB = ptr::null_mut();
}
}
#[cfg(feature = "use-mutexes")]
#[test]
fn recursive_mutex_counts_depth_but_only_one_held_mutex() {
crate::port::test_port_reset();
let mut current = TCB_t::new();
current.uxPriority = 2;
current.uxBasePriority = 2;
let current_ptr = core::ptr::addr_of_mut!(current);
let mut mutex_buffer = StaticQueue_t::new();
unsafe {
pxCurrentTCB = current_ptr;
let mutex = xQueueCreateMutexStatic(queueQUEUE_TYPE_RECURSIVE_MUTEX, &mut mutex_buffer);
assert!(!mutex.is_null());
assert_eq!(xQueueTakeMutexRecursive(mutex, 0), pdPASS);
assert_eq!(xQueueTakeMutexRecursive(mutex, 0), pdPASS);
assert_eq!((*mutex).u.xSemaphore.uxRecursiveCallCount, 2);
assert_eq!((*current_ptr).uxMutexesHeld, 1);
assert_eq!((*mutex).uxMessagesWaiting, 0);
assert_eq!(xQueueGiveMutexRecursive(mutex), pdPASS);
assert_eq!((*mutex).u.xSemaphore.uxRecursiveCallCount, 1);
assert_eq!((*current_ptr).uxMutexesHeld, 1);
assert_eq!((*mutex).uxMessagesWaiting, 0);
assert_eq!(xQueueGiveMutexRecursive(mutex), pdPASS);
assert_eq!((*mutex).u.xSemaphore.uxRecursiveCallCount, 0);
assert_eq!((*current_ptr).uxMutexesHeld, 0);
assert_eq!((*mutex).uxMessagesWaiting, 1);
assert!((*mutex).u.xSemaphore.xMutexHolder.is_null());
pxCurrentTCB = ptr::null_mut();
}
}
}