(linenum→info "unix/slp.c:2238")

glibc/2.7/nptl/pthread_barrier_wait.c

    1: /* Copyright (C) 2003, 2004, 2007 Free Software Foundation, Inc.
    2:    This file is part of the GNU C Library.
    3:    Contributed by Martin Schwidefsky <schwidefsky@de.ibm.com>, 2003.
    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, write to the Free
   17:    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
   18:    02111-1307 USA.  */
   19: 
   20: #include <errno.h>
   21: #include <sysdep.h>
   22: #include <lowlevellock.h>
   23: #include <pthreadP.h>
   24: 
   25: 
   26: /* Wait on barrier.  */
   27: int
   28: pthread_barrier_wait (barrier)
   29:      pthread_barrier_t *barrier;
   30: {
   31:   struct pthread_barrier *ibarrier = (struct pthread_barrier *) barrier;
   32:   int result = 0;
   33: 
   34:   /* Make sure we are alone.  */
   35:   lll_lock (ibarrier->lock, ibarrier->private ^ FUTEX_PRIVATE_FLAG);
   36: 
   37:   /* One more arrival.  */
   38:   --ibarrier->left;
   39: 
   40:   /* Are these all?  */
   41:   if (ibarrier->left == 0)
   42:     {
   43:       /* Yes. Increment the event counter to avoid invalid wake-ups and
   44:          tell the current waiters that it is their turn.  */
   45:       ++ibarrier->curr_event;
   46: 
   47:       /* Wake up everybody.  */
   48:       lll_futex_wake (&ibarrier->curr_event, INT_MAX,
   49:                       ibarrier->private ^ FUTEX_PRIVATE_FLAG);
   50: 
   51:       /* This is the thread which finished the serialization.  */
   52:       result = PTHREAD_BARRIER_SERIAL_THREAD;
   53:     }
   54:   else
   55:     {
   56:       /* The number of the event we are waiting for.  The barrier's event
   57:          number must be bumped before we continue.  */
   58:       unsigned int event = ibarrier->curr_event;
   59: 
   60:       /* Before suspending, make the barrier available to others.  */
   61:       lll_unlock (ibarrier->lock, ibarrier->private ^ FUTEX_PRIVATE_FLAG);
   62: 
   63:       /* Wait for the event counter of the barrier to change.  */
   64:       do
   65:         lll_futex_wait (&ibarrier->curr_event, event,
   66:                         ibarrier->private ^ FUTEX_PRIVATE_FLAG);
   67:       while (event == ibarrier->curr_event);
   68:     }
   69: 
   70:   /* Make sure the init_count is stored locally or in a register.  */
   71:   unsigned int init_count = ibarrier->init_count;
   72: 
   73:   /* If this was the last woken thread, unlock.  */
   74:   if (atomic_increment_val (&ibarrier->left) == init_count)
   75:     /* We are done.  */
   76:     lll_unlock (ibarrier->lock, ibarrier->private ^ FUTEX_PRIVATE_FLAG);
   77: 
   78:   return result;
   79: }
Syntax (Markdown)