2 * FreeRTOS Kernel <DEVELOPMENT BRANCH>
3 * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
5 * SPDX-License-Identifier: MIT
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:
14 * The above copyright notice and this permission notice shall be included in all
15 * copies or substantial portions of the Software.
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.
24 * https://www.FreeRTOS.org
25 * https://github.com/FreeRTOS
29 /* Standard includes. */
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
37 /* FreeRTOS includes. */
41 #include "event_groups.h"
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. */
49 typedef struct EventGroupDef_t
51 EventBits_t uxEventBits;
52 List_t xTasksWaitingForBits; /**< List of tasks waiting for a bit to be set. */
54 #if ( configUSE_TRACE_FACILITY == 1 )
55 UBaseType_t uxEventGroupNumber;
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. */
63 /*-----------------------------------------------------------*/
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.
73 static BaseType_t prvTestWaitCondition( const EventBits_t uxCurrentEventBits,
74 const EventBits_t uxBitsToWaitFor,
75 const BaseType_t xWaitForAllBits ) PRIVILEGED_FUNCTION;
77 /*-----------------------------------------------------------*/
79 #if ( configSUPPORT_STATIC_ALLOCATION == 1 )
81 EventGroupHandle_t xEventGroupCreateStatic( StaticEventGroup_t * pxEventGroupBuffer )
83 EventGroup_t * pxEventBits;
85 traceENTER_xEventGroupCreateStatic( pxEventGroupBuffer );
87 /* A StaticEventGroup_t object must be provided. */
88 configASSERT( pxEventGroupBuffer );
90 #if ( configASSERT_DEFINED == 1 )
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 */
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;
106 if( pxEventBits != NULL )
108 pxEventBits->uxEventBits = 0;
109 vListInitialise( &( pxEventBits->xTasksWaitingForBits ) );
111 #if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
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;
118 #endif /* configSUPPORT_DYNAMIC_ALLOCATION */
120 traceEVENT_GROUP_CREATE( pxEventBits );
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();
130 traceRETURN_xEventGroupCreateStatic( pxEventBits );
135 #endif /* configSUPPORT_STATIC_ALLOCATION */
136 /*-----------------------------------------------------------*/
138 #if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
140 EventGroupHandle_t xEventGroupCreate( void )
142 EventGroup_t * pxEventBits;
144 traceENTER_xEventGroupCreate();
146 /* Allocate the event group. Justification for MISRA deviation as
147 * follows: pvPortMalloc() always ensures returned memory blocks are
148 * aligned per the requirements of the MCU stack. In this case
149 * pvPortMalloc() must return a pointer that is guaranteed to meet the
150 * alignment requirements of the EventGroup_t structure - which (if you
151 * follow it through) is the alignment requirements of the TickType_t type
152 * (EventBits_t being of TickType_t itself). Therefore, whenever the
153 * stack alignment requirements are greater than or equal to the
154 * TickType_t alignment requirements the cast is safe. In other cases,
155 * where the natural word size of the architecture is less than
156 * sizeof( TickType_t ), the TickType_t variables will be accessed in two
157 * or more reads operations, and the alignment requirements is only that
158 * of each individual read. */
159 pxEventBits = ( EventGroup_t * ) pvPortMalloc( sizeof( EventGroup_t ) ); /*lint !e9087 !e9079 see comment above. */
161 if( pxEventBits != NULL )
163 pxEventBits->uxEventBits = 0;
164 vListInitialise( &( pxEventBits->xTasksWaitingForBits ) );
166 #if ( configSUPPORT_STATIC_ALLOCATION == 1 )
168 /* Both static and dynamic allocation can be used, so note this
169 * event group was allocated statically in case the event group is
171 pxEventBits->ucStaticallyAllocated = pdFALSE;
173 #endif /* configSUPPORT_STATIC_ALLOCATION */
175 traceEVENT_GROUP_CREATE( pxEventBits );
179 traceEVENT_GROUP_CREATE_FAILED(); /*lint !e9063 Else branch only exists to allow tracing and does not generate code if trace macros are not defined. */
182 traceRETURN_xEventGroupCreate( pxEventBits );
187 #endif /* configSUPPORT_DYNAMIC_ALLOCATION */
188 /*-----------------------------------------------------------*/
190 EventBits_t xEventGroupSync( EventGroupHandle_t xEventGroup,
191 const EventBits_t uxBitsToSet,
192 const EventBits_t uxBitsToWaitFor,
193 TickType_t xTicksToWait )
195 EventBits_t uxOriginalBitValue, uxReturn;
196 EventGroup_t * pxEventBits = xEventGroup;
197 BaseType_t xAlreadyYielded;
198 BaseType_t xTimeoutOccurred = pdFALSE;
200 traceENTER_xEventGroupSync( xEventGroup, uxBitsToSet, uxBitsToWaitFor, xTicksToWait );
202 configASSERT( ( uxBitsToWaitFor & eventEVENT_BITS_CONTROL_BYTES ) == 0 );
203 configASSERT( uxBitsToWaitFor != 0 );
204 #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) )
206 configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) );
212 uxOriginalBitValue = pxEventBits->uxEventBits;
214 ( void ) xEventGroupSetBits( xEventGroup, uxBitsToSet );
216 if( ( ( uxOriginalBitValue | uxBitsToSet ) & uxBitsToWaitFor ) == uxBitsToWaitFor )
218 /* All the rendezvous bits are now set - no need to block. */
219 uxReturn = ( uxOriginalBitValue | uxBitsToSet );
221 /* Rendezvous always clear the bits. They will have been cleared
222 * already unless this is the only task in the rendezvous. */
223 pxEventBits->uxEventBits &= ~uxBitsToWaitFor;
229 if( xTicksToWait != ( TickType_t ) 0 )
231 traceEVENT_GROUP_SYNC_BLOCK( xEventGroup, uxBitsToSet, uxBitsToWaitFor );
233 /* Store the bits that the calling task is waiting for in the
234 * task's event list item so the kernel knows when a match is
235 * found. Then enter the blocked state. */
236 vTaskPlaceOnUnorderedEventList( &( pxEventBits->xTasksWaitingForBits ), ( uxBitsToWaitFor | eventCLEAR_EVENTS_ON_EXIT_BIT | eventWAIT_FOR_ALL_BITS ), xTicksToWait );
238 /* This assignment is obsolete as uxReturn will get set after
239 * the task unblocks, but some compilers mistakenly generate a
240 * warning about uxReturn being returned without being set if the
241 * assignment is omitted. */
246 /* The rendezvous bits were not set, but no block time was
247 * specified - just return the current event bit value. */
248 uxReturn = pxEventBits->uxEventBits;
249 xTimeoutOccurred = pdTRUE;
253 xAlreadyYielded = xTaskResumeAll();
255 if( xTicksToWait != ( TickType_t ) 0 )
257 if( xAlreadyYielded == pdFALSE )
259 taskYIELD_WITHIN_API();
263 mtCOVERAGE_TEST_MARKER();
266 /* The task blocked to wait for its required bits to be set - at this
267 * point either the required bits were set or the block time expired. If
268 * the required bits were set they will have been stored in the task's
269 * event list item, and they should now be retrieved then cleared. */
270 uxReturn = uxTaskResetEventItemValue();
272 if( ( uxReturn & eventUNBLOCKED_DUE_TO_BIT_SET ) == ( EventBits_t ) 0 )
274 /* The task timed out, just return the current event bit value. */
275 taskENTER_CRITICAL();
277 uxReturn = pxEventBits->uxEventBits;
279 /* Although the task got here because it timed out before the
280 * bits it was waiting for were set, it is possible that since it
281 * unblocked another task has set the bits. If this is the case
282 * then it needs to clear the bits before exiting. */
283 if( ( uxReturn & uxBitsToWaitFor ) == uxBitsToWaitFor )
285 pxEventBits->uxEventBits &= ~uxBitsToWaitFor;
289 mtCOVERAGE_TEST_MARKER();
294 xTimeoutOccurred = pdTRUE;
298 /* The task unblocked because the bits were set. */
301 /* Control bits might be set as the task had blocked should not be
303 uxReturn &= ~eventEVENT_BITS_CONTROL_BYTES;
306 traceEVENT_GROUP_SYNC_END( xEventGroup, uxBitsToSet, uxBitsToWaitFor, xTimeoutOccurred );
308 /* Prevent compiler warnings when trace macros are not used. */
309 ( void ) xTimeoutOccurred;
311 traceRETURN_xEventGroupSync( uxReturn );
315 /*-----------------------------------------------------------*/
317 EventBits_t xEventGroupWaitBits( EventGroupHandle_t xEventGroup,
318 const EventBits_t uxBitsToWaitFor,
319 const BaseType_t xClearOnExit,
320 const BaseType_t xWaitForAllBits,
321 TickType_t xTicksToWait )
323 EventGroup_t * pxEventBits = xEventGroup;
324 EventBits_t uxReturn, uxControlBits = 0;
325 BaseType_t xWaitConditionMet, xAlreadyYielded;
326 BaseType_t xTimeoutOccurred = pdFALSE;
328 traceENTER_xEventGroupWaitBits( xEventGroup, uxBitsToWaitFor, xClearOnExit, xWaitForAllBits, xTicksToWait );
330 /* Check the user is not attempting to wait on the bits used by the kernel
331 * itself, and that at least one bit is being requested. */
332 configASSERT( xEventGroup );
333 configASSERT( ( uxBitsToWaitFor & eventEVENT_BITS_CONTROL_BYTES ) == 0 );
334 configASSERT( uxBitsToWaitFor != 0 );
335 #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) )
337 configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) );
343 const EventBits_t uxCurrentEventBits = pxEventBits->uxEventBits;
345 /* Check to see if the wait condition is already met or not. */
346 xWaitConditionMet = prvTestWaitCondition( uxCurrentEventBits, uxBitsToWaitFor, xWaitForAllBits );
348 if( xWaitConditionMet != pdFALSE )
350 /* The wait condition has already been met so there is no need to
352 uxReturn = uxCurrentEventBits;
353 xTicksToWait = ( TickType_t ) 0;
355 /* Clear the wait bits if requested to do so. */
356 if( xClearOnExit != pdFALSE )
358 pxEventBits->uxEventBits &= ~uxBitsToWaitFor;
362 mtCOVERAGE_TEST_MARKER();
365 else if( xTicksToWait == ( TickType_t ) 0 )
367 /* The wait condition has not been met, but no block time was
368 * specified, so just return the current value. */
369 uxReturn = uxCurrentEventBits;
370 xTimeoutOccurred = pdTRUE;
374 /* The task is going to block to wait for its required bits to be
375 * set. uxControlBits are used to remember the specified behaviour of
376 * this call to xEventGroupWaitBits() - for use when the event bits
377 * unblock the task. */
378 if( xClearOnExit != pdFALSE )
380 uxControlBits |= eventCLEAR_EVENTS_ON_EXIT_BIT;
384 mtCOVERAGE_TEST_MARKER();
387 if( xWaitForAllBits != pdFALSE )
389 uxControlBits |= eventWAIT_FOR_ALL_BITS;
393 mtCOVERAGE_TEST_MARKER();
396 /* Store the bits that the calling task is waiting for in the
397 * task's event list item so the kernel knows when a match is
398 * found. Then enter the blocked state. */
399 vTaskPlaceOnUnorderedEventList( &( pxEventBits->xTasksWaitingForBits ), ( uxBitsToWaitFor | uxControlBits ), xTicksToWait );
401 /* This is obsolete as it will get set after the task unblocks, but
402 * some compilers mistakenly generate a warning about the variable
403 * being returned without being set if it is not done. */
406 traceEVENT_GROUP_WAIT_BITS_BLOCK( xEventGroup, uxBitsToWaitFor );
409 xAlreadyYielded = xTaskResumeAll();
411 if( xTicksToWait != ( TickType_t ) 0 )
413 if( xAlreadyYielded == pdFALSE )
415 taskYIELD_WITHIN_API();
419 mtCOVERAGE_TEST_MARKER();
422 /* The task blocked to wait for its required bits to be set - at this
423 * point either the required bits were set or the block time expired. If
424 * the required bits were set they will have been stored in the task's
425 * event list item, and they should now be retrieved then cleared. */
426 uxReturn = uxTaskResetEventItemValue();
428 if( ( uxReturn & eventUNBLOCKED_DUE_TO_BIT_SET ) == ( EventBits_t ) 0 )
430 taskENTER_CRITICAL();
432 /* The task timed out, just return the current event bit value. */
433 uxReturn = pxEventBits->uxEventBits;
435 /* It is possible that the event bits were updated between this
436 * task leaving the Blocked state and running again. */
437 if( prvTestWaitCondition( uxReturn, uxBitsToWaitFor, xWaitForAllBits ) != pdFALSE )
439 if( xClearOnExit != pdFALSE )
441 pxEventBits->uxEventBits &= ~uxBitsToWaitFor;
445 mtCOVERAGE_TEST_MARKER();
450 mtCOVERAGE_TEST_MARKER();
453 xTimeoutOccurred = pdTRUE;
459 /* The task unblocked because the bits were set. */
462 /* The task blocked so control bits may have been set. */
463 uxReturn &= ~eventEVENT_BITS_CONTROL_BYTES;
466 traceEVENT_GROUP_WAIT_BITS_END( xEventGroup, uxBitsToWaitFor, xTimeoutOccurred );
468 /* Prevent compiler warnings when trace macros are not used. */
469 ( void ) xTimeoutOccurred;
471 traceRETURN_xEventGroupWaitBits( uxReturn );
475 /*-----------------------------------------------------------*/
477 EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup,
478 const EventBits_t uxBitsToClear )
480 EventGroup_t * pxEventBits = xEventGroup;
481 EventBits_t uxReturn;
483 traceENTER_xEventGroupClearBits( xEventGroup, uxBitsToClear );
485 /* Check the user is not attempting to clear the bits used by the kernel
487 configASSERT( xEventGroup );
488 configASSERT( ( uxBitsToClear & eventEVENT_BITS_CONTROL_BYTES ) == 0 );
490 taskENTER_CRITICAL();
492 traceEVENT_GROUP_CLEAR_BITS( xEventGroup, uxBitsToClear );
494 /* The value returned is the event group value prior to the bits being
496 uxReturn = pxEventBits->uxEventBits;
498 /* Clear the bits. */
499 pxEventBits->uxEventBits &= ~uxBitsToClear;
503 traceRETURN_xEventGroupClearBits( uxReturn );
507 /*-----------------------------------------------------------*/
509 #if ( ( configUSE_TRACE_FACILITY == 1 ) && ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) )
511 BaseType_t xEventGroupClearBitsFromISR( EventGroupHandle_t xEventGroup,
512 const EventBits_t uxBitsToClear )
516 traceENTER_xEventGroupClearBitsFromISR( xEventGroup, uxBitsToClear );
518 traceEVENT_GROUP_CLEAR_BITS_FROM_ISR( xEventGroup, uxBitsToClear );
519 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. */
521 traceRETURN_xEventGroupClearBitsFromISR( xReturn );
526 #endif /* if ( ( configUSE_TRACE_FACILITY == 1 ) && ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) ) */
527 /*-----------------------------------------------------------*/
529 EventBits_t xEventGroupGetBitsFromISR( EventGroupHandle_t xEventGroup )
531 UBaseType_t uxSavedInterruptStatus;
532 EventGroup_t const * const pxEventBits = xEventGroup;
533 EventBits_t uxReturn;
535 traceENTER_xEventGroupGetBitsFromISR( xEventGroup );
537 uxSavedInterruptStatus = taskENTER_CRITICAL_FROM_ISR();
539 uxReturn = pxEventBits->uxEventBits;
541 taskEXIT_CRITICAL_FROM_ISR( uxSavedInterruptStatus );
543 traceRETURN_xEventGroupGetBitsFromISR( uxReturn );
546 } /*lint !e818 EventGroupHandle_t is a typedef used in other functions to so can't be pointer to const. */
547 /*-----------------------------------------------------------*/
549 EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup,
550 const EventBits_t uxBitsToSet )
552 ListItem_t * pxListItem;
554 ListItem_t const * pxListEnd;
555 List_t const * pxList;
556 EventBits_t uxBitsToClear = 0, uxBitsWaitedFor, uxControlBits;
557 EventGroup_t * pxEventBits = xEventGroup;
558 BaseType_t xMatchFound = pdFALSE;
560 traceENTER_xEventGroupSetBits( xEventGroup, uxBitsToSet );
562 /* Check the user is not attempting to set the bits used by the kernel
564 configASSERT( xEventGroup );
565 configASSERT( ( uxBitsToSet & eventEVENT_BITS_CONTROL_BYTES ) == 0 );
567 pxList = &( pxEventBits->xTasksWaitingForBits );
568 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. */
571 traceEVENT_GROUP_SET_BITS( xEventGroup, uxBitsToSet );
573 pxListItem = listGET_HEAD_ENTRY( pxList );
576 pxEventBits->uxEventBits |= uxBitsToSet;
578 /* See if the new bit value should unblock any tasks. */
579 while( pxListItem != pxListEnd )
581 pxNext = listGET_NEXT( pxListItem );
582 uxBitsWaitedFor = listGET_LIST_ITEM_VALUE( pxListItem );
583 xMatchFound = pdFALSE;
585 /* Split the bits waited for from the control bits. */
586 uxControlBits = uxBitsWaitedFor & eventEVENT_BITS_CONTROL_BYTES;
587 uxBitsWaitedFor &= ~eventEVENT_BITS_CONTROL_BYTES;
589 if( ( uxControlBits & eventWAIT_FOR_ALL_BITS ) == ( EventBits_t ) 0 )
591 /* Just looking for single bit being set. */
592 if( ( uxBitsWaitedFor & pxEventBits->uxEventBits ) != ( EventBits_t ) 0 )
594 xMatchFound = pdTRUE;
598 mtCOVERAGE_TEST_MARKER();
601 else if( ( uxBitsWaitedFor & pxEventBits->uxEventBits ) == uxBitsWaitedFor )
603 /* All bits are set. */
604 xMatchFound = pdTRUE;
608 /* Need all bits to be set, but not all the bits were set. */
611 if( xMatchFound != pdFALSE )
613 /* The bits match. Should the bits be cleared on exit? */
614 if( ( uxControlBits & eventCLEAR_EVENTS_ON_EXIT_BIT ) != ( EventBits_t ) 0 )
616 uxBitsToClear |= uxBitsWaitedFor;
620 mtCOVERAGE_TEST_MARKER();
623 /* Store the actual event flag value in the task's event list
624 * item before removing the task from the event list. The
625 * eventUNBLOCKED_DUE_TO_BIT_SET bit is set so the task knows
626 * that is was unblocked due to its required bits matching, rather
627 * than because it timed out. */
628 vTaskRemoveFromUnorderedEventList( pxListItem, pxEventBits->uxEventBits | eventUNBLOCKED_DUE_TO_BIT_SET );
631 /* Move onto the next list item. Note pxListItem->pxNext is not
632 * used here as the list item may have been removed from the event list
633 * and inserted into the ready/pending reading list. */
637 /* Clear any bits that matched when the eventCLEAR_EVENTS_ON_EXIT_BIT
638 * bit was set in the control word. */
639 pxEventBits->uxEventBits &= ~uxBitsToClear;
641 ( void ) xTaskResumeAll();
643 traceRETURN_xEventGroupSetBits( pxEventBits->uxEventBits );
645 return pxEventBits->uxEventBits;
647 /*-----------------------------------------------------------*/
649 void vEventGroupDelete( EventGroupHandle_t xEventGroup )
651 EventGroup_t * pxEventBits = xEventGroup;
652 const List_t * pxTasksWaitingForBits;
654 traceENTER_vEventGroupDelete( xEventGroup );
656 configASSERT( pxEventBits );
658 pxTasksWaitingForBits = &( pxEventBits->xTasksWaitingForBits );
662 traceEVENT_GROUP_DELETE( xEventGroup );
664 while( listCURRENT_LIST_LENGTH( pxTasksWaitingForBits ) > ( UBaseType_t ) 0 )
666 /* Unblock the task, returning 0 as the event list is being deleted
667 * and cannot therefore have any bits set. */
668 configASSERT( pxTasksWaitingForBits->xListEnd.pxNext != ( const ListItem_t * ) &( pxTasksWaitingForBits->xListEnd ) );
669 vTaskRemoveFromUnorderedEventList( pxTasksWaitingForBits->xListEnd.pxNext, eventUNBLOCKED_DUE_TO_BIT_SET );
672 ( void ) xTaskResumeAll();
674 #if ( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 0 ) )
676 /* The event group can only have been allocated dynamically - free
678 vPortFree( pxEventBits );
680 #elif ( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) )
682 /* The event group could have been allocated statically or
683 * dynamically, so check before attempting to free the memory. */
684 if( pxEventBits->ucStaticallyAllocated == ( uint8_t ) pdFALSE )
686 vPortFree( pxEventBits );
690 mtCOVERAGE_TEST_MARKER();
693 #endif /* configSUPPORT_DYNAMIC_ALLOCATION */
695 traceRETURN_vEventGroupDelete();
697 /*-----------------------------------------------------------*/
699 #if ( configSUPPORT_STATIC_ALLOCATION == 1 )
700 BaseType_t xEventGroupGetStaticBuffer( EventGroupHandle_t xEventGroup,
701 StaticEventGroup_t ** ppxEventGroupBuffer )
704 EventGroup_t * pxEventBits = xEventGroup;
706 traceENTER_xEventGroupGetStaticBuffer( xEventGroup, ppxEventGroupBuffer );
708 configASSERT( pxEventBits );
709 configASSERT( ppxEventGroupBuffer );
711 #if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
713 /* Check if the event group was statically allocated. */
714 if( pxEventBits->ucStaticallyAllocated == ( uint8_t ) pdTRUE )
716 /* MISRA Ref 11.3.1 [Misaligned access] */
717 /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-113 */
718 /* coverity[misra_c_2012_rule_11_3_violation] */
719 *ppxEventGroupBuffer = ( StaticEventGroup_t * ) pxEventBits;
727 #else /* configSUPPORT_DYNAMIC_ALLOCATION */
729 /* Event group must have been statically allocated. */
730 /* MISRA Ref 11.3.1 [Misaligned access] */
731 /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-113 */
732 /* coverity[misra_c_2012_rule_11_3_violation] */
733 *ppxEventGroupBuffer = ( StaticEventGroup_t * ) pxEventBits;
736 #endif /* configSUPPORT_DYNAMIC_ALLOCATION */
738 traceRETURN_xEventGroupGetStaticBuffer( xReturn );
742 #endif /* configSUPPORT_STATIC_ALLOCATION */
743 /*-----------------------------------------------------------*/
745 /* For internal use only - execute a 'set bits' command that was pended from
747 void vEventGroupSetBitsCallback( void * pvEventGroup,
748 const uint32_t ulBitsToSet )
750 traceENTER_vEventGroupSetBitsCallback( pvEventGroup, ulBitsToSet );
752 ( void ) xEventGroupSetBits( pvEventGroup, ( EventBits_t ) ulBitsToSet ); /*lint !e9079 Can't avoid cast to void* as a generic timer callback prototype. Callback casts back to original type so safe. */
754 traceRETURN_vEventGroupSetBitsCallback();
756 /*-----------------------------------------------------------*/
758 /* For internal use only - execute a 'clear bits' command that was pended from
760 void vEventGroupClearBitsCallback( void * pvEventGroup,
761 const uint32_t ulBitsToClear )
763 traceENTER_vEventGroupClearBitsCallback( pvEventGroup, ulBitsToClear );
765 ( void ) xEventGroupClearBits( pvEventGroup, ( EventBits_t ) ulBitsToClear ); /*lint !e9079 Can't avoid cast to void* as a generic timer callback prototype. Callback casts back to original type so safe. */
767 traceRETURN_vEventGroupClearBitsCallback();
769 /*-----------------------------------------------------------*/
771 static BaseType_t prvTestWaitCondition( const EventBits_t uxCurrentEventBits,
772 const EventBits_t uxBitsToWaitFor,
773 const BaseType_t xWaitForAllBits )
775 BaseType_t xWaitConditionMet = pdFALSE;
777 if( xWaitForAllBits == pdFALSE )
779 /* Task only has to wait for one bit within uxBitsToWaitFor to be
780 * set. Is one already set? */
781 if( ( uxCurrentEventBits & uxBitsToWaitFor ) != ( EventBits_t ) 0 )
783 xWaitConditionMet = pdTRUE;
787 mtCOVERAGE_TEST_MARKER();
792 /* Task has to wait for all the bits in uxBitsToWaitFor to be set.
793 * Are they set already? */
794 if( ( uxCurrentEventBits & uxBitsToWaitFor ) == uxBitsToWaitFor )
796 xWaitConditionMet = pdTRUE;
800 mtCOVERAGE_TEST_MARKER();
804 return xWaitConditionMet;
806 /*-----------------------------------------------------------*/
808 #if ( ( configUSE_TRACE_FACILITY == 1 ) && ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) )
810 BaseType_t xEventGroupSetBitsFromISR( EventGroupHandle_t xEventGroup,
811 const EventBits_t uxBitsToSet,
812 BaseType_t * pxHigherPriorityTaskWoken )
816 traceENTER_xEventGroupSetBitsFromISR( xEventGroup, uxBitsToSet, pxHigherPriorityTaskWoken );
818 traceEVENT_GROUP_SET_BITS_FROM_ISR( xEventGroup, uxBitsToSet );
819 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. */
821 traceRETURN_xEventGroupSetBitsFromISR( xReturn );
826 #endif /* if ( ( configUSE_TRACE_FACILITY == 1 ) && ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) ) */
827 /*-----------------------------------------------------------*/
829 #if ( configUSE_TRACE_FACILITY == 1 )
831 UBaseType_t uxEventGroupGetNumber( void * xEventGroup )
834 EventGroup_t const * pxEventBits = ( EventGroup_t * ) xEventGroup; /*lint !e9087 !e9079 EventGroupHandle_t is a pointer to an EventGroup_t, but EventGroupHandle_t is kept opaque outside of this file for data hiding purposes. */
836 traceENTER_uxEventGroupGetNumber( xEventGroup );
838 if( xEventGroup == NULL )
844 xReturn = pxEventBits->uxEventGroupNumber;
847 traceRETURN_uxEventGroupGetNumber( xReturn );
852 #endif /* configUSE_TRACE_FACILITY */
853 /*-----------------------------------------------------------*/
855 #if ( configUSE_TRACE_FACILITY == 1 )
857 void vEventGroupSetNumber( void * xEventGroup,
858 UBaseType_t uxEventGroupNumber )
860 traceENTER_vEventGroupSetNumber( xEventGroup, uxEventGroupNumber );
862 ( ( EventGroup_t * ) xEventGroup )->uxEventGroupNumber = uxEventGroupNumber; /*lint !e9087 !e9079 EventGroupHandle_t is a pointer to an EventGroup_t, but EventGroupHandle_t is kept opaque outside of this file for data hiding purposes. */
864 traceRETURN_vEventGroupSetNumber();
867 #endif /* configUSE_TRACE_FACILITY */
868 /*-----------------------------------------------------------*/