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@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 45static INLINE int 46ptw32_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 152int 153pthread_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 194int 195pthread_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