]> begriffs open source - cmsis-freertos/blob - Test/VeriFast/queue/xQueueGenericSendFromISR.c
Updated pack to FreeRTOS 10.4.6
[cmsis-freertos] / Test / VeriFast / queue / xQueueGenericSendFromISR.c
1 /*
2  * FreeRTOS V202111.00
3  * Copyright (C) Amazon.com, Inc. or its affiliates.  All Rights Reserved.
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a copy of
6  * this software and associated documentation files (the "Software"), to deal in
7  * the Software without restriction, including without limitation the rights to
8  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9  * the Software, and to permit persons to whom the Software is furnished to do so,
10  * subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be included in all
13  * copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17  * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18  * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21  *
22  * https://www.FreeRTOS.org
23  * https://github.com/FreeRTOS
24  *
25  */
26
27 #include "proof/queue.h"
28 #include "proof/queuecontracts.h"
29
30 BaseType_t xQueueGenericSendFromISR( QueueHandle_t xQueue,
31                                      const void * const pvItemToQueue,
32                                      BaseType_t * const pxHigherPriorityTaskWoken,
33                                      const BaseType_t xCopyPosition )
34
35 /*@requires
36  *  [1/2]queuehandle(xQueue, ?N, ?M, ?is_isr) &*& is_isr == true &*&
37  *  chars(pvItemToQueue, M, ?x) &*&
38  *  integer(pxHigherPriorityTaskWoken, _) &*&
39  *  (xCopyPosition == queueSEND_TO_BACK || xCopyPosition == queueSEND_TO_FRONT || (xCopyPosition == queueOVERWRITE && N == 1));@*/
40
41 /*@ensures
42  *  [1/2]queuehandle(xQueue, N, M, is_isr) &*&
43  *  chars(pvItemToQueue, M, x) &*&
44  *  integer(pxHigherPriorityTaskWoken, _);@*/
45 {
46     BaseType_t xReturn;
47     UBaseType_t uxSavedInterruptStatus;
48
49     #ifdef VERIFAST /*< const pointer declaration */
50         Queue_t * pxQueue = xQueue;
51     #else
52         Queue_t * const pxQueue = xQueue;
53
54         configASSERT( pxQueue );
55         configASSERT( !( ( pvItemToQueue == NULL ) && ( pxQueue->uxItemSize != ( UBaseType_t ) 0U ) ) );
56         configASSERT( !( ( xCopyPosition == queueOVERWRITE ) && ( pxQueue->uxLength != 1 ) ) );
57     #endif
58
59     /* RTOS ports that support interrupt nesting have the concept of a maximum
60      * system call (or maximum API call) interrupt priority.  Interrupts that are
61      * above the maximum system call priority are kept permanently enabled, even
62      * when the RTOS kernel is in a critical section, but cannot make any calls to
63      * FreeRTOS API functions.  If configASSERT() is defined in FreeRTOSConfig.h
64      * then portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion
65      * failure if a FreeRTOS API function is called from an interrupt that has been
66      * assigned a priority above the configured maximum system call priority.
67      * Only FreeRTOS functions that end in FromISR can be called from interrupts
68      * that have been assigned a priority at or (logically) below the maximum
69      * system call interrupt priority.  FreeRTOS maintains a separate interrupt
70      * safe API to ensure interrupt entry is as fast and as simple as possible.
71      * More information (albeit Cortex-M specific) is provided on the following
72      * link: https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
73     portASSERT_IF_INTERRUPT_PRIORITY_INVALID();
74
75     /* Similar to xQueueGenericSend, except without blocking if there is no room
76      * in the queue.  Also don't directly wake a task that was blocked on a queue
77      * read, instead return a flag to say whether a context switch is required or
78      * not (i.e. has a task with a higher priority than us been woken by this
79      * post). */
80     uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
81     /*@assert queue(pxQueue, ?Storage, N, M, ?W, ?R, ?K, ?is_locked, ?abs);@*/
82     {
83         if( ( pxQueue->uxMessagesWaiting < pxQueue->uxLength ) || ( xCopyPosition == queueOVERWRITE ) )
84         {
85             const int8_t cTxLock = pxQueue->cTxLock;
86             const UBaseType_t uxPreviousMessagesWaiting = pxQueue->uxMessagesWaiting;
87
88             traceQUEUE_SEND_FROM_ISR( pxQueue );
89
90             /* Semaphores use xQueueGiveFromISR(), so pxQueue will not be a
91              *  semaphore or mutex.  That means prvCopyDataToQueue() cannot result
92              *  in a task disinheriting a priority and prvCopyDataToQueue() can be
93              *  called here even though the disinherit function does not check if
94              *  the scheduler is suspended before accessing the ready lists. */
95             #ifdef VERIFAST /*< void cast of unused return value */
96                 /*@close queue(pxQueue, Storage, N, M, W, R, K, is_locked, abs);@*/
97                 prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition );
98             #else
99                 ( void ) prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition );
100             #endif
101             /*@open queue(pxQueue, _, N, M, _, _, _, _, _);@*/
102
103             /* The event list is not altered if the queue is locked.  This will
104              * be done when the queue is unlocked later. */
105             if( cTxLock == queueUNLOCKED )
106             {
107                 /* VeriFast: we do not verify this configuration option */
108                 #if ( configUSE_QUEUE_SETS == 1 )
109                     {
110                         if( pxQueue->pxQueueSetContainer != NULL )
111                         {
112                             if( ( xCopyPosition == queueOVERWRITE ) && ( uxPreviousMessagesWaiting != ( UBaseType_t ) 0 ) )
113                             {
114                                 /* Do not notify the queue set as an existing item
115                                  * was overwritten in the queue so the number of items
116                                  * in the queue has not changed. */
117                                 mtCOVERAGE_TEST_MARKER();
118                             }
119                             else if( prvNotifyQueueSetContainer( pxQueue ) != pdFALSE )
120                             {
121                                 /* The queue is a member of a queue set, and posting
122                                  * to the queue set caused a higher priority task to
123                                  * unblock.  A context switch is required. */
124                                 if( pxHigherPriorityTaskWoken != NULL )
125                                 {
126                                     *pxHigherPriorityTaskWoken = pdTRUE;
127                                 }
128                                 else
129                                 {
130                                     mtCOVERAGE_TEST_MARKER();
131                                 }
132                             }
133                             else
134                             {
135                                 mtCOVERAGE_TEST_MARKER();
136                             }
137                         }
138                         else
139                         {
140                             if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
141                             {
142                                 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
143                                 {
144                                     /* The task waiting has a higher priority so
145                                      *  record that a context switch is required. */
146                                     if( pxHigherPriorityTaskWoken != NULL )
147                                     {
148                                         *pxHigherPriorityTaskWoken = pdTRUE;
149                                     }
150                                     else
151                                     {
152                                         mtCOVERAGE_TEST_MARKER();
153                                     }
154                                 }
155                                 else
156                                 {
157                                     mtCOVERAGE_TEST_MARKER();
158                                 }
159                             }
160                             else
161                             {
162                                 mtCOVERAGE_TEST_MARKER();
163                             }
164                         }
165                     }
166                 #else /* configUSE_QUEUE_SETS */
167                     {
168                         if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
169                         {
170                             if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
171                             {
172                                 /* The task waiting has a higher priority so record that a
173                                  * context switch is required. */
174                                 if( pxHigherPriorityTaskWoken != NULL )
175                                 {
176                                     *pxHigherPriorityTaskWoken = pdTRUE;
177                                 }
178                                 else
179                                 {
180                                     mtCOVERAGE_TEST_MARKER();
181                                 }
182                             }
183                             else
184                             {
185                                 mtCOVERAGE_TEST_MARKER();
186                             }
187                         }
188                         else
189                         {
190                             mtCOVERAGE_TEST_MARKER();
191                         }
192
193                         /* Not used in this path. */
194                         #ifndef VERIFAST /*< void cast of unused var */
195                             ( void ) uxPreviousMessagesWaiting;
196                         #endif
197                     }
198                 #endif /* configUSE_QUEUE_SETS */
199             }
200             else
201             {
202                 /* Increment the lock count so the task that unlocks the queue
203                  * knows that data was posted while it was locked. */
204                 configASSERT( cTxLock != queueINT8_MAX );
205
206                 pxQueue->cTxLock = ( int8_t ) ( cTxLock + 1 );
207             }
208
209             xReturn = pdPASS;
210
211             /*@
212              * if (xCopyPosition == queueSEND_TO_BACK)
213              * {
214              *  close queue(pxQueue, Storage, N, M, (W+1)%N, R, (K+1), is_locked, append(abs, singleton(x)));
215              * }
216              * else if (xCopyPosition == queueSEND_TO_FRONT)
217              * {
218              *  if (R == 0)
219              *  {
220              *      close queue(pxQueue, Storage, N, M, W, (N-1), (K+1), is_locked, cons(x, abs));
221              *  }
222              *  else
223              *  {
224              *      close queue(pxQueue, Storage, N, M, W, (R-1), (K+1), is_locked, cons(x, abs));
225              *  }
226              * } else if (xCopyPosition == queueOVERWRITE)
227              * {
228              *  close queue(pxQueue, Storage, N, M, W, R, 1, is_locked, singleton(x));
229              * }
230              * @*/
231         }
232         else
233         {
234             traceQUEUE_SEND_FROM_ISR_FAILED( pxQueue );
235             xReturn = errQUEUE_FULL;
236             /*@close queue(pxQueue, Storage, N, M, W, R, K, is_locked, abs);@*/
237         }
238     }
239     portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
240
241     return xReturn;
242 }