1 /* pthread_barrier_wait.  Generic version.
2    Copyright (C) 2002-2022 Free Software Foundation, Inc.
3    This file is part of the GNU C Library.
4 
5    The GNU C Library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public
7    License as published by the Free Software Foundation; either
8    version 2.1 of the License, or (at your option) any later version.
9 
10    The GNU C Library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Lesser General Public License for more details.
14 
15    You should have received a copy of the GNU Lesser General Public
16    License along with the GNU C Library;  if not, see
17    <https://www.gnu.org/licenses/>.  */
18 
19 #include <pthread.h>
20 #include <assert.h>
21 
22 #include <pt-internal.h>
23 
24 int
pthread_barrier_wait(pthread_barrier_t * barrier)25 pthread_barrier_wait (pthread_barrier_t *barrier)
26 {
27   __pthread_spin_wait (&barrier->__lock);
28   if (--barrier->__pending == 0)
29     {
30       barrier->__pending = barrier->__count;
31 
32       if (barrier->__count == 1)
33 	__pthread_spin_unlock (&barrier->__lock);
34       else
35 	{
36 	  struct __pthread *wakeup;
37 	  unsigned n = 0;
38 
39 	  __pthread_queue_iterate (barrier->__queue, wakeup)
40 	    n++;
41 
42 	  {
43 	    struct __pthread *wakeups[n];
44 	    unsigned i = 0;
45 
46 	    __pthread_dequeuing_iterate (barrier->__queue, wakeup)
47 	      wakeups[i++] = wakeup;
48 
49 	    barrier->__queue = NULL;
50 	    __pthread_spin_unlock (&barrier->__lock);
51 
52 	    for (i = 0; i < n; i++)
53 	      __pthread_wakeup (wakeups[i]);
54 	  }
55 	}
56 
57       return PTHREAD_BARRIER_SERIAL_THREAD;
58     }
59   else
60     {
61       struct __pthread *self = _pthread_self ();
62 
63       /* Add ourselves to the list of waiters.  */
64       __pthread_enqueue (&barrier->__queue, self);
65       __pthread_spin_unlock (&barrier->__lock);
66 
67       __pthread_block (self);
68       return 0;
69     }
70 }
71