freeRTOS 队列3 上锁解锁
/* * Macro to mark a queue as locked. Locking a queue prevents an ISR from * accessing the queue event lists. */ #define prvLockQueue( pxQueue ) \ taskENTER_CRITICAL(); \ { \ if( ( pxQueue )->cRxLock == queueUNLOCKED ) \ { \ ( pxQueue )->cRxLock = queueLOCKED_UNMODIFIED; \ } \ if( ( pxQueue )->cTxLock == queueUNLOCKED ) \ { \ ( pxQueue )->cTxLock = queueLOCKED_UNMODIFIED; \ } \ } \ taskEXIT_CRITICAL() /*-----------------------------------------------------------*/
/* Constants used with the cRxLock and cTxLock structure members. */ #define queueUNLOCKED ( ( int8_t ) -1 ) #define queueLOCKED_UNMODIFIED ( ( int8_t ) 0 )
1 static void prvUnlockQueue( Queue_t * const pxQueue ) 2 { 3 /* THIS FUNCTION MUST BE CALLED WITH THE SCHEDULER SUSPENDED. */ 4 5 /* The lock counts contains the number of extra data items placed or 6 removed from the queue while the queue was locked. When a queue is 7 locked items can be added or removed, but the event lists cannot be 8 updated. 上锁计数器在队列上锁之后进行计数统计,但事件队列中两个列表(WaitToSend/Rcv)的那些任务的事件列表项不会更新变动*/ 9 taskENTER_CRITICAL(); 10 { 11 int8_t cTxLock = pxQueue->cTxLock; 12 13 /* See if data was added to the queue while it was locked. 【】*/ 14 while( cTxLock > queueLOCKED_UNMODIFIED ) 15 { 16 /* Data was posted while the queue was locked. Are any tasks 17 blocked waiting for data to become available? */ 18 #if ( configUSE_QUEUE_SETS == 1 ) 19 { 57 } 58 #else /* configUSE_QUEUE_SETS */ 59 { 60 /* Tasks that are removed from the event list will get added to 61 the pending ready list as the scheduler is still suspended. */ 62 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) 63 { 64 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
//将任务从列表xTaskWaitToRcv中移除 65 { 66 /* The task waiting has a higher priority so record that 67 a context switch is required. */ 68 vTaskMissedYield(); //就一句 xYieldPending = pdTRUE; 69 } 70 else 71 { 72 mtCOVERAGE_TEST_MARKER(); 73 } 74 } 75 else 76 { 77 break; 78 } 79 } 80 #endif /* configUSE_QUEUE_SETS */ 81 82 --cTxLock; 83 } 84 85 pxQueue->cTxLock = queueUNLOCKED; 86 } 87 taskEXIT_CRITICAL(); 88 89 /* Do the same for the Rx lock. */ 90 taskENTER_CRITICAL(); 91 { 92 int8_t cRxLock = pxQueue->cRxLock; 93 94 while( cRxLock > queueLOCKED_UNMODIFIED ) 95 { 96 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE ) 97 { 98 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE ) 99 { 100 vTaskMissedYield(); 101 } 102 else 103 { 104 mtCOVERAGE_TEST_MARKER(); 105 } 106 107 --cRxLock; 108 } 109 else 110 { 111 break; 112 } 113 } 114 115 pxQueue->cRxLock = queueUNLOCKED; 116 } 117 taskEXIT_CRITICAL(); 118 } 119 /*-----------------------------------------------------------*/
解锁过程:
先处理 TxLock,
while(根据TxLock的值,看看队列上锁期间是否有“入队操作”,如果有)
{
则观察事件等待列表,有任务在等待则,
将这个任务从事件等待列表WaitToRcv中踢掉,加入就绪列表 或 Pending就绪列表(函数TaskRemoveFromEventList的操作)
置位PendSV准备切换任务,之后TxLock值减一。
}
修改 TxLock 为 queueUNLOCKED。
RxLock类似。
留白
联我:shen5773384##163.com