Home | History | Annotate | Download | only in pthreads-win32
      1 /*
      2  * pthread_cond_signal.c
      3  *
      4  * Description:
      5  * This translation unit implements condition variables and their primitives.
      6  *
      7  *
      8  * --------------------------------------------------------------------------
      9  *
     10  *      Pthreads-win32 - POSIX Threads Library for Win32
     11  *      Copyright(C) 1998 John E. Bossom
     12  *      Copyright(C) 1999,2005 Pthreads-win32 contributors
     13  *
     14  *      Contact Email: rpj (at) callisto.canberra.edu.au
     15  *
     16  *      The current list of contributors is contained
     17  *      in the file CONTRIBUTORS included with the source
     18  *      code distribution. The list can also be seen at the
     19  *      following World Wide Web location:
     20  *      http://sources.redhat.com/pthreads-win32/contributors.html
     21  *
     22  *      This library is free software; you can redistribute it and/or
     23  *      modify it under the terms of the GNU Lesser General Public
     24  *      License as published by the Free Software Foundation; either
     25  *      version 2 of the License, or (at your option) any later version.
     26  *
     27  *      This library is distributed in the hope that it will be useful,
     28  *      but WITHOUT ANY WARRANTY; without even the implied warranty of
     29  *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     30  *      Lesser General Public License for more details.
     31  *
     32  *      You should have received a copy of the GNU Lesser General Public
     33  *      License along with this library in the file COPYING.LIB;
     34  *      if not, write to the Free Software Foundation, Inc.,
     35  *      59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
     36  *
     37  * -------------------------------------------------------------
     38  * Algorithm:
     39  * See the comments at the top of pthread_cond_wait.c.
     40  */
     41 
     42 #include "pthread.h"
     43 #include "implement.h"
     44 
     45 static INLINE int
     46 ptw32_cond_unblock (pthread_cond_t * cond, int unblockAll)
     47      /*
     48       * Notes.
     49       *
     50       * Does not use the external mutex for synchronisation,
     51       * therefore semBlockLock is needed.
     52       * mtxUnblockLock is for LEVEL-2 synch. LEVEL-2 is the
     53       * state where the external mutex is not necessarily locked by
     54       * any thread, ie. between cond_wait unlocking and re-acquiring
     55       * the lock after having been signaled or a timeout or
     56       * cancellation.
     57       *
     58       * Uses the following CV elements:
     59       *   nWaitersBlocked
     60       *   nWaitersToUnblock
     61       *   nWaitersGone
     62       *   mtxUnblockLock
     63       *   semBlockLock
     64       *   semBlockQueue
     65       */
     66 {
     67   int result;
     68   pthread_cond_t cv;
     69   int nSignalsToIssue;
     70 
     71   if (cond == NULL || *cond == NULL)
     72     {
     73       return EINVAL;
     74     }
     75 
     76   cv = *cond;
     77 
     78   /*
     79    * No-op if the CV is static and hasn't been initialised yet.
     80    * Assuming that any race condition is harmless.
     81    */
     82   if (cv == PTHREAD_COND_INITIALIZER)
     83     {
     84       return 0;
     85     }
     86 
     87   if ((result = pthread_mutex_lock (&(cv->mtxUnblockLock))) != 0)
     88     {
     89       return result;
     90     }
     91 
     92   if (0 != cv->nWaitersToUnblock)
     93     {
     94       if (0 == cv->nWaitersBlocked)
     95 	{
     96 	  return pthread_mutex_unlock (&(cv->mtxUnblockLock));
     97 	}
     98       if (unblockAll)
     99 	{
    100 	  cv->nWaitersToUnblock += (nSignalsToIssue = cv->nWaitersBlocked);
    101 	  cv->nWaitersBlocked = 0;
    102 	}
    103       else
    104 	{
    105 	  nSignalsToIssue = 1;
    106 	  cv->nWaitersToUnblock++;
    107 	  cv->nWaitersBlocked--;
    108 	}
    109     }
    110   else if (cv->nWaitersBlocked > cv->nWaitersGone)
    111     {
    112       /* Use the non-cancellable version of sem_wait() */
    113       if (ptw32_semwait (&(cv->semBlockLock)) != 0)
    114 	{
    115 	  result = errno;
    116 	  (void) pthread_mutex_unlock (&(cv->mtxUnblockLock));
    117 	  return result;
    118 	}
    119       if (0 != cv->nWaitersGone)
    120 	{
    121 	  cv->nWaitersBlocked -= cv->nWaitersGone;
    122 	  cv->nWaitersGone = 0;
    123 	}
    124       if (unblockAll)
    125 	{
    126 	  nSignalsToIssue = cv->nWaitersToUnblock = cv->nWaitersBlocked;
    127 	  cv->nWaitersBlocked = 0;
    128 	}
    129       else
    130 	{
    131 	  nSignalsToIssue = cv->nWaitersToUnblock = 1;
    132 	  cv->nWaitersBlocked--;
    133 	}
    134     }
    135   else
    136     {
    137       return pthread_mutex_unlock (&(cv->mtxUnblockLock));
    138     }
    139 
    140   if ((result = pthread_mutex_unlock (&(cv->mtxUnblockLock))) == 0)
    141     {
    142       if (sem_post_multiple (&(cv->semBlockQueue), nSignalsToIssue) != 0)
    143 	{
    144 	  result = errno;
    145 	}
    146     }
    147 
    148   return result;
    149 
    150 }				/* ptw32_cond_unblock */
    151 
    152 int
    153 pthread_cond_signal (pthread_cond_t * cond)
    154      /*
    155       * ------------------------------------------------------
    156       * DOCPUBLIC
    157       *      This function signals a condition variable, waking
    158       *      one waiting thread.
    159       *      If SCHED_FIFO or SCHED_RR policy threads are waiting
    160       *      the highest priority waiter is awakened; otherwise,
    161       *      an unspecified waiter is awakened.
    162       *
    163       * PARAMETERS
    164       *      cond
    165       *              pointer to an instance of pthread_cond_t
    166       *
    167       *
    168       * DESCRIPTION
    169       *      This function signals a condition variable, waking
    170       *      one waiting thread.
    171       *      If SCHED_FIFO or SCHED_RR policy threads are waiting
    172       *      the highest priority waiter is awakened; otherwise,
    173       *      an unspecified waiter is awakened.
    174       *
    175       *      NOTES:
    176       *
    177       *      1)      Use when any waiter can respond and only one need
    178       *              respond (all waiters being equal).
    179       *
    180       * RESULTS
    181       *              0               successfully signaled condition,
    182       *              EINVAL          'cond' is invalid,
    183       *
    184       * ------------------------------------------------------
    185       */
    186 {
    187   /*
    188    * The '0'(FALSE) unblockAll arg means unblock ONE waiter.
    189    */
    190   return (ptw32_cond_unblock (cond, 0));
    191 
    192 }				/* pthread_cond_signal */
    193 
    194 int
    195 pthread_cond_broadcast (pthread_cond_t * cond)
    196      /*
    197       * ------------------------------------------------------
    198       * DOCPUBLIC
    199       *      This function broadcasts the condition variable,
    200       *      waking all current waiters.
    201       *
    202       * PARAMETERS
    203       *      cond
    204       *              pointer to an instance of pthread_cond_t
    205       *
    206       *
    207       * DESCRIPTION
    208       *      This function signals a condition variable, waking
    209       *      all waiting threads.
    210       *
    211       *      NOTES:
    212       *
    213       *      1)      Use when more than one waiter may respond to
    214       *              predicate change or if any waiting thread may
    215       *              not be able to respond
    216       *
    217       * RESULTS
    218       *              0               successfully signalled condition to all
    219       *                              waiting threads,
    220       *              EINVAL          'cond' is invalid
    221       *              ENOSPC          a required resource has been exhausted,
    222       *
    223       * ------------------------------------------------------
    224       */
    225 {
    226   /*
    227    * The TRUE unblockAll arg means unblock ALL waiters.
    228    */
    229   return (ptw32_cond_unblock (cond, PTW32_TRUE));
    230 
    231 }				/* pthread_cond_broadcast */
    232