| 30 | #include "proof/queuecontracts.h" |
| 31 | |
| 32 | BaseType_t xQueueReceive( QueueHandle_t xQueue, |
| 33 | void * const pvBuffer, |
| 34 | TickType_t xTicksToWait ) |
| 35 | /*@requires [1/2]queuehandle(xQueue, ?N, ?M, ?is_isr) &*& is_isr == false &*& |
| 36 | [1/2]queuesuspend(xQueue) &*& |
| 37 | chars(pvBuffer, M, ?x);@*/ |
| 38 | /*@ensures [1/2]queuehandle(xQueue, N, M, is_isr) &*& |
| 39 | [1/2]queuesuspend(xQueue) &*& |
| 40 | (result == pdPASS ? chars(pvBuffer, M, _) : chars(pvBuffer, M, x));@*/ |
| 41 | { |
| 42 | BaseType_t xEntryTimeSet = pdFALSE; |
| 43 | TimeOut_t xTimeOut; |
| 44 | #ifdef VERIFAST /*< const pointer declaration */ |
| 45 | Queue_t * pxQueue = xQueue; |
| 46 | #else |
| 47 | Queue_t * const pxQueue = xQueue; |
| 48 | |
| 49 | /* Check the pointer is not NULL. */ |
| 50 | configASSERT( ( pxQueue ) ); |
| 51 | |
| 52 | /* The buffer into which data is received can only be NULL if the data size |
| 53 | * is zero (so no data is copied into the buffer). */ |
| 54 | configASSERT( !( ( ( pvBuffer ) == NULL ) && ( ( pxQueue )->uxItemSize != ( UBaseType_t ) 0U ) ) ); |
| 55 | |
| 56 | /* Cannot block if the scheduler is suspended. */ |
| 57 | #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) ) |
| 58 | { |
| 59 | configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) ); |
| 60 | } |
| 61 | #endif |
| 62 | #endif |
| 63 | |
| 64 | /*lint -save -e904 This function relaxes the coding standard somewhat to |
| 65 | * allow return statements within the function itself. This is done in the |
| 66 | * interest of execution time efficiency. */ |
| 67 | for( ; ; ) |
| 68 | /*@invariant [1/2]queuehandle(xQueue, N, M, is_isr) &*& |
| 69 | [1/2]queuesuspend(xQueue) &*& |
| 70 | chars(pvBuffer, M, x) &*& |
| 71 | u_integer(&xTicksToWait, _) &*& |
| 72 | xTIME_OUT(&xTimeOut);@*/ |
| 73 | { |
| 74 | taskENTER_CRITICAL(); |
| 75 | /*@assert queue(pxQueue, ?Storage, N, M, ?W, ?R, ?K, ?is_locked, ?abs);@*/ |
| 76 | { |
| 77 | const UBaseType_t uxMessagesWaiting = pxQueue->uxMessagesWaiting; |
| 78 | |
| 79 | /* Is there data in the queue now? To be running the calling task |
| 80 | * must be the highest priority task wanting to access the queue. */ |
| 81 | if( uxMessagesWaiting > ( UBaseType_t ) 0 ) |
| 82 | { |
| 83 | /*@close queue(pxQueue, Storage, N, M, W, R, K, is_locked, abs);@*/ |
| 84 | /* Data available, remove one item. */ |
| 85 | prvCopyDataFromQueue( pxQueue, pvBuffer ); |
| 86 | /*@open queue_after_prvCopyDataFromQueue(pxQueue, Storage, N, M, W, (R+1)%N, K, is_locked, abs);@*/ |
| 87 | traceQUEUE_RECEIVE( pxQueue ); |
| 88 | pxQueue->uxMessagesWaiting = uxMessagesWaiting - ( UBaseType_t ) 1; |
| 89 | |