]> begriffs open source - freertos/blob - event_groups.c
Suppress MISRA C:2012 rule 11.5 deviations (#878)
[freertos] / event_groups.c
1 /*
2  * FreeRTOS Kernel <DEVELOPMENT BRANCH>
3  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates.  All Rights Reserved.
4  *
5  * SPDX-License-Identifier: MIT
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining a copy of
8  * this software and associated documentation files (the "Software"), to deal in
9  * the Software without restriction, including without limitation the rights to
10  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
11  * the Software, and to permit persons to whom the Software is furnished to do so,
12  * subject to the following conditions:
13  *
14  * The above copyright notice and this permission notice shall be included in all
15  * copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
19  * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
20  * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
21  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23  *
24  * https://www.FreeRTOS.org
25  * https://github.com/FreeRTOS
26  *
27  */
28
29 /* Standard includes. */
30 #include <stdlib.h>
31
32 /* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining
33  * all the API functions to use the MPU wrappers.  That should only be done when
34  * task.h is included from an application file. */
35 #define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
36
37 /* FreeRTOS includes. */
38 #include "FreeRTOS.h"
39 #include "task.h"
40 #include "timers.h"
41 #include "event_groups.h"
42
43 /* Lint e961, e750 and e9021 are suppressed as a MISRA exception justified
44  * because the MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined
45  * for the header files above, but not in this file, in order to generate the
46  * correct privileged Vs unprivileged linkage and placement. */
47 #undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE /*lint !e961 !e750 !e9021 See comment above. */
48
49 typedef struct EventGroupDef_t
50 {
51     EventBits_t uxEventBits;
52     List_t xTasksWaitingForBits; /**< List of tasks waiting for a bit to be set. */
53
54     #if ( configUSE_TRACE_FACILITY == 1 )
55         UBaseType_t uxEventGroupNumber;
56     #endif
57
58     #if ( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )
59         uint8_t ucStaticallyAllocated; /**< Set to pdTRUE if the event group is statically allocated to ensure no attempt is made to free the memory. */
60     #endif
61 } EventGroup_t;
62
63 /*-----------------------------------------------------------*/
64
65 /*
66  * Test the bits set in uxCurrentEventBits to see if the wait condition is met.
67  * The wait condition is defined by xWaitForAllBits.  If xWaitForAllBits is
68  * pdTRUE then the wait condition is met if all the bits set in uxBitsToWaitFor
69  * are also set in uxCurrentEventBits.  If xWaitForAllBits is pdFALSE then the
70  * wait condition is met if any of the bits set in uxBitsToWait for are also set
71  * in uxCurrentEventBits.
72  */
73 static BaseType_t prvTestWaitCondition( const EventBits_t uxCurrentEventBits,
74                                         const EventBits_t uxBitsToWaitFor,
75                                         const BaseType_t xWaitForAllBits ) PRIVILEGED_FUNCTION;
76
77 /*-----------------------------------------------------------*/
78
79 #if ( configSUPPORT_STATIC_ALLOCATION == 1 )
80
81     EventGroupHandle_t xEventGroupCreateStatic( StaticEventGroup_t * pxEventGroupBuffer )
82     {
83         EventGroup_t * pxEventBits;
84
85         traceENTER_xEventGroupCreateStatic( pxEventGroupBuffer );
86
87         /* A StaticEventGroup_t object must be provided. */
88         configASSERT( pxEventGroupBuffer );
89
90         #if ( configASSERT_DEFINED == 1 )
91         {
92             /* Sanity check that the size of the structure used to declare a
93              * variable of type StaticEventGroup_t equals the size of the real
94              * event group structure. */
95             volatile size_t xSize = sizeof( StaticEventGroup_t );
96             configASSERT( xSize == sizeof( EventGroup_t ) );
97         } /*lint !e529 xSize is referenced if configASSERT() is defined. */
98         #endif /* configASSERT_DEFINED */
99
100         /* The user has provided a statically allocated event group - use it. */
101         /* MISRA Ref 11.3.1 [Misaligned access] */
102         /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-113 */
103         /* coverity[misra_c_2012_rule_11_3_violation] */
104         pxEventBits = ( EventGroup_t * ) pxEventGroupBuffer;
105
106         if( pxEventBits != NULL )
107         {
108             pxEventBits->uxEventBits = 0;
109             vListInitialise( &( pxEventBits->xTasksWaitingForBits ) );
110
111             #if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
112             {
113                 /* Both static and dynamic allocation can be used, so note that
114                  * this event group was created statically in case the event group
115                  * is later deleted. */
116                 pxEventBits->ucStaticallyAllocated = pdTRUE;
117             }
118             #endif /* configSUPPORT_DYNAMIC_ALLOCATION */
119
120             traceEVENT_GROUP_CREATE( pxEventBits );
121         }
122         else
123         {
124             /* xEventGroupCreateStatic should only ever be called with
125              * pxEventGroupBuffer pointing to a pre-allocated (compile time
126              * allocated) StaticEventGroup_t variable. */
127             traceEVENT_GROUP_CREATE_FAILED();
128         }
129
130         traceRETURN_xEventGroupCreateStatic( pxEventBits );
131
132         return pxEventBits;
133     }
134
135 #endif /* configSUPPORT_STATIC_ALLOCATION */
136 /*-----------------------------------------------------------*/
137
138 #if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
139
140     EventGroupHandle_t xEventGroupCreate( void )
141     {
142         EventGroup_t * pxEventBits;
143
144         traceENTER_xEventGroupCreate();
145
146         /* MISRA Ref 11.5.1 [Malloc memory assignment] */
147         /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */
148         /* coverity[misra_c_2012_rule_11_5_violation] */
149         pxEventBits = ( EventGroup_t * ) pvPortMalloc( sizeof( EventGroup_t ) );
150
151         if( pxEventBits != NULL )
152         {
153             pxEventBits->uxEventBits = 0;
154             vListInitialise( &( pxEventBits->xTasksWaitingForBits ) );
155
156             #if ( configSUPPORT_STATIC_ALLOCATION == 1 )
157             {
158                 /* Both static and dynamic allocation can be used, so note this
159                  * event group was allocated statically in case the event group is
160                  * later deleted. */
161                 pxEventBits->ucStaticallyAllocated = pdFALSE;
162             }
163             #endif /* configSUPPORT_STATIC_ALLOCATION */
164
165             traceEVENT_GROUP_CREATE( pxEventBits );
166         }
167         else
168         {
169             traceEVENT_GROUP_CREATE_FAILED(); /*lint !e9063 Else branch only exists to allow tracing and does not generate code if trace macros are not defined. */
170         }
171
172         traceRETURN_xEventGroupCreate( pxEventBits );
173
174         return pxEventBits;
175     }
176
177 #endif /* configSUPPORT_DYNAMIC_ALLOCATION */
178 /*-----------------------------------------------------------*/
179
180 EventBits_t xEventGroupSync( EventGroupHandle_t xEventGroup,
181                              const EventBits_t uxBitsToSet,
182                              const EventBits_t uxBitsToWaitFor,
183                              TickType_t xTicksToWait )
184 {
185     EventBits_t uxOriginalBitValue, uxReturn;
186     EventGroup_t * pxEventBits = xEventGroup;
187     BaseType_t xAlreadyYielded;
188     BaseType_t xTimeoutOccurred = pdFALSE;
189
190     traceENTER_xEventGroupSync( xEventGroup, uxBitsToSet, uxBitsToWaitFor, xTicksToWait );
191
192     configASSERT( ( uxBitsToWaitFor & eventEVENT_BITS_CONTROL_BYTES ) == 0 );
193     configASSERT( uxBitsToWaitFor != 0 );
194     #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) )
195     {
196         configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) );
197     }
198     #endif
199
200     vTaskSuspendAll();
201     {
202         uxOriginalBitValue = pxEventBits->uxEventBits;
203
204         ( void ) xEventGroupSetBits( xEventGroup, uxBitsToSet );
205
206         if( ( ( uxOriginalBitValue | uxBitsToSet ) & uxBitsToWaitFor ) == uxBitsToWaitFor )
207         {
208             /* All the rendezvous bits are now set - no need to block. */
209             uxReturn = ( uxOriginalBitValue | uxBitsToSet );
210
211             /* Rendezvous always clear the bits.  They will have been cleared
212              * already unless this is the only task in the rendezvous. */
213             pxEventBits->uxEventBits &= ~uxBitsToWaitFor;
214
215             xTicksToWait = 0;
216         }
217         else
218         {
219             if( xTicksToWait != ( TickType_t ) 0 )
220             {
221                 traceEVENT_GROUP_SYNC_BLOCK( xEventGroup, uxBitsToSet, uxBitsToWaitFor );
222
223                 /* Store the bits that the calling task is waiting for in the
224                  * task's event list item so the kernel knows when a match is
225                  * found.  Then enter the blocked state. */
226                 vTaskPlaceOnUnorderedEventList( &( pxEventBits->xTasksWaitingForBits ), ( uxBitsToWaitFor | eventCLEAR_EVENTS_ON_EXIT_BIT | eventWAIT_FOR_ALL_BITS ), xTicksToWait );
227
228                 /* This assignment is obsolete as uxReturn will get set after
229                  * the task unblocks, but some compilers mistakenly generate a
230                  * warning about uxReturn being returned without being set if the
231                  * assignment is omitted. */
232                 uxReturn = 0;
233             }
234             else
235             {
236                 /* The rendezvous bits were not set, but no block time was
237                  * specified - just return the current event bit value. */
238                 uxReturn = pxEventBits->uxEventBits;
239                 xTimeoutOccurred = pdTRUE;
240             }
241         }
242     }
243     xAlreadyYielded = xTaskResumeAll();
244
245     if( xTicksToWait != ( TickType_t ) 0 )
246     {
247         if( xAlreadyYielded == pdFALSE )
248         {
249             taskYIELD_WITHIN_API();
250         }
251         else
252         {
253             mtCOVERAGE_TEST_MARKER();
254         }
255
256         /* The task blocked to wait for its required bits to be set - at this
257          * point either the required bits were set or the block time expired.  If
258          * the required bits were set they will have been stored in the task's
259          * event list item, and they should now be retrieved then cleared. */
260         uxReturn = uxTaskResetEventItemValue();
261
262         if( ( uxReturn & eventUNBLOCKED_DUE_TO_BIT_SET ) == ( EventBits_t ) 0 )
263         {
264             /* The task timed out, just return the current event bit value. */
265             taskENTER_CRITICAL();
266             {
267                 uxReturn = pxEventBits->uxEventBits;
268
269                 /* Although the task got here because it timed out before the
270                  * bits it was waiting for were set, it is possible that since it
271                  * unblocked another task has set the bits.  If this is the case
272                  * then it needs to clear the bits before exiting. */
273                 if( ( uxReturn & uxBitsToWaitFor ) == uxBitsToWaitFor )
274                 {
275                     pxEventBits->uxEventBits &= ~uxBitsToWaitFor;
276                 }
277                 else
278                 {
279                     mtCOVERAGE_TEST_MARKER();
280                 }
281             }
282             taskEXIT_CRITICAL();
283
284             xTimeoutOccurred = pdTRUE;
285         }
286         else
287         {
288             /* The task unblocked because the bits were set. */
289         }
290
291         /* Control bits might be set as the task had blocked should not be
292          * returned. */
293         uxReturn &= ~eventEVENT_BITS_CONTROL_BYTES;
294     }
295
296     traceEVENT_GROUP_SYNC_END( xEventGroup, uxBitsToSet, uxBitsToWaitFor, xTimeoutOccurred );
297
298     /* Prevent compiler warnings when trace macros are not used. */
299     ( void ) xTimeoutOccurred;
300
301     traceRETURN_xEventGroupSync( uxReturn );
302
303     return uxReturn;
304 }
305 /*-----------------------------------------------------------*/
306
307 EventBits_t xEventGroupWaitBits( EventGroupHandle_t xEventGroup,
308                                  const EventBits_t uxBitsToWaitFor,
309                                  const BaseType_t xClearOnExit,
310                                  const BaseType_t xWaitForAllBits,
311                                  TickType_t xTicksToWait )
312 {
313     EventGroup_t * pxEventBits = xEventGroup;
314     EventBits_t uxReturn, uxControlBits = 0;
315     BaseType_t xWaitConditionMet, xAlreadyYielded;
316     BaseType_t xTimeoutOccurred = pdFALSE;
317
318     traceENTER_xEventGroupWaitBits( xEventGroup, uxBitsToWaitFor, xClearOnExit, xWaitForAllBits, xTicksToWait );
319
320     /* Check the user is not attempting to wait on the bits used by the kernel
321      * itself, and that at least one bit is being requested. */
322     configASSERT( xEventGroup );
323     configASSERT( ( uxBitsToWaitFor & eventEVENT_BITS_CONTROL_BYTES ) == 0 );
324     configASSERT( uxBitsToWaitFor != 0 );
325     #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) )
326     {
327         configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) );
328     }
329     #endif
330
331     vTaskSuspendAll();
332     {
333         const EventBits_t uxCurrentEventBits = pxEventBits->uxEventBits;
334
335         /* Check to see if the wait condition is already met or not. */
336         xWaitConditionMet = prvTestWaitCondition( uxCurrentEventBits, uxBitsToWaitFor, xWaitForAllBits );
337
338         if( xWaitConditionMet != pdFALSE )
339         {
340             /* The wait condition has already been met so there is no need to
341              * block. */
342             uxReturn = uxCurrentEventBits;
343             xTicksToWait = ( TickType_t ) 0;
344
345             /* Clear the wait bits if requested to do so. */
346             if( xClearOnExit != pdFALSE )
347             {
348                 pxEventBits->uxEventBits &= ~uxBitsToWaitFor;
349             }
350             else
351             {
352                 mtCOVERAGE_TEST_MARKER();
353             }
354         }
355         else if( xTicksToWait == ( TickType_t ) 0 )
356         {
357             /* The wait condition has not been met, but no block time was
358              * specified, so just return the current value. */
359             uxReturn = uxCurrentEventBits;
360             xTimeoutOccurred = pdTRUE;
361         }
362         else
363         {
364             /* The task is going to block to wait for its required bits to be
365              * set.  uxControlBits are used to remember the specified behaviour of
366              * this call to xEventGroupWaitBits() - for use when the event bits
367              * unblock the task. */
368             if( xClearOnExit != pdFALSE )
369             {
370                 uxControlBits |= eventCLEAR_EVENTS_ON_EXIT_BIT;
371             }
372             else
373             {
374                 mtCOVERAGE_TEST_MARKER();
375             }
376
377             if( xWaitForAllBits != pdFALSE )
378             {
379                 uxControlBits |= eventWAIT_FOR_ALL_BITS;
380             }
381             else
382             {
383                 mtCOVERAGE_TEST_MARKER();
384             }
385
386             /* Store the bits that the calling task is waiting for in the
387              * task's event list item so the kernel knows when a match is
388              * found.  Then enter the blocked state. */
389             vTaskPlaceOnUnorderedEventList( &( pxEventBits->xTasksWaitingForBits ), ( uxBitsToWaitFor | uxControlBits ), xTicksToWait );
390
391             /* This is obsolete as it will get set after the task unblocks, but
392              * some compilers mistakenly generate a warning about the variable
393              * being returned without being set if it is not done. */
394             uxReturn = 0;
395
396             traceEVENT_GROUP_WAIT_BITS_BLOCK( xEventGroup, uxBitsToWaitFor );
397         }
398     }
399     xAlreadyYielded = xTaskResumeAll();
400
401     if( xTicksToWait != ( TickType_t ) 0 )
402     {
403         if( xAlreadyYielded == pdFALSE )
404         {
405             taskYIELD_WITHIN_API();
406         }
407         else
408         {
409             mtCOVERAGE_TEST_MARKER();
410         }
411
412         /* The task blocked to wait for its required bits to be set - at this
413          * point either the required bits were set or the block time expired.  If
414          * the required bits were set they will have been stored in the task's
415          * event list item, and they should now be retrieved then cleared. */
416         uxReturn = uxTaskResetEventItemValue();
417
418         if( ( uxReturn & eventUNBLOCKED_DUE_TO_BIT_SET ) == ( EventBits_t ) 0 )
419         {
420             taskENTER_CRITICAL();
421             {
422                 /* The task timed out, just return the current event bit value. */
423                 uxReturn = pxEventBits->uxEventBits;
424
425                 /* It is possible that the event bits were updated between this
426                  * task leaving the Blocked state and running again. */
427                 if( prvTestWaitCondition( uxReturn, uxBitsToWaitFor, xWaitForAllBits ) != pdFALSE )
428                 {
429                     if( xClearOnExit != pdFALSE )
430                     {
431                         pxEventBits->uxEventBits &= ~uxBitsToWaitFor;
432                     }
433                     else
434                     {
435                         mtCOVERAGE_TEST_MARKER();
436                     }
437                 }
438                 else
439                 {
440                     mtCOVERAGE_TEST_MARKER();
441                 }
442
443                 xTimeoutOccurred = pdTRUE;
444             }
445             taskEXIT_CRITICAL();
446         }
447         else
448         {
449             /* The task unblocked because the bits were set. */
450         }
451
452         /* The task blocked so control bits may have been set. */
453         uxReturn &= ~eventEVENT_BITS_CONTROL_BYTES;
454     }
455
456     traceEVENT_GROUP_WAIT_BITS_END( xEventGroup, uxBitsToWaitFor, xTimeoutOccurred );
457
458     /* Prevent compiler warnings when trace macros are not used. */
459     ( void ) xTimeoutOccurred;
460
461     traceRETURN_xEventGroupWaitBits( uxReturn );
462
463     return uxReturn;
464 }
465 /*-----------------------------------------------------------*/
466
467 EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup,
468                                   const EventBits_t uxBitsToClear )
469 {
470     EventGroup_t * pxEventBits = xEventGroup;
471     EventBits_t uxReturn;
472
473     traceENTER_xEventGroupClearBits( xEventGroup, uxBitsToClear );
474
475     /* Check the user is not attempting to clear the bits used by the kernel
476      * itself. */
477     configASSERT( xEventGroup );
478     configASSERT( ( uxBitsToClear & eventEVENT_BITS_CONTROL_BYTES ) == 0 );
479
480     taskENTER_CRITICAL();
481     {
482         traceEVENT_GROUP_CLEAR_BITS( xEventGroup, uxBitsToClear );
483
484         /* The value returned is the event group value prior to the bits being
485          * cleared. */
486         uxReturn = pxEventBits->uxEventBits;
487
488         /* Clear the bits. */
489         pxEventBits->uxEventBits &= ~uxBitsToClear;
490     }
491     taskEXIT_CRITICAL();
492
493     traceRETURN_xEventGroupClearBits( uxReturn );
494
495     return uxReturn;
496 }
497 /*-----------------------------------------------------------*/
498
499 #if ( ( configUSE_TRACE_FACILITY == 1 ) && ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) )
500
501     BaseType_t xEventGroupClearBitsFromISR( EventGroupHandle_t xEventGroup,
502                                             const EventBits_t uxBitsToClear )
503     {
504         BaseType_t xReturn;
505
506         traceENTER_xEventGroupClearBitsFromISR( xEventGroup, uxBitsToClear );
507
508         traceEVENT_GROUP_CLEAR_BITS_FROM_ISR( xEventGroup, uxBitsToClear );
509         xReturn = xTimerPendFunctionCallFromISR( vEventGroupClearBitsCallback, ( void * ) xEventGroup, ( uint32_t ) uxBitsToClear, NULL ); /*lint !e9087 Can't avoid cast to void* as a generic callback function not specific to this use case. Callback casts back to original type so safe. */
510
511         traceRETURN_xEventGroupClearBitsFromISR( xReturn );
512
513         return xReturn;
514     }
515
516 #endif /* if ( ( configUSE_TRACE_FACILITY == 1 ) && ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) ) */
517 /*-----------------------------------------------------------*/
518
519 EventBits_t xEventGroupGetBitsFromISR( EventGroupHandle_t xEventGroup )
520 {
521     UBaseType_t uxSavedInterruptStatus;
522     EventGroup_t const * const pxEventBits = xEventGroup;
523     EventBits_t uxReturn;
524
525     traceENTER_xEventGroupGetBitsFromISR( xEventGroup );
526
527     uxSavedInterruptStatus = taskENTER_CRITICAL_FROM_ISR();
528     {
529         uxReturn = pxEventBits->uxEventBits;
530     }
531     taskEXIT_CRITICAL_FROM_ISR( uxSavedInterruptStatus );
532
533     traceRETURN_xEventGroupGetBitsFromISR( uxReturn );
534
535     return uxReturn;
536 } /*lint !e818 EventGroupHandle_t is a typedef used in other functions to so can't be pointer to const. */
537 /*-----------------------------------------------------------*/
538
539 EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup,
540                                 const EventBits_t uxBitsToSet )
541 {
542     ListItem_t * pxListItem;
543     ListItem_t * pxNext;
544     ListItem_t const * pxListEnd;
545     List_t const * pxList;
546     EventBits_t uxBitsToClear = 0, uxBitsWaitedFor, uxControlBits;
547     EventGroup_t * pxEventBits = xEventGroup;
548     BaseType_t xMatchFound = pdFALSE;
549
550     traceENTER_xEventGroupSetBits( xEventGroup, uxBitsToSet );
551
552     /* Check the user is not attempting to set the bits used by the kernel
553      * itself. */
554     configASSERT( xEventGroup );
555     configASSERT( ( uxBitsToSet & eventEVENT_BITS_CONTROL_BYTES ) == 0 );
556
557     pxList = &( pxEventBits->xTasksWaitingForBits );
558     pxListEnd = listGET_END_MARKER( pxList ); /*lint !e826 !e740 !e9087 The mini list structure is used as the list end to save RAM.  This is checked and valid. */
559     vTaskSuspendAll();
560     {
561         traceEVENT_GROUP_SET_BITS( xEventGroup, uxBitsToSet );
562
563         pxListItem = listGET_HEAD_ENTRY( pxList );
564
565         /* Set the bits. */
566         pxEventBits->uxEventBits |= uxBitsToSet;
567
568         /* See if the new bit value should unblock any tasks. */
569         while( pxListItem != pxListEnd )
570         {
571             pxNext = listGET_NEXT( pxListItem );
572             uxBitsWaitedFor = listGET_LIST_ITEM_VALUE( pxListItem );
573             xMatchFound = pdFALSE;
574
575             /* Split the bits waited for from the control bits. */
576             uxControlBits = uxBitsWaitedFor & eventEVENT_BITS_CONTROL_BYTES;
577             uxBitsWaitedFor &= ~eventEVENT_BITS_CONTROL_BYTES;
578
579             if( ( uxControlBits & eventWAIT_FOR_ALL_BITS ) == ( EventBits_t ) 0 )
580             {
581                 /* Just looking for single bit being set. */
582                 if( ( uxBitsWaitedFor & pxEventBits->uxEventBits ) != ( EventBits_t ) 0 )
583                 {
584                     xMatchFound = pdTRUE;
585                 }
586                 else
587                 {
588                     mtCOVERAGE_TEST_MARKER();
589                 }
590             }
591             else if( ( uxBitsWaitedFor & pxEventBits->uxEventBits ) == uxBitsWaitedFor )
592             {
593                 /* All bits are set. */
594                 xMatchFound = pdTRUE;
595             }
596             else
597             {
598                 /* Need all bits to be set, but not all the bits were set. */
599             }
600
601             if( xMatchFound != pdFALSE )
602             {
603                 /* The bits match.  Should the bits be cleared on exit? */
604                 if( ( uxControlBits & eventCLEAR_EVENTS_ON_EXIT_BIT ) != ( EventBits_t ) 0 )
605                 {
606                     uxBitsToClear |= uxBitsWaitedFor;
607                 }
608                 else
609                 {
610                     mtCOVERAGE_TEST_MARKER();
611                 }
612
613                 /* Store the actual event flag value in the task's event list
614                  * item before removing the task from the event list.  The
615                  * eventUNBLOCKED_DUE_TO_BIT_SET bit is set so the task knows
616                  * that is was unblocked due to its required bits matching, rather
617                  * than because it timed out. */
618                 vTaskRemoveFromUnorderedEventList( pxListItem, pxEventBits->uxEventBits | eventUNBLOCKED_DUE_TO_BIT_SET );
619             }
620
621             /* Move onto the next list item.  Note pxListItem->pxNext is not
622              * used here as the list item may have been removed from the event list
623              * and inserted into the ready/pending reading list. */
624             pxListItem = pxNext;
625         }
626
627         /* Clear any bits that matched when the eventCLEAR_EVENTS_ON_EXIT_BIT
628          * bit was set in the control word. */
629         pxEventBits->uxEventBits &= ~uxBitsToClear;
630     }
631     ( void ) xTaskResumeAll();
632
633     traceRETURN_xEventGroupSetBits( pxEventBits->uxEventBits );
634
635     return pxEventBits->uxEventBits;
636 }
637 /*-----------------------------------------------------------*/
638
639 void vEventGroupDelete( EventGroupHandle_t xEventGroup )
640 {
641     EventGroup_t * pxEventBits = xEventGroup;
642     const List_t * pxTasksWaitingForBits;
643
644     traceENTER_vEventGroupDelete( xEventGroup );
645
646     configASSERT( pxEventBits );
647
648     pxTasksWaitingForBits = &( pxEventBits->xTasksWaitingForBits );
649
650     vTaskSuspendAll();
651     {
652         traceEVENT_GROUP_DELETE( xEventGroup );
653
654         while( listCURRENT_LIST_LENGTH( pxTasksWaitingForBits ) > ( UBaseType_t ) 0 )
655         {
656             /* Unblock the task, returning 0 as the event list is being deleted
657              * and cannot therefore have any bits set. */
658             configASSERT( pxTasksWaitingForBits->xListEnd.pxNext != ( const ListItem_t * ) &( pxTasksWaitingForBits->xListEnd ) );
659             vTaskRemoveFromUnorderedEventList( pxTasksWaitingForBits->xListEnd.pxNext, eventUNBLOCKED_DUE_TO_BIT_SET );
660         }
661     }
662     ( void ) xTaskResumeAll();
663
664     #if ( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 0 ) )
665     {
666         /* The event group can only have been allocated dynamically - free
667          * it again. */
668         vPortFree( pxEventBits );
669     }
670     #elif ( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) )
671     {
672         /* The event group could have been allocated statically or
673          * dynamically, so check before attempting to free the memory. */
674         if( pxEventBits->ucStaticallyAllocated == ( uint8_t ) pdFALSE )
675         {
676             vPortFree( pxEventBits );
677         }
678         else
679         {
680             mtCOVERAGE_TEST_MARKER();
681         }
682     }
683     #endif /* configSUPPORT_DYNAMIC_ALLOCATION */
684
685     traceRETURN_vEventGroupDelete();
686 }
687 /*-----------------------------------------------------------*/
688
689 #if ( configSUPPORT_STATIC_ALLOCATION == 1 )
690     BaseType_t xEventGroupGetStaticBuffer( EventGroupHandle_t xEventGroup,
691                                            StaticEventGroup_t ** ppxEventGroupBuffer )
692     {
693         BaseType_t xReturn;
694         EventGroup_t * pxEventBits = xEventGroup;
695
696         traceENTER_xEventGroupGetStaticBuffer( xEventGroup, ppxEventGroupBuffer );
697
698         configASSERT( pxEventBits );
699         configASSERT( ppxEventGroupBuffer );
700
701         #if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
702         {
703             /* Check if the event group was statically allocated. */
704             if( pxEventBits->ucStaticallyAllocated == ( uint8_t ) pdTRUE )
705             {
706                 /* MISRA Ref 11.3.1 [Misaligned access] */
707                 /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-113 */
708                 /* coverity[misra_c_2012_rule_11_3_violation] */
709                 *ppxEventGroupBuffer = ( StaticEventGroup_t * ) pxEventBits;
710                 xReturn = pdTRUE;
711             }
712             else
713             {
714                 xReturn = pdFALSE;
715             }
716         }
717         #else /* configSUPPORT_DYNAMIC_ALLOCATION */
718         {
719             /* Event group must have been statically allocated. */
720             /* MISRA Ref 11.3.1 [Misaligned access] */
721             /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-113 */
722             /* coverity[misra_c_2012_rule_11_3_violation] */
723             *ppxEventGroupBuffer = ( StaticEventGroup_t * ) pxEventBits;
724             xReturn = pdTRUE;
725         }
726         #endif /* configSUPPORT_DYNAMIC_ALLOCATION */
727
728         traceRETURN_xEventGroupGetStaticBuffer( xReturn );
729
730         return xReturn;
731     }
732 #endif /* configSUPPORT_STATIC_ALLOCATION */
733 /*-----------------------------------------------------------*/
734
735 /* For internal use only - execute a 'set bits' command that was pended from
736  * an interrupt. */
737 void vEventGroupSetBitsCallback( void * pvEventGroup,
738                                  const uint32_t ulBitsToSet )
739 {
740     traceENTER_vEventGroupSetBitsCallback( pvEventGroup, ulBitsToSet );
741
742     /* MISRA Ref 11.5.4 [Callback function parameter] */
743     /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */
744     /* coverity[misra_c_2012_rule_11_5_violation] */
745     ( void ) xEventGroupSetBits( pvEventGroup, ( EventBits_t ) ulBitsToSet );
746
747     traceRETURN_vEventGroupSetBitsCallback();
748 }
749 /*-----------------------------------------------------------*/
750
751 /* For internal use only - execute a 'clear bits' command that was pended from
752  * an interrupt. */
753 void vEventGroupClearBitsCallback( void * pvEventGroup,
754                                    const uint32_t ulBitsToClear )
755 {
756     traceENTER_vEventGroupClearBitsCallback( pvEventGroup, ulBitsToClear );
757
758     /* MISRA Ref 11.5.4 [Callback function parameter] */
759     /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */
760     /* coverity[misra_c_2012_rule_11_5_violation] */
761     ( void ) xEventGroupClearBits( pvEventGroup, ( EventBits_t ) ulBitsToClear );
762
763     traceRETURN_vEventGroupClearBitsCallback();
764 }
765 /*-----------------------------------------------------------*/
766
767 static BaseType_t prvTestWaitCondition( const EventBits_t uxCurrentEventBits,
768                                         const EventBits_t uxBitsToWaitFor,
769                                         const BaseType_t xWaitForAllBits )
770 {
771     BaseType_t xWaitConditionMet = pdFALSE;
772
773     if( xWaitForAllBits == pdFALSE )
774     {
775         /* Task only has to wait for one bit within uxBitsToWaitFor to be
776          * set.  Is one already set? */
777         if( ( uxCurrentEventBits & uxBitsToWaitFor ) != ( EventBits_t ) 0 )
778         {
779             xWaitConditionMet = pdTRUE;
780         }
781         else
782         {
783             mtCOVERAGE_TEST_MARKER();
784         }
785     }
786     else
787     {
788         /* Task has to wait for all the bits in uxBitsToWaitFor to be set.
789          * Are they set already? */
790         if( ( uxCurrentEventBits & uxBitsToWaitFor ) == uxBitsToWaitFor )
791         {
792             xWaitConditionMet = pdTRUE;
793         }
794         else
795         {
796             mtCOVERAGE_TEST_MARKER();
797         }
798     }
799
800     return xWaitConditionMet;
801 }
802 /*-----------------------------------------------------------*/
803
804 #if ( ( configUSE_TRACE_FACILITY == 1 ) && ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) )
805
806     BaseType_t xEventGroupSetBitsFromISR( EventGroupHandle_t xEventGroup,
807                                           const EventBits_t uxBitsToSet,
808                                           BaseType_t * pxHigherPriorityTaskWoken )
809     {
810         BaseType_t xReturn;
811
812         traceENTER_xEventGroupSetBitsFromISR( xEventGroup, uxBitsToSet, pxHigherPriorityTaskWoken );
813
814         traceEVENT_GROUP_SET_BITS_FROM_ISR( xEventGroup, uxBitsToSet );
815         xReturn = xTimerPendFunctionCallFromISR( vEventGroupSetBitsCallback, ( void * ) xEventGroup, ( uint32_t ) uxBitsToSet, pxHigherPriorityTaskWoken ); /*lint !e9087 Can't avoid cast to void* as a generic callback function not specific to this use case. Callback casts back to original type so safe. */
816
817         traceRETURN_xEventGroupSetBitsFromISR( xReturn );
818
819         return xReturn;
820     }
821
822 #endif /* if ( ( configUSE_TRACE_FACILITY == 1 ) && ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) ) */
823 /*-----------------------------------------------------------*/
824
825 #if ( configUSE_TRACE_FACILITY == 1 )
826
827     UBaseType_t uxEventGroupGetNumber( void * xEventGroup )
828     {
829         UBaseType_t xReturn;
830
831         /* MISRA Ref 11.5.2 [Opaque pointer] */
832         /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */
833         /* coverity[misra_c_2012_rule_11_5_violation] */
834         EventGroup_t const * pxEventBits = ( EventGroup_t * ) xEventGroup;
835
836         traceENTER_uxEventGroupGetNumber( xEventGroup );
837
838         if( xEventGroup == NULL )
839         {
840             xReturn = 0;
841         }
842         else
843         {
844             xReturn = pxEventBits->uxEventGroupNumber;
845         }
846
847         traceRETURN_uxEventGroupGetNumber( xReturn );
848
849         return xReturn;
850     }
851
852 #endif /* configUSE_TRACE_FACILITY */
853 /*-----------------------------------------------------------*/
854
855 #if ( configUSE_TRACE_FACILITY == 1 )
856
857     void vEventGroupSetNumber( void * xEventGroup,
858                                UBaseType_t uxEventGroupNumber )
859     {
860         traceENTER_vEventGroupSetNumber( xEventGroup, uxEventGroupNumber );
861
862         /* MISRA Ref 11.5.2 [Opaque pointer] */
863         /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */
864         /* coverity[misra_c_2012_rule_11_5_violation] */
865         ( ( EventGroup_t * ) xEventGroup )->uxEventGroupNumber = uxEventGroupNumber;
866
867         traceRETURN_vEventGroupSetNumber();
868     }
869
870 #endif /* configUSE_TRACE_FACILITY */
871 /*-----------------------------------------------------------*/