]> begriffs open source - cmsis-freertos/blob - Source/event_groups.c
updated to PACK.xsd from CMSIS.5.3.0
[cmsis-freertos] / Source / event_groups.c
1 /*
2  * FreeRTOS Kernel V10.0.1
3  * Copyright (C) 2017 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  * http://www.FreeRTOS.org
23  * http://aws.amazon.com/freertos
24  *
25  * 1 tab == 4 spaces!
26  */
27
28 /* Standard includes. */
29 #include <stdlib.h>
30
31 /* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining
32 all the API functions to use the MPU wrappers.  That should only be done when
33 task.h is included from an application file. */
34 #define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
35
36 /* FreeRTOS includes. */
37 #include "FreeRTOS.h"
38 #include "task.h"
39 #include "timers.h"
40 #include "event_groups.h"
41
42 /* Lint e961 and e750 are suppressed as a MISRA exception justified because the
43 MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined for the
44 header files above, but not in this file, in order to generate the correct
45 privileged Vs unprivileged linkage and placement. */
46 #undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE /*lint !e961 !e750. */
47
48 /* The following bit fields convey control information in a task's event list
49 item value.  It is important they don't clash with the
50 taskEVENT_LIST_ITEM_VALUE_IN_USE definition. */
51 #if configUSE_16_BIT_TICKS == 1
52         #define eventCLEAR_EVENTS_ON_EXIT_BIT   0x0100U
53         #define eventUNBLOCKED_DUE_TO_BIT_SET   0x0200U
54         #define eventWAIT_FOR_ALL_BITS                  0x0400U
55         #define eventEVENT_BITS_CONTROL_BYTES   0xff00U
56 #else
57         #define eventCLEAR_EVENTS_ON_EXIT_BIT   0x01000000UL
58         #define eventUNBLOCKED_DUE_TO_BIT_SET   0x02000000UL
59         #define eventWAIT_FOR_ALL_BITS                  0x04000000UL
60         #define eventEVENT_BITS_CONTROL_BYTES   0xff000000UL
61 #endif
62
63 typedef struct xEventGroupDefinition
64 {
65         EventBits_t uxEventBits;
66         List_t xTasksWaitingForBits;            /*< List of tasks waiting for a bit to be set. */
67
68         #if( configUSE_TRACE_FACILITY == 1 )
69                 UBaseType_t uxEventGroupNumber;
70         #endif
71
72         #if( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )
73                 uint8_t ucStaticallyAllocated; /*< Set to pdTRUE if the event group is statically allocated to ensure no attempt is made to free the memory. */
74         #endif
75 } EventGroup_t;
76
77 /*-----------------------------------------------------------*/
78
79 /*
80  * Test the bits set in uxCurrentEventBits to see if the wait condition is met.
81  * The wait condition is defined by xWaitForAllBits.  If xWaitForAllBits is
82  * pdTRUE then the wait condition is met if all the bits set in uxBitsToWaitFor
83  * are also set in uxCurrentEventBits.  If xWaitForAllBits is pdFALSE then the
84  * wait condition is met if any of the bits set in uxBitsToWait for are also set
85  * in uxCurrentEventBits.
86  */
87 static BaseType_t prvTestWaitCondition( const EventBits_t uxCurrentEventBits, const EventBits_t uxBitsToWaitFor, const BaseType_t xWaitForAllBits ) PRIVILEGED_FUNCTION;
88
89 /*-----------------------------------------------------------*/
90
91 #if( configSUPPORT_STATIC_ALLOCATION == 1 )
92
93         EventGroupHandle_t xEventGroupCreateStatic( StaticEventGroup_t *pxEventGroupBuffer )
94         {
95         EventGroup_t *pxEventBits;
96
97                 /* A StaticEventGroup_t object must be provided. */
98                 configASSERT( pxEventGroupBuffer );
99
100                 #if( configASSERT_DEFINED == 1 )
101                 {
102                         /* Sanity check that the size of the structure used to declare a
103                         variable of type StaticEventGroup_t equals the size of the real
104                         event group structure. */
105                         volatile size_t xSize = sizeof( StaticEventGroup_t );
106                         configASSERT( xSize == sizeof( EventGroup_t ) );
107                 }
108                 #endif /* configASSERT_DEFINED */
109
110                 /* The user has provided a statically allocated event group - use it. */
111                 pxEventBits = ( EventGroup_t * ) pxEventGroupBuffer; /*lint !e740 EventGroup_t and StaticEventGroup_t are guaranteed to have the same size and alignment requirement - checked by configASSERT(). */
112
113                 if( pxEventBits != NULL )
114                 {
115                         pxEventBits->uxEventBits = 0;
116                         vListInitialise( &( pxEventBits->xTasksWaitingForBits ) );
117
118                         #if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
119                         {
120                                 /* Both static and dynamic allocation can be used, so note that
121                                 this event group was created statically in case the event group
122                                 is later deleted. */
123                                 pxEventBits->ucStaticallyAllocated = pdTRUE;
124                         }
125                         #endif /* configSUPPORT_DYNAMIC_ALLOCATION */
126
127                         traceEVENT_GROUP_CREATE( pxEventBits );
128                 }
129                 else
130                 {
131                         traceEVENT_GROUP_CREATE_FAILED();
132                 }
133
134                 return ( EventGroupHandle_t ) pxEventBits;
135         }
136
137 #endif /* configSUPPORT_STATIC_ALLOCATION */
138 /*-----------------------------------------------------------*/
139
140 #if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
141
142         EventGroupHandle_t xEventGroupCreate( void )
143         {
144         EventGroup_t *pxEventBits;
145
146                 /* Allocate the event group. */
147                 pxEventBits = ( EventGroup_t * ) pvPortMalloc( sizeof( EventGroup_t ) );
148
149                 if( pxEventBits != NULL )
150                 {
151                         pxEventBits->uxEventBits = 0;
152                         vListInitialise( &( pxEventBits->xTasksWaitingForBits ) );
153
154                         #if( configSUPPORT_STATIC_ALLOCATION == 1 )
155                         {
156                                 /* Both static and dynamic allocation can be used, so note this
157                                 event group was allocated statically in case the event group is
158                                 later deleted. */
159                                 pxEventBits->ucStaticallyAllocated = pdFALSE;
160                         }
161                         #endif /* configSUPPORT_STATIC_ALLOCATION */
162
163                         traceEVENT_GROUP_CREATE( pxEventBits );
164                 }
165                 else
166                 {
167                         traceEVENT_GROUP_CREATE_FAILED();
168                 }
169
170                 return ( EventGroupHandle_t ) pxEventBits;
171         }
172
173 #endif /* configSUPPORT_DYNAMIC_ALLOCATION */
174 /*-----------------------------------------------------------*/
175
176 EventBits_t xEventGroupSync( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet, const EventBits_t uxBitsToWaitFor, TickType_t xTicksToWait )
177 {
178 EventBits_t uxOriginalBitValue, uxReturn;
179 EventGroup_t *pxEventBits = ( EventGroup_t * ) xEventGroup;
180 BaseType_t xAlreadyYielded;
181 BaseType_t xTimeoutOccurred = pdFALSE;
182
183         configASSERT( ( uxBitsToWaitFor & eventEVENT_BITS_CONTROL_BYTES ) == 0 );
184         configASSERT( uxBitsToWaitFor != 0 );
185         #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) )
186         {
187                 configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) );
188         }
189         #endif
190
191         vTaskSuspendAll();
192         {
193                 uxOriginalBitValue = pxEventBits->uxEventBits;
194
195                 ( void ) xEventGroupSetBits( xEventGroup, uxBitsToSet );
196
197                 if( ( ( uxOriginalBitValue | uxBitsToSet ) & uxBitsToWaitFor ) == uxBitsToWaitFor )
198                 {
199                         /* All the rendezvous bits are now set - no need to block. */
200                         uxReturn = ( uxOriginalBitValue | uxBitsToSet );
201
202                         /* Rendezvous always clear the bits.  They will have been cleared
203                         already unless this is the only task in the rendezvous. */
204                         pxEventBits->uxEventBits &= ~uxBitsToWaitFor;
205
206                         xTicksToWait = 0;
207                 }
208                 else
209                 {
210                         if( xTicksToWait != ( TickType_t ) 0 )
211                         {
212                                 traceEVENT_GROUP_SYNC_BLOCK( xEventGroup, uxBitsToSet, uxBitsToWaitFor );
213
214                                 /* Store the bits that the calling task is waiting for in the
215                                 task's event list item so the kernel knows when a match is
216                                 found.  Then enter the blocked state. */
217                                 vTaskPlaceOnUnorderedEventList( &( pxEventBits->xTasksWaitingForBits ), ( uxBitsToWaitFor | eventCLEAR_EVENTS_ON_EXIT_BIT | eventWAIT_FOR_ALL_BITS ), xTicksToWait );
218
219                                 /* This assignment is obsolete as uxReturn will get set after
220                                 the task unblocks, but some compilers mistakenly generate a
221                                 warning about uxReturn being returned without being set if the
222                                 assignment is omitted. */
223                                 uxReturn = 0;
224                         }
225                         else
226                         {
227                                 /* The rendezvous bits were not set, but no block time was
228                                 specified - just return the current event bit value. */
229                                 uxReturn = pxEventBits->uxEventBits;
230                                 xTimeoutOccurred = pdTRUE;
231                         }
232                 }
233         }
234         xAlreadyYielded = xTaskResumeAll();
235
236         if( xTicksToWait != ( TickType_t ) 0 )
237         {
238                 if( xAlreadyYielded == pdFALSE )
239                 {
240                         portYIELD_WITHIN_API();
241                 }
242                 else
243                 {
244                         mtCOVERAGE_TEST_MARKER();
245                 }
246
247                 /* The task blocked to wait for its required bits to be set - at this
248                 point either the required bits were set or the block time expired.  If
249                 the required bits were set they will have been stored in the task's
250                 event list item, and they should now be retrieved then cleared. */
251                 uxReturn = uxTaskResetEventItemValue();
252
253                 if( ( uxReturn & eventUNBLOCKED_DUE_TO_BIT_SET ) == ( EventBits_t ) 0 )
254                 {
255                         /* The task timed out, just return the current event bit value. */
256                         taskENTER_CRITICAL();
257                         {
258                                 uxReturn = pxEventBits->uxEventBits;
259
260                                 /* Although the task got here because it timed out before the
261                                 bits it was waiting for were set, it is possible that since it
262                                 unblocked another task has set the bits.  If this is the case
263                                 then it needs to clear the bits before exiting. */
264                                 if( ( uxReturn & uxBitsToWaitFor ) == uxBitsToWaitFor )
265                                 {
266                                         pxEventBits->uxEventBits &= ~uxBitsToWaitFor;
267                                 }
268                                 else
269                                 {
270                                         mtCOVERAGE_TEST_MARKER();
271                                 }
272                         }
273                         taskEXIT_CRITICAL();
274
275                         xTimeoutOccurred = pdTRUE;
276                 }
277                 else
278                 {
279                         /* The task unblocked because the bits were set. */
280                 }
281
282                 /* Control bits might be set as the task had blocked should not be
283                 returned. */
284                 uxReturn &= ~eventEVENT_BITS_CONTROL_BYTES;
285         }
286
287         traceEVENT_GROUP_SYNC_END( xEventGroup, uxBitsToSet, uxBitsToWaitFor, xTimeoutOccurred );
288
289         /* Prevent compiler warnings when trace macros are not used. */
290         ( void ) xTimeoutOccurred;
291
292         return uxReturn;
293 }
294 /*-----------------------------------------------------------*/
295
296 EventBits_t xEventGroupWaitBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToWaitFor, const BaseType_t xClearOnExit, const BaseType_t xWaitForAllBits, TickType_t xTicksToWait )
297 {
298 EventGroup_t *pxEventBits = ( EventGroup_t * ) xEventGroup;
299 EventBits_t uxReturn, uxControlBits = 0;
300 BaseType_t xWaitConditionMet, xAlreadyYielded;
301 BaseType_t xTimeoutOccurred = pdFALSE;
302
303         /* Check the user is not attempting to wait on the bits used by the kernel
304         itself, and that at least one bit is being requested. */
305         configASSERT( xEventGroup );
306         configASSERT( ( uxBitsToWaitFor & eventEVENT_BITS_CONTROL_BYTES ) == 0 );
307         configASSERT( uxBitsToWaitFor != 0 );
308         #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) )
309         {
310                 configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) );
311         }
312         #endif
313
314         vTaskSuspendAll();
315         {
316                 const EventBits_t uxCurrentEventBits = pxEventBits->uxEventBits;
317
318                 /* Check to see if the wait condition is already met or not. */
319                 xWaitConditionMet = prvTestWaitCondition( uxCurrentEventBits, uxBitsToWaitFor, xWaitForAllBits );
320
321                 if( xWaitConditionMet != pdFALSE )
322                 {
323                         /* The wait condition has already been met so there is no need to
324                         block. */
325                         uxReturn = uxCurrentEventBits;
326                         xTicksToWait = ( TickType_t ) 0;
327
328                         /* Clear the wait bits if requested to do so. */
329                         if( xClearOnExit != pdFALSE )
330                         {
331                                 pxEventBits->uxEventBits &= ~uxBitsToWaitFor;
332                         }
333                         else
334                         {
335                                 mtCOVERAGE_TEST_MARKER();
336                         }
337                 }
338                 else if( xTicksToWait == ( TickType_t ) 0 )
339                 {
340                         /* The wait condition has not been met, but no block time was
341                         specified, so just return the current value. */
342                         uxReturn = uxCurrentEventBits;
343                         xTimeoutOccurred = pdTRUE;
344                 }
345                 else
346                 {
347                         /* The task is going to block to wait for its required bits to be
348                         set.  uxControlBits are used to remember the specified behaviour of
349                         this call to xEventGroupWaitBits() - for use when the event bits
350                         unblock the task. */
351                         if( xClearOnExit != pdFALSE )
352                         {
353                                 uxControlBits |= eventCLEAR_EVENTS_ON_EXIT_BIT;
354                         }
355                         else
356                         {
357                                 mtCOVERAGE_TEST_MARKER();
358                         }
359
360                         if( xWaitForAllBits != pdFALSE )
361                         {
362                                 uxControlBits |= eventWAIT_FOR_ALL_BITS;
363                         }
364                         else
365                         {
366                                 mtCOVERAGE_TEST_MARKER();
367                         }
368
369                         /* Store the bits that the calling task is waiting for in the
370                         task's event list item so the kernel knows when a match is
371                         found.  Then enter the blocked state. */
372                         vTaskPlaceOnUnorderedEventList( &( pxEventBits->xTasksWaitingForBits ), ( uxBitsToWaitFor | uxControlBits ), xTicksToWait );
373
374                         /* This is obsolete as it will get set after the task unblocks, but
375                         some compilers mistakenly generate a warning about the variable
376                         being returned without being set if it is not done. */
377                         uxReturn = 0;
378
379                         traceEVENT_GROUP_WAIT_BITS_BLOCK( xEventGroup, uxBitsToWaitFor );
380                 }
381         }
382         xAlreadyYielded = xTaskResumeAll();
383
384         if( xTicksToWait != ( TickType_t ) 0 )
385         {
386                 if( xAlreadyYielded == pdFALSE )
387                 {
388                         portYIELD_WITHIN_API();
389                 }
390                 else
391                 {
392                         mtCOVERAGE_TEST_MARKER();
393                 }
394
395                 /* The task blocked to wait for its required bits to be set - at this
396                 point either the required bits were set or the block time expired.  If
397                 the required bits were set they will have been stored in the task's
398                 event list item, and they should now be retrieved then cleared. */
399                 uxReturn = uxTaskResetEventItemValue();
400
401                 if( ( uxReturn & eventUNBLOCKED_DUE_TO_BIT_SET ) == ( EventBits_t ) 0 )
402                 {
403                         taskENTER_CRITICAL();
404                         {
405                                 /* The task timed out, just return the current event bit value. */
406                                 uxReturn = pxEventBits->uxEventBits;
407
408                                 /* It is possible that the event bits were updated between this
409                                 task leaving the Blocked state and running again. */
410                                 if( prvTestWaitCondition( uxReturn, uxBitsToWaitFor, xWaitForAllBits ) != pdFALSE )
411                                 {
412                                         if( xClearOnExit != pdFALSE )
413                                         {
414                                                 pxEventBits->uxEventBits &= ~uxBitsToWaitFor;
415                                         }
416                                         else
417                                         {
418                                                 mtCOVERAGE_TEST_MARKER();
419                                         }
420                                 }
421                                 else
422                                 {
423                                         mtCOVERAGE_TEST_MARKER();
424                                 }
425                                 xTimeoutOccurred = pdTRUE;
426                         }
427                         taskEXIT_CRITICAL();
428                 }
429                 else
430                 {
431                         /* The task unblocked because the bits were set. */
432                 }
433
434                 /* The task blocked so control bits may have been set. */
435                 uxReturn &= ~eventEVENT_BITS_CONTROL_BYTES;
436         }
437         traceEVENT_GROUP_WAIT_BITS_END( xEventGroup, uxBitsToWaitFor, xTimeoutOccurred );
438
439         /* Prevent compiler warnings when trace macros are not used. */
440         ( void ) xTimeoutOccurred;
441
442         return uxReturn;
443 }
444 /*-----------------------------------------------------------*/
445
446 EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToClear )
447 {
448 EventGroup_t *pxEventBits = ( EventGroup_t * ) xEventGroup;
449 EventBits_t uxReturn;
450
451         /* Check the user is not attempting to clear the bits used by the kernel
452         itself. */
453         configASSERT( xEventGroup );
454         configASSERT( ( uxBitsToClear & eventEVENT_BITS_CONTROL_BYTES ) == 0 );
455
456         taskENTER_CRITICAL();
457         {
458                 traceEVENT_GROUP_CLEAR_BITS( xEventGroup, uxBitsToClear );
459
460                 /* The value returned is the event group value prior to the bits being
461                 cleared. */
462                 uxReturn = pxEventBits->uxEventBits;
463
464                 /* Clear the bits. */
465                 pxEventBits->uxEventBits &= ~uxBitsToClear;
466         }
467         taskEXIT_CRITICAL();
468
469         return uxReturn;
470 }
471 /*-----------------------------------------------------------*/
472
473 #if ( ( configUSE_TRACE_FACILITY == 1 ) && ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) )
474
475         BaseType_t xEventGroupClearBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToClear )
476         {
477                 BaseType_t xReturn;
478
479                 traceEVENT_GROUP_CLEAR_BITS_FROM_ISR( xEventGroup, uxBitsToClear );
480                 xReturn = xTimerPendFunctionCallFromISR( vEventGroupClearBitsCallback, ( void * ) xEventGroup, ( uint32_t ) uxBitsToClear, NULL );
481
482                 return xReturn;
483         }
484
485 #endif
486 /*-----------------------------------------------------------*/
487
488 EventBits_t xEventGroupGetBitsFromISR( EventGroupHandle_t xEventGroup )
489 {
490 UBaseType_t uxSavedInterruptStatus;
491 EventGroup_t *pxEventBits = ( EventGroup_t * ) xEventGroup;
492 EventBits_t uxReturn;
493
494         uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
495         {
496                 uxReturn = pxEventBits->uxEventBits;
497         }
498         portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
499
500         return uxReturn;
501 }
502 /*-----------------------------------------------------------*/
503
504 EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet )
505 {
506 ListItem_t *pxListItem, *pxNext;
507 ListItem_t const *pxListEnd;
508 List_t *pxList;
509 EventBits_t uxBitsToClear = 0, uxBitsWaitedFor, uxControlBits;
510 EventGroup_t *pxEventBits = ( EventGroup_t * ) xEventGroup;
511 BaseType_t xMatchFound = pdFALSE;
512
513         /* Check the user is not attempting to set the bits used by the kernel
514         itself. */
515         configASSERT( xEventGroup );
516         configASSERT( ( uxBitsToSet & eventEVENT_BITS_CONTROL_BYTES ) == 0 );
517
518         pxList = &( pxEventBits->xTasksWaitingForBits );
519         pxListEnd = listGET_END_MARKER( pxList ); /*lint !e826 !e740 The mini list structure is used as the list end to save RAM.  This is checked and valid. */
520         vTaskSuspendAll();
521         {
522                 traceEVENT_GROUP_SET_BITS( xEventGroup, uxBitsToSet );
523
524                 pxListItem = listGET_HEAD_ENTRY( pxList );
525
526                 /* Set the bits. */
527                 pxEventBits->uxEventBits |= uxBitsToSet;
528
529                 /* See if the new bit value should unblock any tasks. */
530                 while( pxListItem != pxListEnd )
531                 {
532                         pxNext = listGET_NEXT( pxListItem );
533                         uxBitsWaitedFor = listGET_LIST_ITEM_VALUE( pxListItem );
534                         xMatchFound = pdFALSE;
535
536                         /* Split the bits waited for from the control bits. */
537                         uxControlBits = uxBitsWaitedFor & eventEVENT_BITS_CONTROL_BYTES;
538                         uxBitsWaitedFor &= ~eventEVENT_BITS_CONTROL_BYTES;
539
540                         if( ( uxControlBits & eventWAIT_FOR_ALL_BITS ) == ( EventBits_t ) 0 )
541                         {
542                                 /* Just looking for single bit being set. */
543                                 if( ( uxBitsWaitedFor & pxEventBits->uxEventBits ) != ( EventBits_t ) 0 )
544                                 {
545                                         xMatchFound = pdTRUE;
546                                 }
547                                 else
548                                 {
549                                         mtCOVERAGE_TEST_MARKER();
550                                 }
551                         }
552                         else if( ( uxBitsWaitedFor & pxEventBits->uxEventBits ) == uxBitsWaitedFor )
553                         {
554                                 /* All bits are set. */
555                                 xMatchFound = pdTRUE;
556                         }
557                         else
558                         {
559                                 /* Need all bits to be set, but not all the bits were set. */
560                         }
561
562                         if( xMatchFound != pdFALSE )
563                         {
564                                 /* The bits match.  Should the bits be cleared on exit? */
565                                 if( ( uxControlBits & eventCLEAR_EVENTS_ON_EXIT_BIT ) != ( EventBits_t ) 0 )
566                                 {
567                                         uxBitsToClear |= uxBitsWaitedFor;
568                                 }
569                                 else
570                                 {
571                                         mtCOVERAGE_TEST_MARKER();
572                                 }
573
574                                 /* Store the actual event flag value in the task's event list
575                                 item before removing the task from the event list.  The
576                                 eventUNBLOCKED_DUE_TO_BIT_SET bit is set so the task knows
577                                 that is was unblocked due to its required bits matching, rather
578                                 than because it timed out. */
579                                 vTaskRemoveFromUnorderedEventList( pxListItem, pxEventBits->uxEventBits | eventUNBLOCKED_DUE_TO_BIT_SET );
580                         }
581
582                         /* Move onto the next list item.  Note pxListItem->pxNext is not
583                         used here as the list item may have been removed from the event list
584                         and inserted into the ready/pending reading list. */
585                         pxListItem = pxNext;
586                 }
587
588                 /* Clear any bits that matched when the eventCLEAR_EVENTS_ON_EXIT_BIT
589                 bit was set in the control word. */
590                 pxEventBits->uxEventBits &= ~uxBitsToClear;
591         }
592         ( void ) xTaskResumeAll();
593
594         return pxEventBits->uxEventBits;
595 }
596 /*-----------------------------------------------------------*/
597
598 void vEventGroupDelete( EventGroupHandle_t xEventGroup )
599 {
600 EventGroup_t *pxEventBits = ( EventGroup_t * ) xEventGroup;
601 const List_t *pxTasksWaitingForBits = &( pxEventBits->xTasksWaitingForBits );
602
603         vTaskSuspendAll();
604         {
605                 traceEVENT_GROUP_DELETE( xEventGroup );
606
607                 while( listCURRENT_LIST_LENGTH( pxTasksWaitingForBits ) > ( UBaseType_t ) 0 )
608                 {
609                         /* Unblock the task, returning 0 as the event list is being deleted
610                         and cannot therefore have any bits set. */
611                         configASSERT( pxTasksWaitingForBits->xListEnd.pxNext != ( const ListItem_t * ) &( pxTasksWaitingForBits->xListEnd ) );
612                         vTaskRemoveFromUnorderedEventList( pxTasksWaitingForBits->xListEnd.pxNext, eventUNBLOCKED_DUE_TO_BIT_SET );
613                 }
614
615                 #if( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 0 ) )
616                 {
617                         /* The event group can only have been allocated dynamically - free
618                         it again. */
619                         vPortFree( pxEventBits );
620                 }
621                 #elif( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) )
622                 {
623                         /* The event group could have been allocated statically or
624                         dynamically, so check before attempting to free the memory. */
625                         if( pxEventBits->ucStaticallyAllocated == ( uint8_t ) pdFALSE )
626                         {
627                                 vPortFree( pxEventBits );
628                         }
629                         else
630                         {
631                                 mtCOVERAGE_TEST_MARKER();
632                         }
633                 }
634                 #endif /* configSUPPORT_DYNAMIC_ALLOCATION */
635         }
636         ( void ) xTaskResumeAll();
637 }
638 /*-----------------------------------------------------------*/
639
640 /* For internal use only - execute a 'set bits' command that was pended from
641 an interrupt. */
642 void vEventGroupSetBitsCallback( void *pvEventGroup, const uint32_t ulBitsToSet )
643 {
644         ( void ) xEventGroupSetBits( pvEventGroup, ( EventBits_t ) ulBitsToSet );
645 }
646 /*-----------------------------------------------------------*/
647
648 /* For internal use only - execute a 'clear bits' command that was pended from
649 an interrupt. */
650 void vEventGroupClearBitsCallback( void *pvEventGroup, const uint32_t ulBitsToClear )
651 {
652         ( void ) xEventGroupClearBits( pvEventGroup, ( EventBits_t ) ulBitsToClear );
653 }
654 /*-----------------------------------------------------------*/
655
656 static BaseType_t prvTestWaitCondition( const EventBits_t uxCurrentEventBits, const EventBits_t uxBitsToWaitFor, const BaseType_t xWaitForAllBits )
657 {
658 BaseType_t xWaitConditionMet = pdFALSE;
659
660         if( xWaitForAllBits == pdFALSE )
661         {
662                 /* Task only has to wait for one bit within uxBitsToWaitFor to be
663                 set.  Is one already set? */
664                 if( ( uxCurrentEventBits & uxBitsToWaitFor ) != ( EventBits_t ) 0 )
665                 {
666                         xWaitConditionMet = pdTRUE;
667                 }
668                 else
669                 {
670                         mtCOVERAGE_TEST_MARKER();
671                 }
672         }
673         else
674         {
675                 /* Task has to wait for all the bits in uxBitsToWaitFor to be set.
676                 Are they set already? */
677                 if( ( uxCurrentEventBits & uxBitsToWaitFor ) == uxBitsToWaitFor )
678                 {
679                         xWaitConditionMet = pdTRUE;
680                 }
681                 else
682                 {
683                         mtCOVERAGE_TEST_MARKER();
684                 }
685         }
686
687         return xWaitConditionMet;
688 }
689 /*-----------------------------------------------------------*/
690
691 #if ( ( configUSE_TRACE_FACILITY == 1 ) && ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) )
692
693         BaseType_t xEventGroupSetBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet, BaseType_t *pxHigherPriorityTaskWoken )
694         {
695         BaseType_t xReturn;
696
697                 traceEVENT_GROUP_SET_BITS_FROM_ISR( xEventGroup, uxBitsToSet );
698                 xReturn = xTimerPendFunctionCallFromISR( vEventGroupSetBitsCallback, ( void * ) xEventGroup, ( uint32_t ) uxBitsToSet, pxHigherPriorityTaskWoken );
699
700                 return xReturn;
701         }
702
703 #endif
704 /*-----------------------------------------------------------*/
705
706 #if (configUSE_TRACE_FACILITY == 1)
707
708         UBaseType_t uxEventGroupGetNumber( void* xEventGroup )
709         {
710         UBaseType_t xReturn;
711         EventGroup_t *pxEventBits = ( EventGroup_t * ) xEventGroup;
712
713                 if( xEventGroup == NULL )
714                 {
715                         xReturn = 0;
716                 }
717                 else
718                 {
719                         xReturn = pxEventBits->uxEventGroupNumber;
720                 }
721
722                 return xReturn;
723         }
724
725 #endif /* configUSE_TRACE_FACILITY */
726 /*-----------------------------------------------------------*/
727
728 #if ( configUSE_TRACE_FACILITY == 1 )
729
730         void vEventGroupSetNumber( void * xEventGroup, UBaseType_t uxEventGroupNumber )
731         {
732                 ( ( EventGroup_t * ) xEventGroup )->uxEventGroupNumber = uxEventGroupNumber;
733         }
734
735 #endif /* configUSE_TRACE_FACILITY */
736 /*-----------------------------------------------------------*/
737
738