]> git.sur5r.net Git - freertos/blob - FreeRTOS-Labs/Demo/FreeRTOS_Plus_POSIX_with_actor_Windows_Simulator/lib/FreeRTOS-Plus-POSIX/source/FreeRTOS_POSIX_pthread_barrier.c
Add the Labs projects provided in the V10.2.1_191129 zip file.
[freertos] / FreeRTOS-Labs / Demo / FreeRTOS_Plus_POSIX_with_actor_Windows_Simulator / lib / FreeRTOS-Plus-POSIX / source / FreeRTOS_POSIX_pthread_barrier.c
1 /*\r
2  * Amazon FreeRTOS POSIX V1.1.0\r
3  * Copyright (C) 2018 Amazon.com, Inc. or its affiliates.  All Rights Reserved.\r
4  *\r
5  * Permission is hereby granted, free of charge, to any person obtaining a copy of\r
6  * this software and associated documentation files (the "Software"), to deal in\r
7  * the Software without restriction, including without limitation the rights to\r
8  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\r
9  * the Software, and to permit persons to whom the Software is furnished to do so,\r
10  * subject to the following conditions:\r
11  *\r
12  * The above copyright notice and this permission notice shall be included in all\r
13  * copies or substantial portions of the Software.\r
14  *\r
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\r
17  * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\r
18  * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r
19  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
20  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
21  *\r
22  * http://aws.amazon.com/freertos\r
23  * http://www.FreeRTOS.org\r
24  */\r
25 \r
26 /**\r
27  * @file FreeRTOS_POSIX_pthread_barrier.c\r
28  * @brief Implementation of barrier functions in pthread.h\r
29  */\r
30 \r
31 /* C standard library includes. */\r
32 #include <stddef.h>\r
33 \r
34 /* FreeRTOS+POSIX includes. */\r
35 #include "FreeRTOS_POSIX.h"\r
36 #include "FreeRTOS_POSIX/errno.h"\r
37 #include "FreeRTOS_POSIX/pthread.h"\r
38 \r
39 #include "atomic.h"\r
40 \r
41 /*\r
42  * @brief barrier max count\r
43  *\r
44  * Barriers are implemented on FreeRTOS event groups, of which 8 bits are usable\r
45  * when configUSE_16_BIT_TICKS is 1. Otherwise, 24 bits are usable.\r
46  */\r
47 /**@{ */\r
48 #if ( configUSE_16_BIT_TICKS == 1 )\r
49     #define posixPTHREAD_BARRIER_MAX_COUNT    ( 8 )\r
50 #else\r
51     #define posixPTHREAD_BARRIER_MAX_COUNT    ( 24 )\r
52 #endif\r
53 /**@} */\r
54 \r
55 /*-----------------------------------------------------------*/\r
56 \r
57 int pthread_barrier_destroy( pthread_barrier_t * barrier )\r
58 {\r
59     pthread_barrier_internal_t * pxBarrier = ( pthread_barrier_internal_t * ) ( barrier );\r
60 \r
61     /* Free all resources used by the barrier. */\r
62     ( void ) vEventGroupDelete( ( EventGroupHandle_t ) &pxBarrier->xBarrierEventGroup );\r
63     ( void ) vSemaphoreDelete( ( SemaphoreHandle_t ) &pxBarrier->xThreadCountSemaphore );\r
64 \r
65     return 0;\r
66 }\r
67 \r
68 /*-----------------------------------------------------------*/\r
69 \r
70 int pthread_barrier_init( pthread_barrier_t * barrier,\r
71                           const pthread_barrierattr_t * attr,\r
72                           unsigned count )\r
73 {\r
74     int iStatus = 0;\r
75     pthread_barrier_internal_t * pxNewBarrier = ( pthread_barrier_internal_t * ) ( barrier );\r
76 \r
77     /* Silence warnings about unused parameters. */\r
78     ( void ) attr;\r
79 \r
80     /* Ensure count is greater than 0. */\r
81     if( count == 0 )\r
82     {\r
83         iStatus = EINVAL;\r
84     }\r
85 \r
86     /* Ensure that count will fit in a FreeRTOS event group. */\r
87     if( iStatus == 0 )\r
88     {\r
89         if( count > posixPTHREAD_BARRIER_MAX_COUNT )\r
90         {\r
91             /* No memory exists in the event group for more than\r
92              * posixPTHREAD_BARRIER_MAX_COUNT threads. */\r
93             iStatus = ENOMEM;\r
94         }\r
95     }\r
96 \r
97     if( iStatus == 0 )\r
98     {\r
99         /* Set the current thread count and threshold. */\r
100         pxNewBarrier->uThreadCount = 0;\r
101         pxNewBarrier->uThreshold = count;\r
102 \r
103         /* Create the FreeRTOS event group. This call will not fail when its\r
104          * argument isn't NULL. */\r
105         ( void ) xEventGroupCreateStatic( &pxNewBarrier->xBarrierEventGroup );\r
106 \r
107         /* Create the semaphore that prevents more than count threads from being\r
108          * unblocked by a single successful pthread_barrier_wait. This semaphore\r
109          * counts down from count and cannot decrement below 0. */\r
110         ( void ) xSemaphoreCreateCountingStatic( ( UBaseType_t ) count, /* Max count. */\r
111                                                  ( UBaseType_t ) count, /* Initial count. */\r
112                                                  &pxNewBarrier->xThreadCountSemaphore );\r
113     }\r
114 \r
115     return iStatus;\r
116 }\r
117 \r
118 /*-----------------------------------------------------------*/\r
119 \r
120 int pthread_barrier_wait( pthread_barrier_t * barrier )\r
121 {\r
122     int iStatus = 0;\r
123     unsigned i = 0; /* Loop iterator. */\r
124     pthread_barrier_internal_t * pxBarrier = ( pthread_barrier_internal_t * ) ( barrier );\r
125     unsigned uThreadNumber = 0;\r
126 \r
127     /* Decrement the number of threads waiting on this barrier. This will prevent more\r
128      * than pxBarrier->uThreshold threads from being unblocked by a single successful\r
129      * pthread_barrier_wait call.\r
130      *\r
131      * This call will never fail because it blocks forever.\r
132      */\r
133     ( void ) xSemaphoreTake( ( SemaphoreHandle_t ) &pxBarrier->xThreadCountSemaphore, portMAX_DELAY );\r
134 \r
135     uThreadNumber = Atomic_Increment_u32( ( uint32_t * ) &pxBarrier->uThreadCount );\r
136 \r
137     /* Set the bit in the event group representing this thread, then wait for the other\r
138      * threads to set their bit. This call should wait forever until all threads have set\r
139      * their bit, so the return value is ignored. */\r
140     ( void ) xEventGroupSync( ( EventGroupHandle_t ) &pxBarrier->xBarrierEventGroup,\r
141                               1 << uThreadNumber,                 /* Which bit in the event group to set. */\r
142                               ( 1 << pxBarrier->uThreshold ) - 1, /* Wait for all threads to set their bits. */\r
143                               portMAX_DELAY );\r
144 \r
145     /* The first thread to enter the barrier gets PTHREAD_BARRIER_SERIAL_THREAD as its\r
146      * return value and resets xThreadCountSemaphore. */\r
147 \r
148     if( uThreadNumber == 0 )\r
149     {\r
150         iStatus = PTHREAD_BARRIER_SERIAL_THREAD;\r
151 \r
152         /* uThreadCount can be safely changed without locking xThreadCountMutex\r
153          * because xThreadCountSemaphore is currently 0. */\r
154         pxBarrier->uThreadCount = 0;\r
155 \r
156         /* Reset xThreadCountSemaphore. This allows more threads to enter the\r
157          * barrier, starting a new cycle. */\r
158         for( i = 0; i < pxBarrier->uThreshold; i++ )\r
159         {\r
160             xSemaphoreGive( ( SemaphoreHandle_t ) &pxBarrier->xThreadCountSemaphore );\r
161         }\r
162     }\r
163 \r
164     return iStatus;\r
165 }\r